逆向——微信接收文本图片消息

目录

前言

一、找接收消息的位置

二、找接收图片地址

三、代码实现


前言

参考大神anhkgg的文章https://bbs.pediy.com/thread-249274.htm

实现目前最新的微信版本:3.2.1.154

并扩展支持上接收图片、视频、文件、小视频等信息

 

一、找接收消息的位置

使用工具

OllyDbg、CE(Cheat Engine)

1、打开OllyDbg、CE(Cheat Engine)和微信,附加微信进程到OllyDbg、CE(Cheat Engine)中

OD附加有标题“微信”的进程,CE附加与OD加载的进程ID相同的进程

2、给加载上调试的微信发一个消息:“123456”。切到CE界面,点击“新的扫描”,扫描类型选择“搜索字符串”,输入文本“123456”,点击首次扫描,发现查到很多地址;

 

 

3、再次发送“abcdef”,把CE界面搜索文本改为“abcdef”,注意这次点击再次扫描,发现还剩两个地址,把查询结果添加到地址列表

 

4、改变其中一个数值,如果微信收到的内容跟着变,那么说明是这个地址,如果没变,说明是另一个。找到这个内存后接下来在OD中下内存写入断点;

 

5、再次发一条信息,在段下来的地方根据堆栈向上找接收内容的来源,最终向上回溯大概9次,点击K查看堆栈的话是这个位置

 

6、在这里下断点观察EDI的内容,EDI指向内存再指向的内存如下图所示。+40的位置是发送者ID,+68的位置是发送的内容。如果改成群发送的文本,+40的位置是群ID,+178是发送者的群成员ID

 

二、找接收图片地址

1、发送一张图片,发现内容部分是一串xml格式字符

<?xml version="1.0"?>

<msg>

<img aeskey="38303330323961663865383830626462" encryver="0" cdnthumbaeskey="" cdnthumburl="" cdnthumblength="0" cdnthumbheight="0" cdnthumbwidth="0" cdnmidheight="0" cdnmidwidth="0" cdnhdheight="0" cdnhdwidth="0" cdnmidimgurl="" length="0" tpthumburl="https://wwfile.work.weixin.qq.com/cgi-bin/download?f=30680201020461305f0201000204edb3413602030f55ca02045b6cc2dc020460a37bf7042435353632333961362d623138302d346366662d383162302d6362353663643936323635320201000202052004102181b6b9c48579d8654f6879536581310201010201000400&amp;t=70F95321C6137C5FE12CE67AC53A6475E7BF5274DC1132D233AC7140376BBA5726343EF95DFB4C2C60BD3887E2EBA21F15D86ACC22464085DBF1C88083E05964211CF2E2A981440A09207130D1E8705AAA6409FFFC159D078B20FA3FE5C6B639D710E171C6AC2FF9BE4D7CF00639A8FD4D8B200A876EBDE5BA43E912D1177CFFD802B62DE3682C9236F7ECF52C1C4A61910FA7602716878D840BD05AE49E496EBD88C1E1290171813060E5EDE1600F6F294833A53F301821F25BF1597F1E6D4E89BCFB37D3AB83EAACBDC02F033E29A5C9A1BB552D97FB0FA8E9F5695AAD02787A87372534B0F9160BF65C1C08B4DA33BD13010C1AA2B94510CFBC4EC4B2C1060F7DA6986C06298940CB97D1277BF365&amp;p=3" tpthumblength="2522" tpthumbheight="131" tpthumbwidth="224" tpthumbaeskey="38303330323961663865383830626462" tpurl="https://wwfile.work.weixin.qq.com/cgi-bin/download?f=30680201020461305f0201000204edb3413602030f55ca02045b6cc2dc020460a37bf7042435353632333961362d623138302d346366662d383162302d6362353663643936323635320201000202052004102181b6b9c48579d8654f6879536581310201010201000400&amp;t=70F95321C6137C5FE12CE67AC53A6475E7BF5274DC1132D233AC7140376BBA5726343EF95DFB4C2C60BD3887E2EBA21F15D86ACC22464085DBF1C88083E05964211CF2E2A981440A09207130D1E8705AAA6409FFFC159D078B20FA3FE5C6B639D710E171C6AC2FF9BE4D7CF00639A8FD4D8B200A876EBDE5BA43E912D1177CFFD802B62DE3682C9236F7ECF52C1C4A61910FA7602716878D840BD05AE49E496EBD88C1E1290171813060E5EDE1600F6F294833A53F301821F25BF1597F1E6D4E89BCFB37D3AB83EAACBDC02F033E29A5C9A1BB552D97FB0FA8E9F5695AAD02787A87372534B0F9160BF65C1C08B4DA33BD13010C1AA2B94510CFBC4EC4B2C1060F7DA6986C06298940CB97D1277BF365&amp;p=2" tplength="1840" tpheight="131" tpwidth="224" tpauthkey="0A2B6F4E2D4D77415141414141444B35692D425A6764323663357252576C314831736F40696D2E7778776F726B10E7C6F6A205" tphdurl="https://wwfile.work.weixin.qq.com/cgi-bin/download?f=30680201020461305f0201000204edb3413602030f55ca02045b6cc2dc020460a37bf7042435353632333961362d623138302d346366662d383162302d6362353663643936323635320201000202052004102181b6b9c48579d8654f6879536581310201010201000400&amp;t=70F95321C6137C5FE12CE67AC53A6475E7BF5274DC1132D233AC7140376BBA5726343EF95DFB4C2C60BD3887E2EBA21F15D86ACC22464085DBF1C88083E05964211CF2E2A981440A09207130D1E8705AAA6409FFFC159D078B20FA3FE5C6B639D710E171C6AC2FF9BE4D7CF00639A8FD4D8B200A876EBDE5BA43E912D1177CFFD802B62DE3682C9236F7ECF52C1C4A61910FA7602716878D840BD05AE49E496EBD88C1E1290171813060E5EDE1600F6F294833A53F301821F25BF1597F1E6D4E89BCFB37D3AB83EAACBDC02F033E29A5C9A1BB552D97FB0FA8E9F5695AAD02787A87372534B0F9160BF65C1C08B4DA33BD13010C1AA2B94510CFBC4EC4B2C1060F7DA6986C06298940CB97D1277BF365&amp;p=1" tphdlength="1299" />

</msg>

2、img有几个属性:aeskey、tpthumbaeskey、tpurl等,随便复制一个,如tpurl,在OD中搜索参考字符串:右键——搜索——所有参考字符串,弹出“索索-文本字符串中引用”窗口,Ctrl+F弹出搜索输入框,输入tpurl点击确定(快捷键Ctrl+L查找下一处;Ctrl+Sheft+L查找上一处)

 

3、双击查到的行,转到反汇编窗口。在这下断点,并搜索所有Push "tpurl"的地方都下断点(一共查到两处)

4、再次发一张图片,在第一个push “tpurl”的地方断下来,然后再CreateFileW下断,F5后在CreateFileW断下时观察参数路径,一直F5执行直到路径包含File\Image停下,Ctrl+F5执行到返回指令,此时Eax寄存器中保存的是文件句柄,紧接着程序会向文件中写数据,所以在KERNEL32.WriteFile下断点(其他断点都可以先禁用,以免产生干扰),直到参数句柄和打开文件句柄一致

 

5、此时观察WriteFile第二个参数也就是lpBuffer,发现是空的,再次F5直到有值,此时会发现存的数据格式是图片格式。

6、但是有的人按照这一套操作下来,可能有的人会发现写入文件时lpBuffer 的数据不是图片格式,而是不知道是什么格式的一堆字符,这是因为如果用手机选择本地图片文件发送的时候,保存的是加密后的图片信息,向上追溯保存信息的来源,然后向上追溯向上两层堆栈处,此时ebp-14是加密后图片信息,在这个位置找到函数其实位置(或者向上找到ebp-14开始出现的地方)下断点。

7、最后找到这个位置(特征码:\x8B\x5D\xFC\x3B\xD7\x7D\x25\x2B\xDE\x8D\x0C\x16\x89\x5D\xFC),此时的ebp-4是加密前的图片数据,在此位置下断点

8、那么这里的函数入参只有图片信息,没有发送者信息,怎样找到发送者信息呢?经过寻找,发现esp+4中存储的内存结构中,有图片路径信息,接收文本消息处的消息里也有路径信息,可以作为关联

9、再在收文本信息的位置下断点,查看消息结构体信息,可以看到有两个路径信息,+18C是缩略图,+1A0是原图,而接收图片断点在收到图片时也会执行两次,一次是缩略图,一次是原图

 

三、代码实现

1、CWeBase基类

提供两个入口函数Hook、UnHook,方便hook调用

/**
* @brief hook对象基类
* 两个入口函数Hook、UnHook,方便hook调用
*/
class CWeBase
{
private:
	//HOOK地址
	unsigned int m_nAddress;
	//代码
	unsigned char m_sCode[10];
	//代码长度
	unsigned int m_nCodeLen;
	//线程表
	TV_ThreadTable m_ThreadTable;
public:
	CWeBase();
	~CWeBase();

private:
	/**
	* @brief 获取HOOK代码和长度
	* @param nAddress		hook的代码位置
	* @param strCode		代码位置的反汇编的代码
	* @param nCodeLen		代码位置的反汇编的代码所占内存长度
	*/
	bool GetHookCode(int nAddress, std::string& strCode, int& nCodeLen);
	//获取线程列表
	void GetAllThread();
	//挂起所有线程
	void SuspendAllThread();
	//恢复所有线程
	void ResumeAllThread();
	//刷新CPU缓存
	void UpdateCache(LPVOID lpBase, int nBaseSize);

protected:
	

	unsigned int GetCallAddressByOffset(unsigned int nOffset, LPCSTR module = NULL);

	bool GetObjectString(unsigned int nObject, unsigned int nOffset, LPSTR lpOutBuf, int nBufLen);
	int GetObjectInt(unsigned int nObject, unsigned int nOffset);
public:
	/**
	* @brief 下钩子
	* @param lpModuleName	模块名
	* @param nOffset		偏移地址
	* @param nCallBack		回调函数地址
	* @param pJmpAddress	记录回调后跳转回来的地址
	* @retval 1				成功
	* @retval 0				失败
	*/
	bool Hook(LPCSTR lpModuleName, unsigned int nOffset, unsigned int nCallBack, unsigned int* pJmpAddress);
	/**
	* @brief UnHook
	* 取消钩子
	*/
	void UnHook();

};

2、CReceive类,继承CWeBase基类

在接收消息的特定位置下钩子,并解析接收到的消息信息,包括发送者id和接收的内容(文本、视频、图片等)

/**
* @ brief hook接收消息
* 在接收消息的特定位置下钩子,并解析接收到的消息信息,包括发送者id和接收的内容(文本、视频、图片等)
*/
class CReceive :public CWeBase
{
public:
    CReceive();
    ~CReceive();

	/**
	* @ brief 解析接收的信息
	* @ param 接收的信息存放地址
	*/
	void CallBackManage(unsigned int nObject);
	
public:
	//记录回调后转回地址
	static unsigned int m_nJmpAddress;

	static CReceive* m_sReveiv;
	//回调地址
	T_CallBack_RecvMsg m_pCallBack;
	/**
	* @brief 下钩子
	* @retval 1 成功
	* @retval 0 失败
	*/
	bool ToHook(T_CallBack_RecvMsg pCallBack);
};

3、CReceivePicture:接收图片hook

接收图片和路径信息,通过路径信息和发送者信息进行关联

/**
* @brief	接收图片hook
* 接收图片和路径信息,通过路径信息和发送者信息进行关联
*/
class CReceivePicture :public CWeBase
{
public:
	CReceivePicture();
	~CReceivePicture();
	/**
	* brief	接收图片hook回调
	* param	nBuffer		图片内容
	* param nBufferSize	图片内容长度
	* param nObject		图片路径所在结构
	*/
	void CallBackManage(unsigned int nBuffer, unsigned int nBufferSize,unsigned int nObject);

public:
	//记录回调后转回地址
	static unsigned int m_nJmpAddress;
	//接收图片hook对象静态指针
	static CReceivePicture* m_sReveivPicture;
	//接收图片路径配置
	static std::string m_sRevPicPath;

	//回调地址
	T_CallBack_RecvMsg m_pCallBack;
	/**
	* @brief 下钩子
	* @retval 1 成功
	* @retval 0 失败
	*/
	bool ToHook(T_CallBack_RecvMsg pCallBack);
};

4、完整代码源码地址:https://gitee.com/zhangruyi/we-chat-tool

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值