您當前的位置:首頁 > 體育

PC 端微信逆向分析

作者:由 看雪 發表于 體育時間:2017-09-05

關鍵字: 微信、duilib庫hook,duilib模擬點選。

最近有朋友問我libcef如何注入js,然後又談到微信用了libcef云云。

搗騰了一下午,知道怎麼注入js後,發現朋友是需要auto control ui

瞬間崩潰。。。。

誠然微信有些瀏覽器功能用到了cef,但是主介面是duilib寫的

跟cef沒毛關係,(libcef封裝到qbcore。dll裡面,想注入js需要hook libcef的匯出函式

拿到browser,替換callback……)

話題回到pc端微信怎麼auto control ui,以及如何拿到”控制元件“上面的資訊

下面為原理截圖,看不懂請參考duilib原始碼

CWindowWnd 指標可以透過GetWindowLongPtr獲取

PC 端微信逆向分析

PC 端微信逆向分析

PC 端微信逆向分析

PC 端微信逆向分析

CWindowWnd指標 == WindowImplBase指標

然後透過

static_cast(pWinImplBase)

轉換得到INotifyUI指標,再透過虛擬函式地址表就能找到Notify指標

最後替換Notify指標就能監控到所有duilib事件了

PC 端微信逆向分析

PC 端微信逆向分析

事件結構體,pSender是事件的觸發者,我們後面透過獲取root節點就能得到所有CControlUI

這個結構我們可以偽造出來,然後直接呼叫原始Notify回撥就能模擬介面操作了

PC 端微信逆向分析

PC 端微信逆向分析

每一個xml建立CControlUI 樹的時候,都會呼叫CDialogBuilder::Create

我們透過hook這個函式,返回就能得到root節點

PC 端微信逆向分析

PC 端微信逆向分析

這裡是duilib的container節點原理,如果父親是一個容器節點,就把自己新增到父親裡面

PC 端微信逆向分析

PC 端微信逆向分析

得到節點樹之後,我們需要列舉所有節點

看看這些虛擬函式是不是很可愛,很方便,有沒有想到com技術

PC 端微信逆向分析

PC 端微信逆向分析

這個虛擬函式更可愛,哈哈

PC 端微信逆向分析

PC 端微信逆向分析

可愛到我不需要判斷數量,只需要判斷結果是否為NULL就能知道是否列舉結束

PC 端微信逆向分析

PC 端微信逆向分析

原理圖都貼了,最好自己看看duilib原始碼,pc端微信介面是duilib寫的,基本的虛擬函式偏移沒有變化,說明騰訊沒有大改動duilib(新增虛擬函式)

當然,我發現有些結構被改動過,這裡就不提了。

關於duilib的訊息流動,自己可以好好看看原始碼。

以下為部分程式碼,自行完成完整版

//hook CDialogBuilder::Create

/*

CControlUI* CDialogBuilder::Create(IDialogBuilderCallback* pCallback, CPaintManagerUI* pManager, CControlUI* pParent)

*/

VOID WINAPI CDialogBuilder_Create_Ret(CControlUI* pControlUI)

{

TRACE_LOG_INFO(_T(“CDialogBuilder::Create Ret 。。。”));

if (pControlUI)

enumContainer(pControlUI);

}

//遍歷控制元件的資訊

void enumContainer(CControlUI * pControlUI)

{

LPCTSTR lpcszClass = pControlUI->GetClass();

LPCTSTR lpcszName = pControlUI->GetName();

LPCTSTR lpcszText = pControlUI->GetText();

if (lpcszClass)

TRACE_LOG_INFO(_T(“%s”), lpcszClass);

if (lpcszName)

TRACE_LOG_INFO(_T(“%s”), lpcszName);

if (lpcszText)

TRACE_LOG_INFO(_T(“%s”), lpcszText);

if (CDuiString(_T(“session_list”)) == pControlUI->GetName())

{

g_session_list = pControlUI;

}

if (CDuiString(_T(“contact_list”)) == pControlUI->GetName())

{

g_contact_list = pControlUI;

}

IContainerUI *pContainerUI = static_cast(pControlUI->GetInterface(_T(“IContainer”)));

if (pContainerUI)

{

int i = 0;

CControlUI * pControlIter = NULL;

while (pControlIter = pContainerUI->GetItemAt(i++))

{

enumContainer(pControlIter);

}

}

}

//hook event notify

class CHookNotify : INotifyUI

{

public:

typedef void(CHookNotify::*pfn_Notify)(TNotifyUI& msg);

void Notify(TNotifyUI& msg)

{

extern CHookNotify::pfn_Notify g_pfn_oldnotify;

return (this->*g_pfn_oldnotify)(msg);

}

};

CHookNotify::pfn_Notify g_pfn_oldnotify = NULL;

DWORD WINAPI test_thread(

LPVOID lpThreadParameter

{

MessageBox(NULL, NULL, NULL, MB_OK);

HWND hMainWnd = FindWindow(_T(“WeChatMainWndForPC”), NULL);

if (!hMainWnd)

{

TRACE_LOG_INFO(_T(“%s”), _T(“FindWindow Error 。。。”));

return 0;

}

CWindowWnd *pThis = reinterpret_cast(::GetWindowLongPtr(hMainWnd, GWLP_USERDATA));

if (!pThis)

{

TRACE_LOG_INFO(_T(“%s”), _T(“Get CWindowWnd Pointer Error 。。。”));

return 0;

}

HWND *phWnd = reinterpret_cast(((uintptr_t)pThis + sizeof(uintptr_t)));

if (IsBadReadPtr(phWnd, sizeof(HWND)))

{

TRACE_LOG_INFO(_T(“%s”), _T(“Pointer Invalid Error 。。。”));

return 0;

}

if (*phWnd != hMainWnd)

{

TRACE_LOG_INFO(_T(“%s”), _T(“Invalid CWindowWnd Pointer Error 。。。”));

return 0;

}

//WindowImplBase * == CWindowWnd *

WindowImplBase *pWinImplBase = reinterpret_cast(pThis);

INotifyUI *pNotifyThis = static_cast(pWinImplBase);

CHookNotify::pfn_Notify *p_pfn_oldnotify = *reinterpret_cast(pNotifyThis);

//set virtual table hook

g_pfn_oldnotify = *p_pfn_oldnotify;

CHookNotify::pfn_Notify temp;

__asm push CHookNotify::Notify;

__asm pop temp;

DWORD dwOldProtect = 0;

VirtualProtect(p_pfn_oldnotify, sizeof(void *), PAGE_EXECUTE_READWRITE, &dwOldProtect);

*p_pfn_oldnotify = temp;

return 0;

}

最後來一張效果圖

PC 端微信逆向分析

PC 端微信逆向分析

本文由看雪論壇 tongzeyu 原創 轉載請註明來自看雪社群

標簽: pfn  pControlUI  duilib  notify  trace