PC微信逆向:使用HOOK拦截二维码
2019-08-10 07:51:01 Author: mp.weixin.qq.com(查看原文) 阅读量:51 收藏

本文作者:鬼手56(信安之路病毒分析小组成员 & 信安之路 2019 年度优秀作者)

成员招募:信安之路病毒分析小组寻找志同道合的朋友

当前微信版本

寻找微信二维码基址

PNG 文件格式

微信二维码在内存中存放形式是 png 格式的二进制数据,所以我们需要眼熟一下 png 的文件格式,如图

前 32 个字节是固定的,分别是 btPngSignature 和 struct PNG_CHUNK chunk 结构,其中保存有 png 图片的标识。

其中 NG 和 IHDR 是每个 PNG 文件都会有的标识,眼熟一下就好。微信的二维码图片就是通过这种格式在内存中存放

使用 CE 过滤基址

首先在微信未登录状态下附加微信,此时二维码还未加载

然后选择未知的数值,点击首次扫描

出现三百万个结果

此时我们再次点击切换账号,出现二维码,让保存二维码的地址被赋值

然后选择变动的数值 再次扫描

此时还剩下七万个结果

然后用手机扫描二维码 不要点击登录,再次扫描变动的数值,此时还剩三万多个结果

接着随意移动微信框,点击未变动的数值,还剩一万多个结果。返回二维码登录重复以上操作,直到地址栏还剩下两个绿色的基址,这两个绿色的基址就是我们要的。

因为随机基址的存在,这个地址在各位的电脑上是不一样的。但是低四位是一致的,这两个地址应该是 xxxx9194 和 xxxx919C。

使用 OD 确定二维码基址

然后重启一次微信,再用 CE 附加,回到这个状态

用 OD 附加微信,在找到的第一个地址 xxxx9194 下内存写入断点

点击切换账号,在二维码未加载时程序会断下。注意,这个地方会断下来两次,第二次才是我们要的结果。

因为二维码是存放在微信的核心模块 WeChatWin 中的,所以我们在堆栈中找到所有的 WeChatWin 中的函数

像这种 API 的调用就可以直接排除掉,然后在每一个疑似函数上下断点。找的时候堆栈尽量往下拉,这个函数会比较靠后。

因为我已经找过一遍了,所以直接告诉你们是这一个。特征是有一个 ecx 传参。

接着在这个函数上下断点,删除内存访问断点,F9 运行

然后扫一下二维码,点击返回二维码登录,程序断下

此时观察 ecx 指针的内容,明显是一个结构体,结构体的第一个是地址,第二个好像是大小。然后在这个地址上数据窗口跟随

里面是 PNG 文件的二进制数据,这个就是我们要找的微信二维码的基址

验证二维码基址

打开 PCHunter,选择微信进程,查看->查看进程内存,输入地址和大小,然后将内存 dump 下来

打开图片

现在已经确定就是我们需要的二维码。然后我们将这个 call 的地址减去模块基址,记录下偏移。待会需要 HOOK 这个 call

寻找微信二维码内容的基址

微信二维码的存储内容

二维码其实是一种开放性的信息存储器,它将固定的信息存储在自己的黑白小方块之间。大部分的二维码都有一个特点,就是里面存放的其实是一段文本。我们可以利用这个文本来寻找突破口

将微信的二维码截图保存,然后用在线的二维码解码器解析微信的二维码

可以看到解码之后的结果是一段网址

使用 CE 寻找二维码内容的基址

如果直接搜索这段网址是找不到任何结果的,原因是因为微信在保存这段位置的时候,实际上是将它分为了两部分存储

第一部分的固定不变的,第二部分被当作一个参数传入,客户端从服务器获取的只是第二部分的内容。所以我们去搜索第二部分。

另外,微信的二维码会定时刷新,刷新的时候会改变第二部分的内容。如果你搜不到的话可能是因为之前的文本已经失效了。从解析文本到搜索文本最好在一分钟之内完成

此时 我们直接搜索第二部分的文本

搜索完成之后,等待二维码自动刷新,然后找到那个变化之后的地址,用截图上传的方式确保找到的是正确的地址

然后用 OD 附加微信,在找到的地址上下内存写入断点

等待二维码自动刷新,二维码刷新时会往原来存放二维码的地址写入新的二维码数据,程序就会断下

此时 eax 指向二维码的文本内容,我们找到堆栈中的第一个地址,在数据窗口显示,此时就能找到存放微信二维码数据的基址了

然后我们在 CE 中添加 WeChatWin.dll 模块,找到模块基址,算出偏移(用 0x104CF618-0xF250000=127F618)。然后将这个地址换成模块基址+偏移的方式添加到 CE 地址栏。

验证基址

重新打开微信,用 CE 载入

保留当前列表,然后将二维码内容指针的值添加到列表

点击确定。此时二维码的内容和解析出来的内容一致,说明基址有效

定制微信登录二维码的可能性

那么我们拿到这个二维码的内容有什么作用呢?我们可以将这个获取到的二维码内容调用二维码生成器的 API 接口进行再次编码,然后生成一个更加漂亮好看专属二维码,效果如图:

使用 hook 截取二维码

接着我们编写一个 dll,将这个 dll 注入到微信进程中,利用 IAT Hook 截取微信的二维码。部分关键代码如下:

开启 HOOK

void StartHook(DWORD dwHookOffset,LPVOID pFunAddr, HWND hWnd){  hDlg = hWnd;  //拿到模块基址  DWORD dwWeChatWinAddr = GetWeChatWinAddr();  //需要HOOK的地址  DWORD dwHookAddr = dwWeChatWinAddr + dwHookOffset;
//填充数据 jmpCode[0] = 0xE9; //计算偏移 *(DWORD*)(&jmpCode[1]) = (DWORD)pFunAddr - dwHookAddr-5;
// 保存以前的属性用于还原 DWORD OldProtext = 0;
// 因为要往代码段写入数据,又因为代码段是不可写的,所以需要修改属性 VirtualProtect((LPVOID)dwHookAddr, 5, PAGE_EXECUTE_READWRITE, &OldProtext);
//保存原有的指令 memcpy(backCode, (void*)dwHookAddr, 5);
//写入自己的代码 memcpy((void*)dwHookAddr, jmpCode, 5); // 执行完了操作之后需要进行还原 VirtualProtect((LPVOID)dwHookAddr, 5, OldProtext, &OldProtext);}

卸载 HOOK

void UnHook(DWORD dwHookOffset){  DWORD dwWeChatWinAddr = GetWeChatWinAddr();  DWORD dwHookAddr = dwWeChatWinAddr + dwHookOffset;
// 保存以前的属性用于还原 DWORD OldProtext = 0;
// 因为要往代码段写入数据,又因为代码段是不可写的,所以需要修改属性 VirtualProtect((LPVOID*)dwHookAddr, 5, PAGE_EXECUTE_READWRITE, &OldProtext);
// Hook 就是向其中写入自己的代码 memcpy((LPVOID*)dwHookAddr, backCode, 5);
// 执行完了操作之后需要进行还原 VirtualProtect((LPVOID*)dwHookAddr, 5, OldProtext, &OldProtext);}

保存图片

void SaveImg(DWORD qrcode){  //获取图片长度  DWORD dwPicLen = qrcode + 0x4;  size_t cpyLen = (size_t)*((LPVOID*)dwPicLen);  //拷贝图片的数据  char PicData[0xFFF] = { 0 };  memcpy(PicData, *((LPVOID*)qrcode), cpyLen);
//将文件写到本地 HANDLE hFile = CreateFileA("E:\\qrcode.png",GENERIC_ALL,0,NULL,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL); if (hFile==NULL) { MessageBox(NULL, "创建图片文件失败", "错误", 0); return; }
DWORD dwRead = 0; if (WriteFile(hFile, PicData, cpyLen, &dwRead, NULL) == 0) { MessageBox(NULL, "写入图片文件失败", "错误", 0); return; }
CloseHandle(hFile); //显示图片 CImage img; CRect rect; //拿到控件的句柄 HWND hPic = GetDlgItem(hDlg, IDC_QRPIC); GetClientRect(hPic, &rect); //载入图片 img.Load("E:\\qrcode.png"); img.Draw(GetDC(hPic), rect);
//显示二维码内容 ShowQrCodeContent(hDlg);
//完成之后卸载HOOK UnHook(QrCodeOffset);}

最终效果

最终效果如图:

推荐阅读

原创 PC 端微信技术研究之保存聊天语言

原创 微信PC端技术研究(3)-如何找到消息发送接口

原创 PC微信逆向:发送与接收消息的分析与代码实现

原创 PC微信逆向:分析发送xml名片call

原创 PC微信逆向:两种姿势教你解密数据库文件


文章来源: http://mp.weixin.qq.com/s?__biz=MzI5MDQ2NjExOQ==&mid=2247491075&idx=1&sn=a3ffb7ddbf27e30250f7be3a1a8c492e&chksm=ec1e2e2bdb69a73d28677a1c31f9d32db31362687213739b7ea5d0031488cbc2bdb6a16fdd7c#rd
如有侵权请联系:admin#unsafe.sh