记一次hook mac地址实现伪装硬件码

1. 前言

好久没写文章了,工作比较忙,不过我还是对技术比较热爱,即使它不能给我带来利益,保持初心。

工作期间遇到一个问题,连接vpn的软件是校验机器硬件码,不是公司电脑不让使用vpn软件,上下班已经让我搞得筋疲力尽了,我不想每天背个电脑回家,这还怎么让我在家愉快的加班?

2. 分析

首先,我能想到硬件码当然是mac地址,为了验证我自己的想法,我需要将mac地址设置成与公司电脑mac地址相同的地址。

这里windows 上有简单的修改mac地址的方法,通过修改注册表,简单来说就是给注册表增加选项,让网络地址可以配置。

正常无线网卡是没有 “网络地址” 这个配置项的,是通过注册表增加实现的这个配置项。

不过这里有限制,就是mac 地址的第二位必须为固定的一些值,这是受到系统的限制,看网上说xp系统是没有限制的,不过我不可能去换xp系统的。

无奈,我需要快速验证到底是不是根据mac地址生成的硬件码,因为如果不是 mac地址生成的硬件码,我后续的工作无法进行下去。

这里采用简单粗暴的方法,直接使用虚拟机

然后装上对应的vpn 软件,功夫不负有心人,果然是mac地址生成的硬件码。

3. 大胆猜测

知道了修改mac地址就可以实现伪装硬件码后,后面的思路就是如何 让软件读取到假的mac地址,我猜测 vpn 软件是通过windows 的api 来读取 mac 地址的,简单的百度一下发现 GetAdaptersInfo这个函数,其在 Iphlpapi.dll

简单用frida 验证一下 vpn 软件是否调度到了 GetAdaptersInfo 这个函数:

frida-trace -i "GetAdaptersInfo" "软件完整地址"

输出:

GetAdaptersInfo: Loaded handler at "C:\\Users\\pc\\Desktop\\__handlers__\\IPHLPAPI.DLL\\GetAdaptersInfo.js"
Started tracing 1 function. Press Ctrl+C to stop.
/* TID 0x3cf8 */
2948 ms 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0f4ee254 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee264 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee274 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee284 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee294 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee2a4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee2b4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee2c4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee2d4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee2e4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee2f4 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee304 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee314 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee324 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee334 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0f4ee344 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
2948 ms GetAdaptersInfo()

可以看到软件确实调用到了 GetAdaptersInfo 这个函数。

这里要注意一个问题,启动cmd时要用 管理员权限 启动,否者hook不到。

4. 分析GetAdaptersInfo函数

DWOED GetAdaptersInfo(

PIP_ADAPTER_INFO pAdapterInfo;

PULONG pOutBufLen;

);

函数有俩个参数,第一个参数是 PIP_ADAPTER_INFO 类型的指针,最终结果也存储在 第一个参数里面。

第二个参数是一个长度,是一个整数型指针。

返回值也是一个整数表示是否获取成功。

简单一个程序,获取mac及网络地址的代码:

#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#pragma comment(lib,"Iphlpapi.lib")
int main()
{
// 初始化winsock
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pAdapter = NULL;
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = (PIP_ADAPTER_INFO)malloc(ulOutBufLen);
DWORD dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
// 第一次调用GetAdapterInfo获取ulOutBufLen大小
if (dwRetVal == ERROR_BUFFER_OVERFLOW)
{
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO*)malloc(ulOutBufLen);
dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
}
if (dwRetVal == NO_ERROR)
{
pAdapter = pAdapterInfo;
while (pAdapter)
{
printf("Adapter Name: \t%s\n", pAdapter->AdapterName);
printf("Adapter Desc: \t%s\n", pAdapter->Description);
printf("MAC Addr: \t%02x-%02x-%02x-%02x-%02x-%02x\n",
pAdapter->Address[0],
pAdapter->Address[1],
pAdapter->Address[2],
pAdapter->Address[3],
pAdapter->Address[4],
pAdapter->Address[5]);
printf("IP Address: \t%s\n", pAdapter->IpAddressList.IpAddress.String);
printf("IP Mask: \t%s\n", pAdapter->IpAddressList.IpMask.String);
printf("Gateway: \t%s\n", pAdapter->GatewayList.IpAddress.String);
pAdapter = pAdapter->Next;
}// end while
}
else
{
printf("Call to GetAdaptersInfo failed.\n");
}
if (pAdapterInfo != NULL)
{
free(pAdapterInfo); //释放资源
}
return 0;
} //end main

简单调试一下这个程序:

可以看到 第一个参数 是一个结构体,有点像 链表的数据结构,每次使用 Next 来调度到下一块内存,存储的也是下一块网卡信息(包括虚拟网卡)。而我们需要的Mac 地址就存放在 Address 这个字段中。

因为 frida 脚本我还不知道如果调度结构体,所以这里通过偏移值来修改的(如果有方法,还请评论区大佬教我)。

这里需要注意调试时是x86来调试,因为vpn软件是32位的。

算一下mac(Address) 地址针对 pAdapterInfo 偏移值:

>>> 0x0087f19c-0x0087f008
404
>>>

next 针对 pAdapterInfo 偏移值:

>>> 0x0087f288-0x0087f008
640
>>>

5. 编写 frida 脚本

这里有一个难点,如何在函数结束的时候 改变其内存值,hook脚本 onLeave中的参数是返回值,而不是函数的参数,这里可以在 onEnter 对第一个参数this绑定,这样 onLeave 时就可以调到这个指针了

var writeFile = Module.getExportByName(null, "GetAdaptersInfo");

Interceptor.attach(writeFile, {
onEnter: function(args)
{
this.data = args[0] //动态绑定第一个参数到 this,为了在函数返回是修改
},
onLeave:function(ret){
// 1280
// 640
console.log(Memory.readByteArray(ptr(this.data.add(404)), 6)) //输出第一块网卡mac地址
console.log(Memory.readByteArray(ptr(this.data.add(1044)), 6)) // +640结构体偏移,获得下一块网卡mac地址
Memory.writeByteArray(ptr(this.data.add(1684)),[0x01,0x02,0x03,0x04,0x05,0x06]) // 写入第三块网卡mac地址
}
});

启动命令(cmd管理员权限):

frida "软件路径" -l C:\Users\pc\Desktop\hooking.js --no-pause

6. 后记

通过这个案例解决了我实际的问题,这个东西前前后后弄了一周 (工作时间除外),从刚开始有这个想法,到一步一步分析验证。东西做出来后也有很大的成就感。针对逆向这方面我是个小白,很多东西都是现查的。

有一些感想:保持清晰思路,大胆猜想,小心验证,保证你逻辑每一步都正确,最后的结果肯定是符合预期的,这就叫合理吧。

记一次hook mac地址实现伪装硬件码的相关教程结束。

相关推荐:

如何在 Flask 应用中实现多网卡 IP 地址监听(生产环境推荐方案)

Flask内置开发服务器不支持同时绑定多个IP地址,且严禁用于生产环境;实现多网卡高可用监听需改用专业WSGI服务器(如Gunicorn),通过多--bind参数绑定不同IP,达成简单故障转移能力。 flask内置开发服务器不支持同时绑定多个ip地址,且严禁用于生产环境;实现多网卡高可用监听需改用专...

如何在 Flask 应用中实现多 IP 地址监听(生产环境推荐方案)

Flask内置开发服务器不支持同时绑定多个IP地址;如需实现双网卡高可用监听,必须改用生产级WSGI服务器(如Gunicorn),通过多--bind参数实现多地址监听。 flask内置开发服务器不支持同时绑定多个ip地址;如需实现双网卡高可用监听,必须改用生产级wsgi服务器(如gunicorn),...

Python监控CPU使用率自动降频_subprocess调用硬件接口

调用cpupower失败主因是权限不足或路径未找到,应使用绝对路径并配置免密sudo;psutil.cpu_percent()需先预热调用,再设合理间隔;降频逻辑需加滑动窗口防抖,避免频繁切换。 subprocess调用cpupower失败:权限和路径问题最常见 直接用subprocess.run(...

Python哈希冲突怎么解决_链地址法与开放寻址法代码演示

Python内置dict和set采用开放寻址法而非链地址法,通过探测序列寻找空槽;手动实现链地址法需用列表存桶,开放寻址法则需DELETE标记处理删除。 哈希冲突发生时,dict和set实际用的是链地址法 Python内置的dict和set在底层C实现中采用的是**开放寻址法(openaddress...

Python id()函数怎么用_获取对象内存地址与同一性比较

id()返回对象在内存中的唯一标识整数,在CPython中是地址,但仅当前运行期有效,不可用于指针运算;主要用于调试、元编程和对象身份快照,而非替代is。 id()返回的是什么地址?不是C语言那种可直接操作的指针 id()返回的是一个整数,在CPython中它确实是对象在内存中的地址(即&o...

Python身份运算符是什么_is与==的区别及内存地址比较

is判断对象是否为同一内存地址,用于None/单例等恒等性比较;==比较值相等,依赖__eq__方法,适用于常规数据比对。 is判断的是不是同一个对象 Python中is不是比较值,而是检查两个变量是否指向**同一块内存地址**。这在判断单例、None、小整数或短字符串时特别关键——因为它们可能被缓...

Python怎么在Mac上开发_macOS自带Python与Homebrew管理

不能动macOS系统自带的/usr/bin/python3,因其受SIP保护,强行修改会导致系统功能异常;应使用Homebrew安装Python并优先配置$PATH,再用其python3-mvenv创建虚拟环境。 macOS自带Python为什么不能乱动 系统自带的python3(macOS12+默...