PC微信逆向:使用HOOK拦截二维码

微信版本

在这里插入图片描述

寻找微信二维码基址

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寻找二维码内容的基址

在这里插入图片描述

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

第一部分:http://weixin.qq.com/x
第二部分:/I-yOUnFpRaZOwZyVPC0H

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

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

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

在这里插入图片描述

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

在这里插入图片描述

然后用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);
}

最终效果

最终效果如图:

在这里插入图片描述

最后附上工程和成品DLL

目前微信机器人的成品已经发布,需要代码请移步Github。还请亲们帮忙点个star

https://github.com/TonyChen56/WeChatRobot

### 回答1: Python钩子微信是一种使用Python编程语言编写的程序,用于检测和捕获微信应用程序的输入和输出,并进行处理和操作。该程序可以用于自动发送和接收微信消息,拦截和修改微信消息,获取微信用户信息以及实现其他自定义功能。要实现Python钩子微信,需要了解微信应用程序的工作原理和API,以及Python的基本编程知识和技能。在编写程序时,需要使用第三方库和工具,例如itchat、pymouse、pyHook等。通过这些工具,可以轻松地编写Python钩子微信程序,并实现自己想要的功能。但是需要注意,在编写程序时,应遵守微信的相关规定和条例,不得用于非法或未经授权的用途。除此之外,在编写钩子程序时,还应注意安全问题,避免损坏计算机系统或容易出现安全漏洞。总之,Python钩子微信是实现微信自定义功能的一种有效方法,但需要在充分了解微信API和Python编程基础的基础上进行。 ### 回答2: Python hook PC微信,也就是通过Python程序来对PC版的微信进行一些自定义的操作。首先需要了解的是,PC微信是一个Windows平台的桌面应用程序,而Python是一种高级编程语言,可以通过一些模块和库来实现对PC微信的控制和管理。 要实现钩取(hookPC微信,需要使用到相关的模块和包,比如pyHook、keyboard、ctypes等。其中,pyHook是一个Python钩子模块,它可以捕获各种Windows事件,如键盘鼠标事件等。而keyboard则是另一个Python模块,它也可以用于监测和记录键盘事件。最后,ctypes是一个Python模块,用于调用或操作Windows中的DLL、API以及C的库。 钩取PC微信主要可以实现以下几个方面: 1. 监测和记录键盘事件 通过使用pyHook、keyboard等模块,可以在Python程序中监测和记录PC微信中的各种键盘事件,比如输入字符、快捷键等。这可以方便地实现自动回复、自动切换聊天窗口等功能。 2. 控制和管理PC微信窗口 通过使用ctypes,在Python程序中可以调用Windows API函数,比如FindWindow、SetWindowPos等,来实现对PC微信窗口的控制和管理,比如改变窗口大小、位置,最小化窗口等。 3. 实现自动化脚本 通过以上两个方面的应用,可以实现对PC微信的自动化控制和管理。比如可以编写Python脚本,使其自动监测PC微信中的消息,自动回复、发送消息,或者进行一些其他操作等。 总之,Python hook PC微信可以为我们带来很多便利和效率,在实际应用中也有很多种可能,比如在聊天机器人、自动化聊天、消息推送等方面都有着广泛的应用。 ### 回答3: Python Hook PC微信,简单来说就是使用Python编写程序完成对PC微信软件的钩子(hook)功能。钩子是一种编程技术,可以监视计算机的特定活动,并在特定事件发生时触发自定义功能。 对于PC微信软件而言,可能存在一些无法实现的需求,或者需要对其界面进行改进等情况。这时,我们可以使用Python编写程序,来完成对微信软件的钩子,实现我们想要的效果。 具体来说,Python Hook PC微信可以通过以下步骤实现: 1. 导入Python的ctypes库,用于调用Windows的API函数。 2. 使用WinAPI获取微信的句柄(handle),并将其与Python中的句柄绑定。 3. 使用WinAPI获取微信窗口中的各种控件,包括菜单、列表、文本框、按钮等。 4. 对这些控件进行钩子操作,比如监控鼠标和键盘事件,或者改变控件的样式、位置、大小等。 5. 根据需要编写自己的功能,比如监听微信收到新消息的通知,自动回复消息,或者改变接收到的消息格式等。 需要注意的是,钩子的实现需要一定的编程技巧和经验,同时也具有一定的安全风险。在实际编写过程中,应当按照规范操作,避免对微信软件及其用户造成损害。此外,Python Hook PC微信也有一定的局限性,可能会受到微信版本升级、系统环境变化、安全策略影响等问题。因此,我们需要在编写程序前进行足够的研究和测试,以确保可靠性和稳定性。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鬼手56

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值