六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

使用HOOK攔截封包原理

[摘要]截獲API是個很有用的東西,比如你想分析一下別人的程序是怎樣工作的。這里我介紹一下一種我自己試驗通過的方法。 首先,我們必須設法把自己的代碼放到目標程序的進程空間里去。Windows Hook可以幫我們實現這一點。SetWindowsHookEx的聲明如下: HHOOK SetWindowsHoo...
截獲API是個很有用的東西,比如你想分析一下別人的程序是怎樣工作的。這里我介紹一下一種我自己試驗通過的方法。
首先,我們必須設法把自己的代碼放到目標程序的進程空間里去。Windows Hook可以幫我們實現這一點。SetWindowsHookEx的聲明如下:
HHOOK SetWindowsHookEx(
int idHook, // hook type
HOOKPROC lpfn, // hook procedure
HINSTANCE hMod, // handle to application instance
DWORD dwThreadId // thread identifier
);
具體的參數含義可以翻閱msdn,沒有msdn可謂寸步難行。
這里Hook本身的功能并不重要,我們使用它的目的僅僅只是為了能夠讓Windows把我們的代碼植入別的進程里去。hook Type我們任選一種即可,只要保證是目標程序肯定會調用到就行,這里我用的是WH_CALLWNDPROC。lpfn和hMod分別指向我們的鉤子代碼及其所在的dll,dwThreadId設為0,表示對所有系統內的線程都掛上這樣一個hook,這樣我們才能把代碼放到別的進程里去。

之后,我們的代碼就已經進入了系統內的所有進程空間了。必須注意的是,我們只需要截獲我們所關心的目標程序的調用,因此還必須區分一下進程號。我們自己的鉤子函數中,第一次運行將進行最重要的API重定向的工作。也就是通過將所需要截獲的API的開頭幾個字節改為一個跳轉指令,使其跳轉到我們的API中來。這是最關鍵的部分。這里我想截三個調用,ws2_32.dll中的send和recv、user32.dll中的GetMessageA。

DWORD dwCurrentPID = 0;
HHOOK hOldHook = NULL;
DWORD pSend = 0;
DWORD pRecv = 0;
GETMESSAGE pGetMessage = NULL;

BYTE btNewBytes[8] = { 0x0B8, 0x0, 0x0, 0x40, 0x0, 0x0FF, 0x0E0, 0 };
DWORD dwOldBytes[3][2];

HANDLE hDebug = INVALID_HANDLE_value;

LRESULT CALLBACK CallWndProc( int nCode, WPARAM wParam, LPARAM lParam )
{
DWORD dwSize;
DWORD dwPIDWatched;
HMODULE hLib;

if( dwCurrentPID == 0 )
{
dwCurrentPID = GetCurrentProcessId();
HWND hwndMainHook;
hwndMainHook = ::FindWindow( 0, "MainHook" );
dwPIDWatched = ::SendMessage( hwndMainHook, (WM_USER+100), 0, 0 );
hOldHook = (HHOOK)::SendMessage( hwndMainHook, (WM_USER+101), 0, 0 );

if( dwCurrentPID == dwPIDWatched )
{
hLib = LoadLibrary( "ws2_32.dll" );
pSend = (DWORD)GetProcAddress( hLib, "send" );
pRecv = (DWORD)GetProcAddress( hLib, "recv" );

::ReadProcessMemory( INVALID_HANDLE_value, (void *)pSend, (void *)dwOldBytes[0], sizeof(DWORD)*2, &dwSize );
*(DWORD *)( btNewBytes + 1 ) = (DWORD)new_send;
::WriteProcessMemory( INVALID_HANDLE_value, (void *)pSend, (void *)btNewBytes, sizeof(DWORD)*2, &dwSize );

::ReadProcessMemory( INVALID_HANDLE_value, (void *)pRecv, (void *)dwOldBytes[1], sizeof(DWORD)*2, &dwSize );
*(DWORD *)( btNewBytes + 1 ) = (DWORD)new_recv;
::WriteProcessMemory( INVALID_HANDLE_value, (void *)pRecv, (void *)btNewBytes, sizeof(DWORD)*2, &dwSize );

hLib = LoadLibrary( "user32.dll" );
pGetMessage = (GETMESSAGE)GetProcAddress( hLib, "GetMessageA" );
::ReadProcessMemory( INVALID_HANDLE_value, (void *)pGetMessage, (void *)dwOldBytes[2], sizeof(DWORD)*2, &dwSize );
*(DWORD *)( btNewBytes + 1 ) = (DWORD)new_GetMessage;
::WriteProcessMemory( INVALID_HANDLE_value, (void *)pGetMessage, (void *)btNewBytes, sizeof(DWORD)*2, &dwSize );

hDebug = ::CreateFile( "C:\\Trace.log", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 );
}
}

if( hOldHook != NULL )
{
return CallNextHookEx( hOldHook, nCode, wParam, lParam );
}

return 0;
}

上面的鉤子函數,只有第一次運行時有用,就是把三個函數的首8字節修改一下(實際上只需要7個)。btNewBytes中的指令實際就是
mov eax, 0x400000
jmp eax
這里的0x400000就是新的函數的地址,比如new_recv/new_send/new_GetMessage,此時,偷梁換柱已經完成。再看看我們的函數中都干了些什么。以GetMessageA為例:

BOOL _stdcall new_GetMessage( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax )
{
DWORD dwSize;
char szTemp[256];
BOOL r = false;

//Watch here before it's executed.
sprintf( szTemp, "Before GetMessage : HWND 0x%8.8X, msgMin 0x%8.8X, msgMax 0x%8.8x \r\n", hWnd, wMsgFilterMin, wMsgFilterMax );
::WriteFile( hDebug, szTemp, strlen(szTemp), &dwSize, 0 );
//Watch over

// restore it at first
::WriteProcessMemory( INVALID_HANDLE_value, (void *)pGetMessage, (void *)dwOldBytes[2], sizeof(DWORD)*2, &dwSize );

// execute it
r = pGetMessage( lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax );

// hook it again
*(DWORD *)( btNewBytes + 1 ) = (DWORD)new_GetMessage;
::WriteProcessMemory( INVALID_HANDLE_value, (void *)pGetMessage, (void *)btNewBytes, sizeof(DWORD)*2, &dwSize );

//Watch here after it's executed
sprintf( szTemp, "Result of GetMessage is %d.\r\n", r );
::WriteFile( hDebug, szTemp, strlen( szTemp ), &dwSize, 0 );
if( r )
{
sprintf( szTemp, "Msg : HWND 0x%8.8X, MSG 0x%8.8x, wParam 0x%8.8X, lParam 0x%8.8X\r\nTime 0x%8.8X, X %d, Y %d\r\n",
lpMsg->hwnd, lpMsg->message,
lpMsg->wParam, lpMsg->lParam, lpMsg->time,
lpMsg->pt.x, lpMsg->pt.y );
::WriteFile( hDebug, szTemp, strlen( szTemp ), &dwSize, 0 );
}
strcpy( szTemp, "\r\n" );
::WriteFile( hDebug, szTemp, strlen( szTemp ), &dwSize, 0 );

//Watch over

return r;
}

先將截獲下來的參數,寫入到一個log文件中,以便分析。然后恢復原先保留下來的GetMessageA的首8字節,然后執行真正的GetMessageA調用,完畢后再將執行結果也寫入log文件,然后將GetMessageA的執行結果返回給調用者。
整個截獲的過程就是這樣。你可以把其中的寫log部分改成你自己想要的操作。這里有個不足的地方是,截獲動作是不能夠并發進行的,如果目標進程是多線程的,就會有問題。解決辦法是,可以在每次new_GetMessage中加入一個CriticalSection的鎖和解鎖,以使調用變為串行進行,但這個我沒有試驗過。 


主站蜘蛛池模板: 亚洲午夜精品一级在线 | 青春草在线免费视频 | 伊人中文字幕在线观看 | 四虎tv| 欧美亚洲综合网 | 日韩新片在线观看 | 五月激情婷婷综合 | 亚洲欧美中文日韩v在线观看 | 综合激情婷婷 | 色香天天| 日本大片免a费观看在线 | 亚洲爱爱网站 | 在线污污视污免费 | 日本青草视频 | 搜索黄色毛片 | 日本高清在线视频www色下载 | 日韩污网站 | 欧美一级淫片aaaaaaa视频 | 夜夜夜夜夜夜夜工噜噜噜 | 日韩精品一区二区三区乱码 | 我想看一级毛片免费的 | 日日夜夜国产 | 在线视频欧美亚洲 | 一区二区三区在线免费视频 | 全黄大全大色全免费大片 | 日韩伦理一区二区三区 | 日操夜操 | 在线青草 | 四虎成人在线视频 | 亚洲综合精品一二三区在线 | 日本激情视频一区二区三区 | 青娱乐极品视频在线 | 青草久久久 | 日韩毛片免费在线观看 | 色综合久久天天综合观看 | 偷偷操不一样的久久 | 日本精品久久久久久久 | 四虎影视在线永久免费观看 | 日日摸夜夜搂人人要 | 天天晚上干白天干 | 亚洲第一男人网站 |