最近因为需要要挂机发送消息,所以要在监控的基础上做模拟发送,发送的基本效果就是给定一个wxid,给定消息内容,进行发送。
之前论坛有人已经就duilib和发送消息进行了研究,我也只是在看了他们以后完成的。
因为历史原因,微信版本是1.0.25。本教程仅作为学习研究。
1.HookCDialogBUilder::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了。