[原创]PC微信发送消息研究

最近因为需要要挂机发送消息,所以要在监控的基础上做模拟发送,发送的基本效果就是给定一个,给定消息内容,进行发送。
之前有人已经就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(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(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发消息了。
再补充一下消息拦截可以在插入的地方拦截,做记录大概这么个位置,直接附加然后搜字符串就能搜到了,下个断点啥都明白了。

这里写图片描述

——完——
关注公纵号无极圈wuji1a

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值