DuiLib逆向分析の按鈕事件定位

VxerLee暱稱已被使用發表於2021-12-10

DuiLib逆向分析の按鈕事件定位

0x00 前言

記錄自己學習Duilib逆向分析的筆記。

DuiLib介紹

DuiLib官方介紹,Duilib是一個Windows下免費開源的DirectUI介面庫,由於簡約易擴充套件的設計以及穩定高效的實現被各大網際網路公司普遍接受,廣泛應用於包括IM、視訊客戶端、股票行情軟體、導航軟體、手機輔助軟體、安全軟體等多個行業的眾多pc客戶端軟體。Duilib還在不斷的發展中,在文件、例子、動畫、渲染引擎等多個方面將持續改進。

DirectUI介紹,直接在父視窗上繪圖,構建易於擴充套件的介面。(DirectUI意為直接在父視窗上繪圖(Paint on parent dc directly)。即子視窗不以視窗控制程式碼 的形式建立(windowless),只是邏輯上的視窗,繪製在父視窗之上。)

Duilib是一個自繪控制元件介面庫,可以很方便的構建高效,絢麗的,非常易於擴充套件的介面。

國外如微軟,國內如騰訊百度等公司的客戶端產品多采用這種方式來組織介面,從而很好的將介面和邏輯分離,同時易於實現各種超炫的介面效果如換色,換膚,透明等。

DuiLib安裝

安裝DuiLib推薦用C++庫管理器vcpkg來安裝,這東西我感覺類似Python的pip。可以很方便的安裝管理第三方庫

vcpkg官方安裝教程,安裝vcpkg非常簡單,就如下幾條命令就搞定:

git clone https://github.com/microsoft/vcpkg
#將vcpkg目錄新增到環境變數
RefreshEnv.cmd          #更新環境變數
bootstarp-vcpkg.bat     #vcpkg初始化相關檔案
vcpkg integrate install #配置到VS相關環境中
vcpkg search  [庫名]    #搜尋相關第三方庫
vcpkg install [庫名]    #安裝第三方庫

安裝DuiLib庫:

vcpkg install DuiLib #安裝DuiLib庫

DuiLib Hello,World!

裝好了庫後,我們來寫第一個DuiLib程式,經典的Hello,World!

//DuiLib庫標頭檔案
#include <DuiLib/UILib.h>
//名稱空間
using namespace DuiLib;

//重寫Windows視窗類,繼承自->CWindow -> INotifyUI
class CDuilibWnd : public CWindowWnd,public INotifyUI
{
    
    public:
    //虛擬函式
    virtual LPCTSTR GetWindowClassName() const {return _T("DuiWnd");}//視窗類
    //重寫響應訊息
    virtual void Notify(TNotifyUI& msg)
    {
        if(msg.sType == _T("click"))
        {
            if(msg.pSender->GetName() == _T("Hello_btn"))
            {
                MessageBoxA(NULL,"Hello,World!","Dui逆向の按鈕事件定位",MB_OK);
            }
        }
    }
    //重寫訊息處理
    virtual LRESULT HandleMessage(UINT uMsg,WPARAM wParam,LPARAM lParam)//回撥函式
    {
        LRESULT lRes = 0;
        if(uMsg == WM_CREATE)
        {
            m_PaintManager.Init(m_hWnd);
            //利用XML佈局生成介面
            CDialogBuilder builder;
            CControlUI* pRoot = builder.Create(_T("duilib.xml"),0,NULL,&m_PaintManager);
            ASSERT(pRoot && "Failed to parse XML");
            m_PaintManager.AttachDialog(pRoot);
            //用於處理訊息
            m_PaintManager.AddNotifier(this);
            return lRes;
        }
        if(m_PaintManager.MessageHandler(uMsg,wParam,lParam,lRes)) return lRes;
        return __super::HandleMessage(uMsg,wParam,lParam);
    }
    
    protected:
    CPaintManagerUI m_PaintManager;
}

int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
    CPaintManagerUI::SetInstance(hInstance);//繫結視窗控制程式碼
    CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());//載入XML
    //建立並顯示視窗
    CDuilibWnd duilibWnd;
    duilibWnd.Create(NULL,_T("Dui逆向の按鈕事件定位"),UI_WNDSTYLE_FRAME,WS_EX_WINDOWEDGE);
    duilibWnd.ShowModal();//監聽訊息
    return 0;
}

duilib.xml 介面佈局檔案

<?xml version="1.0" encoding="UTF-8"?>
<Window size="320,100">
    <HorizontalLayout bkcolor="#FFFFFFFF">
		<Button name="Hello_btn" text="按鈕"  height="40" width="80"  bordersize="1,1,1,1" bordercolor="#0079DE" padding="111,10,0,0"/>
    </HorizontalLayout>
</Window>

編譯生成後的介面如下,並且點選按鈕後觸發了事件:

image-20211210141430317

Duilib逆向分析之定位按鈕事件

碎碎念

所以我覺得做逆向開發,不能盲目的一開始就去看OD,去IDA F5反編譯,而是應該擅長利用搜尋引擎去學習瞭解相關:框架、庫、模型、開發等知識,有了這些知識後逆向就如魚得水。

第一步:獲取xml佈局檔案

首先切入點是從duilib.xml檔案開始,所以我們在逆向Duilib相關程式時候應該先拿到他的佈局檔案。

而在我們的demo中duilib.xml是在本地的,而在原始碼中可以看到builder.Create來載入使用duilib.xml

image-20211210142047876

如果xml在本地的話則很簡單直接找到路徑即可,但是常規逆向分析中基本都是在記憶體中的,那這種要如何獲取到他的xml佈局檔案呢?

思路還是一樣,先定位到這個builder.Create函式,然後跟進去一步步除錯,看堆疊資訊,看經過哪一句彙編程式碼或Call後出現xml內容。

image-20211210150307646

第二步:按鈕事件分金點穴

當我們拿到佈局後,找到對應按鈕的名稱,例子中的按鈕對應的名稱是Hello_btn,然後去除錯軟體中搜尋相關字串Hello_btn

image-20211210150422786

並且下上斷點。

image-20211210150543271

當我們點選按鈕後,成功的斷到如下位置:

image-20211210150711936

111

斷點斷到後,檢視上下文中的彙編就已經很明顯了,在je下面 (je那一句是判斷當前btn按鈕事件是否是Hello_btn的按鈕事件),對應的原始碼就是:

if(msg.pSender->GetName() == _T("Hello_btn"))
{
    MessageBoxA(NULL,"Hello,World!","Dui逆向の按鈕事件定位",MB_OK);
}

感謝觀看我的筆記,如有問題請指出謝謝。

逆向、PWN學習交流

Pwn菜雞學習小分隊群聊二維碼

相關文章