• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運(yùn)轉(zhuǎn),開(kāi)心的工作
            簡(jiǎn)單、開(kāi)放、平等的公司文化;尊重個(gè)性、自由與個(gè)人價(jià)值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            ? Windows下Hook API技術(shù) inline hook 收藏

            ? 什么叫Hook API?所謂Hook就是鉤子的意思,而API是指 Windows開(kāi)放給程序員的編程接口,使得在用戶級(jí)別下可以對(duì)操作系統(tǒng)進(jìn)行控制,也就是一般的應(yīng)用程序都需要調(diào)用API來(lái)完成某些功能, Hook API的意思就是在這些應(yīng)用程序調(diào)用真正的系統(tǒng)API前可以先被截獲,從而進(jìn)行一些處理再調(diào)用真正的API來(lái)完成功能。在講Hook API之 前先來(lái)看一下如何Hook消息,例如Hook全局鍵盤(pán)消息,從而可以知道用戶按了哪些鍵,這種Hook消息的功能可以由以下函數(shù)來(lái)完成,該函數(shù)將一個(gè)新的 Hook加入到原來(lái)的Hook鏈中,當(dāng)某一消息到達(dá)后會(huì)依次經(jīng)過(guò)它的Hook鏈再交給應(yīng)用程序。HHOOK SetWindowsHookEx(
            ???? int idHook,????????????????????? //Hook類型,例如WH_KEYBOARD,WH_MOUSE
            ???? HOOKPROC lpfn,????????????? //Hook處理過(guò)程函數(shù)的地址
            ???? HINSTANCE hMod,?????????? //包含Hook處理過(guò)程函數(shù)的dll句柄(若在本進(jìn)程可以為NULL)
            ???? DWORD dwThreadId,????? //要Hook的線程ID,若為0,表示全局Hook所有
            );???? 這里需要提一下的就是如果是Hook全局的而不是某個(gè)特定的進(jìn)程則需要將Hook過(guò)程編寫(xiě)為一個(gè)DLL,以便讓任何程序都可以加載它來(lái)獲取Hook過(guò)程函 數(shù)。???? 而對(duì)于Hook API微軟并沒(méi)有提供直接的接口函數(shù),也許它并不想讓我們這樣做, 不過(guò)有2種方法可以完成該功能。第一種,修改可執(zhí)行文件的IAT表(即輸入表),因?yàn)樵谠摫碇杏涗浟怂姓{(diào)用API的函數(shù)地址,則只需將這些地址改為自己 函數(shù)的地址即可,但是這樣有一個(gè)局限,因?yàn)橛械某绦驎?huì)加殼,這樣會(huì)隱藏真實(shí)的IAT表,從而使該方法失效。第二種方法是直接跳轉(zhuǎn),改變API函數(shù)的頭幾個(gè) 字節(jié),使程序跳轉(zhuǎn)到自己的函數(shù),然后恢復(fù)API開(kāi)頭的幾個(gè)字節(jié),在調(diào)用AP完成功能后再改回來(lái)又能繼續(xù)Hook了,但是這種方法也有一個(gè)問(wèn)題就是同步的問(wèn) 題,當(dāng)然這是可以克服的,并且該方法不受程序加殼的限制。???? 下面將以一個(gè)Hook指定程序send函數(shù)的例子來(lái)詳細(xì)描述如何Hook API,以達(dá)到監(jiān)視程序發(fā)送的每個(gè)封包的目的。采用的是第二種方法,編寫(xiě)為一個(gè)dll。首先是一些全局聲明,//本dll的handle
            HANDLE g_hInstance = NULL;
            //修改API入口為 mov eax, 00400000;jmp eax是程序能跳轉(zhuǎn)到自己的函數(shù)
            BYTE g_btNewBytes[8] = { 0xB8, 0x0, 0x0, 0x40, 0x0, 0xFF, 0xE0, 0x0 };
            // 保存原API入口的8個(gè)字節(jié)
            DWORD g_dwOldBytes[2][2] = { 0x0, 0x0, 0x0, 0x0 };
            // 鉤子句柄
            HHOOK??? g_hOldHook = NULL;
            //API中send函數(shù)的地址
            DWORD g_pSend = 0;
            //事務(wù),解決同步問(wèn)題
            HANDLE g_hSendEvent = NULL;//自己的send函數(shù)地址,參數(shù)必須與API的send函數(shù)地址相同int _stdcall hook_send( SOCKET s, const char *buf, int len, int flags );//要Hook的進(jìn)程和主線程ID號(hào)DWORD g_dwProcessID = 0;
            DWORD g_dwThreadID = 0;???? 從聲明可以看出,我們會(huì)把API函數(shù)的首8個(gè)字節(jié)改為 mov eax, 00400000;jmp eax ,使程序能夠跳轉(zhuǎn),只需獲取我們自己的函數(shù) 地址填充掉00400000即可實(shí)現(xiàn)跳轉(zhuǎn)。而g_dwOldBytes是用來(lái)保存API開(kāi)頭原始的8個(gè)字節(jié),在真正執(zhí)行API函數(shù)是需要寫(xiě)回。還有一點(diǎn), 在聲明新的函數(shù)時(shí),該例中為hook_send,除了保正參數(shù)與API的一致外,還需要聲明為_(kāi)_stdcall類型,表示函數(shù)在退出前自己來(lái)清理堆棧, 因?yàn)檫@里是直接跳轉(zhuǎn)到新函數(shù)處,所以必須自己清理堆棧。下面看主函數(shù),BOOL APIENTRY DllMain( HANDLE hModule,
            ??????????????????????????????????? DWORD?? ul_reason_for_call,
            ??????????????????????????????????? LPVOID lpReserved
            ????????????????????????????????? )
            {
            ???? if(ul_reason_for_call == DLL_PROCESS_ATTACH)
            ??? {?????? //獲取本dll句柄
            ?????? g_hInstance = hModule;???????????? //創(chuàng)建事務(wù)
            ?????? g_hSendEvent = CreateEvent( NULL, FALSE, TRUE, NULL );
            ?????
            ?????? //重寫(xiě)API開(kāi)頭的8字節(jié)
            ?????? HMODULE hWsock = LoadLibrary( "wsock32.dll" );
            ?????? g_pSend = ( DWORD )GetProcAddress( hWsock, "send" );?????? //保存原始字節(jié)?????? ReadProcessMemory( INVALID_HANDLE_VALUE, ( void * )g_pSend,
            ?????????? ( void * )g_dwOldBytes[0], sizeof( DWORD )*2, NULL );?????? //將00400000改寫(xiě)為我們函數(shù)的地址
            ?????? *( DWORD* )( g_btNewBytes + 1 ) = ( DWORD )hook_send;
            ?????? WriteProcessMemory( INVALID_HANDLE_VALUE, ( void * )g_pSend,
            ?????????? ( void * )g_btNewBytes, sizeof( DWORD )*2, NULL );
            ???? }
            ???? return TRUE;
            }???? 以上是dll的main函數(shù),在被指定的程序加載的時(shí)候會(huì)自動(dòng)運(yùn)行dll的main函數(shù)來(lái)完成初始化,這里就是改寫(xiě)API的首地址來(lái)完成跳轉(zhuǎn)。當(dāng)然本程序 是對(duì)于指定程序進(jìn)行Hook,如果要進(jìn)行全局Hook,可以在main函數(shù)中用GetModuleFileName函數(shù)來(lái)獲取exe文件完整路徑,判斷當(dāng) 前進(jìn)程是否是想要Hook的進(jìn)程。寫(xiě)函數(shù)中使用INVALID_HANDLE_VALUE,表示寫(xiě)本進(jìn)程。int _stdcall hook_send( SOCKET s, const char *buf, int len, int flags )
            {
            ??? int nRet;??? WaitForSingleObject( g_hSendEvent, INFINITE );????? //恢復(fù)API頭8個(gè)字節(jié)
            ??? WriteProcessMemory( INVALID_HANDLE_VALUE, ( void* )g_pSend,
            ?????? ( void* )g_dwOldBytes[0], sizeof( DWORD )*2, NULL );??? /*??? 這里可以添加想要進(jìn)行的處理過(guò)程??? */??? //真正執(zhí)行API函數(shù)
            ??? nRet = send( s, buf, len, flags );??? //寫(xiě)入跳轉(zhuǎn)語(yǔ)句,繼續(xù)Hook
            ??? WriteProcessMemory( INVALID_HANDLE_VALUE, ( void* )g_pSend,
            ?????? ( void* )g_btNewBytes, sizeof( DWORD )*2, NULL );??? SetEvent( g_hSendEvent );??? return nRet;
            }HOOK_API BOOL StartHook(HWND hWnd)
            {???? //通過(guò)傳入的窗口句柄獲取線程句柄
            ???? g_dwThreadID = GetWindowThreadProcessId( hWnd, &g_dwProcessID );???? //WH_CALLWNDPROC類型的Hook
            ???? g_hOldHook = SetWindowsHookEx( WH_CALLWNDPROC,?? HookProc,?????????? ( HINSTANCE ) g_hInstance, g_dwThreadID );
            ???? if( g_hOldHook == NULL )
            ???????? return FALSE;
            ???? return TRUE;
            }static LRESULT WINAPI HookProc( int nCode, WPARAM wParam, LPARAM lParam )
            {
            return CallNextHookEx( g_hOldHook, nCode, wParam, lParam );
            }HOOK_API void StopHook(void)
            {
            ??? if(g_hOldHook != NULL)
            ??? {
            ??????? WaitForSingleObject( g_hSendEvent, INFINITE );
            ??????? HANDLE hProcess = NULL;
            ??????? hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, g_dwProcessID);
            ??????? DWORD dwOldProc;
            ??????? DWORD dwNewProc;??????? //改變頁(yè)面屬性為讀寫(xiě)
            ??????? VirtualProtectEx( hProcess, ( void* )g_pSend, 8, PAGE_READWRITE, &dwOldProc );??????? //恢復(fù)API的首8個(gè)字節(jié)
            ??????? WriteProcessMemory( hProcess, ( void* )g_pSend,
            ???????????? ( void* )g_dwOldBytes[0], sizeof( DWORD )*2, NULL );??????? //恢復(fù)頁(yè)面文件的屬性
            ??????? VirtualProtectEx( hProcess, ( void* )g_pSend, 8, dwOldProc, &dwNewProc );
            ?
            ??????? CloseHandle(g_hSendEvent);
            ?
            ??????? UnhookWindowsHookEx( g_hOldHook );
            ???? }
            }??? 可以看出,我們創(chuàng)建的Hook類型是WH_CALLWNDPROC類型,該類型的Hook在進(jìn)程與系統(tǒng)一通信時(shí)就會(huì)被加載到進(jìn)程空間,從而調(diào)用dll的 main函數(shù)完成真正的Hook,而在SetWindowsHookEx函數(shù)中指定的HookProc函數(shù)將不作任何處理,只是調(diào)用 CallNextHookEx將消息交給Hook鏈中下一個(gè)環(huán)節(jié)處理,因?yàn)檫@里SetWindowsHookEx的唯一作用就是讓進(jìn)程加載我們的 dll。???? 以上就是一個(gè)最簡(jiǎn)單的Hook API的例子,該種技術(shù)可以完成許多功能。例如網(wǎng)游外掛制作過(guò)程中截取發(fā)送的與收到的封包即可使用該方法,或者也可以在 Hook到API后加入木馬功能,反向連接指定的主機(jī)或者監(jiān)聽(tīng)某一端口,還有許多加殼也是用該原理來(lái)隱藏IAT表,填入自己的函數(shù)地址。

            亚洲精品无码久久毛片| 青青热久久综合网伊人| 亚洲精品无码久久久久久| 亚洲综合伊人久久综合| 久久Av无码精品人妻系列 | 久久香综合精品久久伊人| 久久偷看各类wc女厕嘘嘘| 久久精品国产亚洲网站| 久久精品亚洲欧美日韩久久| 色播久久人人爽人人爽人人片AV| 亚洲国产精品无码久久SM| 国产精品久久久久无码av| 久久996热精品xxxx| 国内精品伊人久久久久777| 国产一区二区三区久久| 四虎久久影院| 精品久久777| 久久久久青草线蕉综合超碰| 狠狠色丁香久久综合五月| 亚洲人成电影网站久久| 91精品国产色综合久久| 四虎久久影院| 久久精品免费观看| 2020久久精品亚洲热综合一本 | 日韩电影久久久被窝网| 国产亚洲色婷婷久久99精品| 久久夜色精品国产| 久久亚洲精品视频| 狠狠色婷婷久久一区二区| 99久久精品免费看国产| 热re99久久精品国99热| 久久人搡人人玩人妻精品首页| 久久久精品人妻一区二区三区蜜桃 | 久久午夜福利无码1000合集| 婷婷久久综合九色综合98| 色欲av伊人久久大香线蕉影院| 久久精品国产亚洲av瑜伽| 久久最新精品国产| 亚洲午夜久久久影院| 亚洲精品午夜国产va久久| 久久久久九九精品影院|