欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

QQScreenShot之逆向并提取QQ截圖--基本功能

  發(fā)布時間:2023-02-04 11:31:59   作者:佚名   我要評論
QQ截圖是我用過的最好用的截圖工具, 由于基本不在電腦上登QQ了, 于是就想將其提取出獨立版目前除了屏幕錄制功能其他都逆出來了, 在此分享一下

0x0 前言

QQ截圖是我用過的最好用的截圖工具, 由于基本不在電腦上登QQ了, 于是就想將其提取出獨立版
目前除了屏幕錄制功能其他都逆出來了, 在此分享一下, 源碼見附件, 成品太大了放網(wǎng)盤了

(其他功能的效果展示請移步下一個帖子 逆向并提取QQ截圖--OCR和其他功能)

0x1 環(huán)境

版本: QQ 9.5.4.28063

0x2 從COM入手

網(wǎng)上搜一搜就知道QQ歷年版本的截圖功能都放在了Camera.dll里, IDA打開Camera.dll看一下導(dǎo)出表:

Camera_Export

(圖 2-1)

大概率是通過COM組件的方式去調(diào)用截圖功能, 那么必然會去調(diào)用CoCreateInstance獲取類的實例, 但是在CoCreateInstance下斷是斷不下來的, 后面可以知道QQ在Common.dll中自己實現(xiàn)了CoCreateInstance函數(shù), 也就是無注冊表的COM調(diào)用

CoCreateInstance的內(nèi)部實現(xiàn)是這樣的:

CoCreateInstance(....)
{
    //.......
    IClassFactory *pClassFactory=NULL;
    //↓內(nèi)部調(diào)用DllGetClassObject
    CoGetClassObject(CLSID_Object, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void **)&pClassFactory);
    pClassFactory->CreateInstance(NULL, IID_IUnknown, (void**)&pUnk);
    pClassFactory->Release();
    //........
}

無論如何都會調(diào)用DllGetClassObject獲取類廠指針

于是在Camera的DllGetClassObject下斷看一下調(diào)用棧:

callstack1

(圖2-2)

顯然截圖的命令是被asynctask異步分發(fā)過來的, 那么appframework模塊可能就是調(diào)用源頭了

0x3 分析調(diào)用棧

基址:camera=67CA0000, common=71860000, appframework=6BE40000

看到common.7183713那個調(diào)用棧函數(shù), IDA分析一下:

CoCreateInstanceWithDllname

(圖 3-1)
動態(tài)調(diào)試一下就是知道這個函數(shù)就是QQ自己實現(xiàn)的CoCreateInstance

 common.719DB0A9:

sc_call
(圖 3-2) 

一直分析到appframework.68EEE54A:

call_source
(圖 3-3) 

所以直接call (AppFramework+AE46D)函數(shù)(也就是圖3-3), 就可以調(diào)用截圖了, 當(dāng)然應(yīng)該也可以去調(diào)圖3-2中的v33(v21, v25, v4, v20), 但是調(diào)appframework的話, 一些初始化啊, 析構(gòu)的方法就不需要我們?nèi)ゲ傩脑倌M調(diào)用了
我采用的方式是模擬整個(AppFramework+AE46D)函數(shù), 當(dāng)然直接call應(yīng)該也可以, 但是我一開始直接call的時候發(fā)現(xiàn)sub_5081B982(&v17)那個函數(shù)總是返回NULL, 下面自然也就不會執(zhí)行了, 后來才發(fā)現(xiàn)需要初始化PlatformCore

0x4 初始化PlatformCore

在逆向過程中經(jīng)常會發(fā)現(xiàn)程序會去調(diào)用類似下圖的代碼:
getplatformcore
(圖 4-1)
看一下Common.dll的導(dǎo)出表:
common_platform
(圖 4-2) 

因為幾乎所有函數(shù)的調(diào)用棧都會經(jīng)HummerEngine.dll所以去這個dll里看了看, 還真就發(fā)現(xiàn)了初始化過程:

hummer_init
(圖 4-3)

直接仿著反編譯結(jié)果寫一份!:

typedef long (WINAPI *LPFN_Util_Com_CreateObjectFromDllFile)(wchar_t const *, struct _GUID const &, struct _GUID const &, void * *, struct IUnknown *);
typedef int (__cdecl *LPFN_Util_CoreCenter_InitPlatform)(wchar_t *);
typedef int (__cdecl *LPFN_Util_Boot_InitPlatformI18NConfig)(void);
 
HRESULT res = 0;
LPFN_Util_Com_CreateObjectFromDllFile lpfnCreateObjectFromDllFile = (LPFN_Util_Com_CreateObjectFromDllFile)CommonMgr.GetFuncAddr("?CreateObjectFromDllFile@Com@Util@@YGJPB_WABU_GUID@@1PAPAXPAUIUnknown@@@Z");
res = lpfnCreateObjectFromDllFile(L"Common.dll", CLSID_Common_Init, IID_ICommon_Init, (void**)(&testPtr), NULL);
 
LPFN_Util_Boot_InitPlatformI18NConfig lpfnInitPlatformI18NConfig = (LPFN_Util_Boot_InitPlatformI18NConfig)CommonMgr.GetFuncAddr("?InitPlatformI18NConfig@Boot@Util@@YAHXZ");
res = lpfnInitPlatformI18NConfig();
 
LPFN_Util_Boot_InitPlatformFileSystem lpfnInitPlatformFileSystem = (LPFN_Util_Boot_InitPlatformFileSystem)CommonMgr.GetFuncAddr("?InitPlatformFileSystem@Boot@Util@@YAHXZ");
res = lpfnInitPlatformFileSystem();
//...
//完整代碼見附件

0x41 其他初始化工作

這樣跑其實還是會崩潰, 調(diào)試一下發(fā)現(xiàn)需要SetMainAndLogicThreadId, 還是模擬一下:

/**
 * @brief 設(shè)置主線程和邏輯線程ID
 */
void InitMainAndLogicThreadId()
{
    LPFN_Util_Misc_SetMainAndLogicThreadId
    lpfnSetMainAndLogicThreadId = (LPFN_Util_Misc_SetMainAndLogicThreadId)CommonMgr.GetFuncAddr("?SetMainAndLogicThreadId@Misc@Util@@YAXKK@Z");
    lpfnSetMainAndLogicThreadId(GetCurrentThreadId(), 0);
}

0x5 模擬調(diào)用截圖!

其實還是直接仿著(AppFramework+AE46D)函數(shù)的反編譯結(jié)果寫一份就好了, 貼一下部分代碼:

// 模擬AppFramework的調(diào)用函數(shù)
DWORD *ITXData1 = NULL, *ITXData2 = NULL;
lpfnCreateTXData((void**)&ITXData1);
DWORD lpfnITXData_vtbl_func1 = *(DWORD*)(*ITXData1 + 320);
char *IDvf1_Arg2 = "type"; OLECHAR *IDvf1_Arg3_c = L"Camera";
BSTR IDvf1_Arg3 = SysAllocString(IDvf1_Arg3_c);
__asm
{
    push IDvf1_Arg3
    push IDvf1_Arg2
    push ITXData1
    call lpfnITXData_vtbl_func1
}
lpfnCreateTXData((void**)&ITXData2);
DWORD lpfnITXData_vtbl_func2 = *(DWORD*)(*ITXData2 + 240);
char *IDvf2_arg2_1 = "_Handled_", *IDvf2_arg2_2 = "_SelfHotKey_",*IDvf2_arg2_3 = "_KeyDown_";
__asm
{
    push 0
    push IDvf2_arg2_1
    push ITXData2
    call lpfnITXData_vtbl_func2
    push 1
    push IDvf2_arg2_2
    push ITXData2
    call lpfnITXData_vtbl_func2
    push 0
    push IDvf2_arg2_3
    push ITXData2
    call lpfnITXData_vtbl_func2
}
DWORD lpfnScreenShot = CommonMgr.GetDllBaseAddr() + 0x17CA30;
OLECHAR *arg2_c = L"hotkey"; BSTR arg2 = SysAllocString(arg2_c);
__asm
{
    push 0
    push ITXData2
    push ITXData1
    push arg2
    push 0
    call lpfnScreenShot
}
//printf("Call ScreenShot Func Over\n");

0x6 細(xì)節(jié)處理

保存圖片的時候會崩潰掉, 逆向調(diào)試一下發(fā)現(xiàn), 是在保存的時候:

save_crash

大概是v50+1388那里, 猜測一下這個函數(shù)是用來寫入上次保存文件路徑的, 直接patch掉好了
還有程序退出的時候也會崩潰, 我進(jìn)行了這樣的處理:

//SetCoreCenterStopState
DWORD lpCC_CreateObjectFactory = (CommonMgr.GetDllBaseAddr() + 0x248A3C);
*(DWORD*)(lpCC_CreateObjectFactory - 0x4) = 0;
*(DWORD*)lpCC_CreateObjectFactory = 1;

就是讓調(diào)用Util::CoreCenter::IsStopped()的時候返回TRUE

0x7 效果

demo

0x8 總結(jié)

這個markdown的圖片都是用提取出來QQScreenShot截圖的, 也沒發(fā)現(xiàn)內(nèi)存泄漏

相關(guān)文章

最新評論