• <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.¢%

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

            Windows下Hook API技術 inline hook

            Posted on 2010-07-02 08:20 S.l.e!ep.¢% 閱讀(1560) 評論(0)  編輯 收藏 引用 所屬分類: RootKit

            ? Windows下Hook API技術 inline hook 收藏

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

            精品久久久久久亚洲| 精产国品久久一二三产区区别 | 2021少妇久久久久久久久久| 久久久久人妻一区精品色| 久久91精品国产91久久麻豆| 激情综合色综合久久综合| 97香蕉久久夜色精品国产 | 久久国产精品99精品国产987| 精品无码久久久久久国产| 精品伊人久久大线蕉色首页| 伊人色综合久久| 激情伊人五月天久久综合| 日韩电影久久久被窝网| 久久久91精品国产一区二区三区| 久久综合日本熟妇| 伊人久久综合热线大杳蕉下载| 久久精品国产亚洲AV影院| 久久精品国产精品亚洲| 精品国产VA久久久久久久冰| 18禁黄久久久AAA片| 国产精品热久久毛片| 久久青青草原综合伊人| 亚洲AV日韩AV天堂久久| 久久久SS麻豆欧美国产日韩| 日韩精品无码久久一区二区三| 国产精久久一区二区三区| 国产精品视频久久| 久久精品国产第一区二区三区| 狠狠精品久久久无码中文字幕| 亚洲国产成人精品91久久久| 久久精品国产只有精品66| 久久久91精品国产一区二区三区 | 中文字幕乱码久久午夜| 性做久久久久久免费观看| 久久男人中文字幕资源站| 国产福利电影一区二区三区久久久久成人精品综合 | 国内精品免费久久影院| 国产精品久久久久jk制服| 亚洲?V乱码久久精品蜜桃| 久久91精品国产91久| 亚洲国产精品无码久久九九|