首页
论坛
专栏
课程

[调试逆向] [原创]PC微信发送消息研究

2018-3-6 14:09 9008

[调试逆向] [原创]PC微信发送消息研究

2018-3-6 14:09
9008
最近因为需要要挂机发送消息,所以要在监控的基础上做模拟发送,发送的基本效果就是给定一个wxid,给定消息内容,进行发送。
之前论坛有人已经就duilib和发送消息进行了研究,我也只是在看了他们以后完成的。
因为历史原因,微信版本是1.0.25。本教程仅作为学习研究。
1.Hook CDialogBUilder::Create 
   这里主要是为了拿到解密的xml以及获取控件的指针地址。
   如何找到这个函数的地址,通过搜索字符串“加载资源失败“,“Duilib”。找到以后,上面的两个函数就是了。然后进行hook。
   获取文件名和文件,我hook了两个地方。
  void __declspec(naked) MyDumpDuilibXml()
{
__asm{
    pushfd
pushad
push [esp+0x30]
push [esp+0x30]
push [esp+0x30]
push ecx //拿到文件名
call CLoadXmlFromMem_Ret
popad
popfd
jmp[g_dumpDuilibXml]
}
}
unsigned g_dumpxmlGetFileName = 0;

void __declspec(naked) MyDumpDuilibXmlGetFileName()
{
__asm{
pushfd
pushad
push [esp+0x28]
call CDumpDuilibXmlGetFileName
popad
popfd
jmp[g_dumpxmlGetFileName]
}
}
WCHAR * g_currentXmlFileName = NULL;

VOID WINAPI CDumpDuilibXmlGetFileName(WCHAR* currentXmlFileName)
{
g_currentXmlFileName = currentXmlFileName;
}
VOID WINAPI CLoadXmlFromMem_Ret(void* cmakeup ,BYTE* pByte,int dwSize,int encoding)
{
LPTSTR m_pstrXML;
if( dwSize >= 3 && pByte[0] == 0xEF && pByte[1] == 0xBB && pByte[2] == 0xBF ) 
{
pByte += 3; dwSize -= 3;
DWORD nWide = ::MultiByteToWideChar( CP_UTF8, 0, (LPCSTR)pByte, dwSize, NULL, 0 );
m_pstrXML = static_cast<LPTSTR>(malloc((nWide + 1)*sizeof(TCHAR)));
::MultiByteToWideChar( CP_UTF8, 0, (LPCSTR)pByte, dwSize, m_pstrXML, nWide );
m_pstrXML[nWide] = _T('\0');
}else
{
DWORD nWide = ::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)pByte, dwSize, NULL, 0 );
m_pstrXML = static_cast<LPTSTR>(malloc((nWide + 1)*sizeof(TCHAR)));
::MultiByteToWideChar( CP_ACP, 0, (LPCSTR)pByte, dwSize, m_pstrXML, nWide );
m_pstrXML[nWide] = _T('\0');
}
if (g_currentXmlFileName)
{
TCHAR szPath[MAX_PATH] = {0};  
TCHAR szDrive[MAX_PATH] = {0};  
TCHAR szDir[MAX_PATH] = {0};  
TCHAR szFileName[MAX_PATH] = {0};  
TCHAR szExt[MAX_PATH] = {0};  
wstring filepath = L"D:\\tempxml\\";

filepath.append(g_currentXmlFileName);
wcscpy(szPath, filepath.c_str());  
split_path(szPath, szDrive, szDir, szFileName, szExt);
filepath = L"D:\\tempxml\\";
filepath.append(szFileName);
filepath.append(szExt);
//_cwprintf_s(_T("filepath %ws\r\n"), filepath.c_str());
HANDLE hFile = CreateFile(filepath.c_str(), 
GENERIC_WRITE, 0, NULL,  
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
DWORD dwBytesWriten = 0;
int nRet = WriteFile(hFile, pByte, dwSize, &dwBytesWriten, NULL);  
CloseHandle(hFile);

g_currentXmlFileName = NULL;
}

}
大概这样hook一下以后就能得到所有的完整的Xml了。

通过xml我们可以得到微信的duilib的布局以及控件名称,为之后我们进内存搜代码提供方便。
并且在创建完成之后我们需要拿到input_richedit的控件地址,因为之后要做setText操作。
2.hook Notify 同样看论坛的hook代码基本不需要改,就行。
  其实hook了Notify函数以后,我们可以模拟发送消息如何发送呢?
        void *  g_CHookNotify_base = 0;
void Notify(TNotifyUI& msg)
{
extern CHookNotify::pfn_Notify g_pfn_oldnotify;
if (!g_CHookNotify_base)
{
g_CHookNotify_base = this;
_cwprintf_s(L"g_CHookNotify_base  %p\r\n", g_CHookNotify_base);
}
           return (this->*g_pfn_oldnotify)(msg);
      }
这里提前保存一下ecx的指针。
然后调用:
       CHookNotify * pthis = (CHookNotify*)g_CHookNotify_base;
TNotifyUI * mewmsg =new  TNotifyUI;
mewmsg->sType = CDuiString(_T("click"));
mewmsg->sVirtualWnd = CDuiString(_T(""));
mewmsg->pSender = g_profileSendBtn;
mewmsg->dwTimestamp = ::GetTickCount();
mewmsg->ptMouse.x = 0;
mewmsg->ptMouse.y = 0;
mewmsg->wParam = NULL;
mewmsg->lParam =NULL;

        int * p = (int*)((int)pthis+0xDE0);
wstring aaa( pwxid);
VString * pstring  = new VString;
pstring->pstting = (WCHAR*)aaa.c_str();
pstring->size = aaa.size();
memcpy(p,pstring,sizeof(pstring));
         pthis->Notify(*mewmsg);

当然这里用到了g_profileSendBtn,这个在获取input_richedit的时候同步获取的。这里模拟的就是选择某个联系人然后点击发消息。
联系人的wxid 保存在偏移0xDE0的地方了,这个偏移如何找,主要是通过跟踪点击事件的处理函数。其实所有的消息处理都在
g_pfn_oldnotify这里进行的,找到profileSendBtn的字符串就能找到处理函数。
这一步进行了以后,你要发送的wxid就会被至于session_list的顶端,这样就算session_list本身没有也会自动添加。
__asm{
pushfd
pushad
mov eax ,writestring
push eax
mov ecx,g_input_richedit
mov eax,[g_input_richedit]
mov eax,[eax]
call [eax+0x2C]
popad
popfd
}
然后调用settext把文本加入进去,0x2C可以根据调用一下getText得到,在它的下一个函数就是了。
最后点击发送
__asm{
pushfd
pushad
mov ecx,pWinImplBase
call g_sendText
popad
popfd
}
可以采用模拟点击的调用,也可以直接这样。随便那种都行,这样就能对任意wxid发消息了。
再补充一下消息拦截可以在插入的地方拦截,做记录大概这么个位置,直接附加然后搜字符串就能搜到了,下个断点啥都明白了。




[招聘]欢迎市场人员加入看雪学院团队!

最后于 2018-3-6 14:14 被大魔头编辑 ,原因:
最新回复 (18)
friendanx 2018-3-6 22:33
2
0
感谢分享
zhhigh 2018-3-7 15:59
3
0
感谢分享
jacksonfan 2018-3-25 11:30
4
0
厉害,学习了
十年一刻 2018-3-29 14:08
5
0
你好我可以加你qq吗
fengyelan 2018-3-30 10:53
6
0
感谢分享
petersonhz 2018-3-30 21:23
7
0
挂机发送消息,楼主是做公众号的么
荒野之狼 2018-3-30 22:00
8
0
zhuangbx 2018-4-1 10:29
9
0
谢谢分享
TheRoad 2018-4-12 09:11
10
0
感谢分享思路,
redacker 2018-4-12 09:37
11
0
感谢分享思路.
wx_夏了茶糜 2018-4-23 08:53
12
0
感谢分享思路
nchxmoon 2018-4-23 14:15
13
0
厉害
大月月鸟 2018-4-24 21:46
14
0
厉害
longyaohua 2018-6-19 03:45
15
0
非常感谢您的赐教,受益匪浅啊!
最后我还是想请教您,发图片和发表情,自定义表情      这些怎么弄
BlackJZero 2018-6-19 11:11
16
0
学习
化魔 2018-7-7 07:51
17
0
留下脚印,以后回来!
coolsnake 2018-7-7 19:25
18
0
非常感谢,正是我想要的。
真烧鱼 2019-2-28 16:01
19
0
请问是版本的问题吗,版本6.2.7我没找到Duilib上面有关于文件和和文件名的函数,只看到load资源文件类型为zipres的功能部分
游客
登录 | 注册 方可回帖
返回