2012-04-08 79 views
3

我有一個應用程序,它使用Winsock 2.0 recv函數,我可以通過Redox Packet Editor捕獲輸出,例如,它確認版本是2.0。Winsock recv hooking Detours

我有這樣的代碼掛鉤函數:

#define _CRT_SECURE_NO_DEPRECATE 
#ifndef WIN32_LEAN_AND_MEAN 
#define WIN32_LEAN_AND_MEAN 
#endif 

#include <windows.h> 
#include <WinSock2.h> 
#include <detours.h> 
#include <stdio.h> 
#pragma comment(lib, "ws2_32.lib") 


FILE *pSendLogFile; 
FILE *pRecvLogFile; 

int (WINAPI *pSend)(SOCKET s, const char* buf, int len, int flags) = send; 
int WINAPI MySend(SOCKET s, const char* buf, int len, int flags); 
int (WINAPI *pRecv)(SOCKET s, char *buf, int len, int flags) = recv; 
int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags); 


INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) 
{ 
    switch(Reason) 
    { 
     case DLL_PROCESS_ATTACH: 
      DisableThreadLibraryCalls(hDLL); 

      DetourTransactionBegin(); 
      DetourUpdateThread(GetCurrentThread()); 
      DetourAttach(&(PVOID&)pSend, MySend); 
      if(DetourTransactionCommit() == NO_ERROR) 
       MessageBox(0,"send() detoured successfully","asd",MB_OK); 

      DetourTransactionBegin(); 
      DetourUpdateThread(GetCurrentThread()); 
      DetourAttach(&(PVOID&)pRecv, MyRecv); 
      if(DetourTransactionCommit() == NO_ERROR) 
       MessageBox(0,"recv() detoured successfully","asd",MB_OK); 
      break; 

    case DLL_PROCESS_DETACH: 
    case DLL_THREAD_ATTACH: 
    case DLL_THREAD_DETACH: 
     break; 
    } 
    return TRUE; 
} 


int WINAPI MySend(SOCKET s, const char* buf, int len, int flags) 
{ 
    MessageBox(0,"sent","sent",MB_OK); 
    return pSend(s, buf, len, flags); 
} 

int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags) 
{ 
    MessageBox(0,"recvd","recvd",MB_OK); 
    return pRecv(s, buf, len, flags); 
} 

對於send,一切完美,但我沒有得到任何輸出recv。我嘗試使用1.1版Winsock的另一個應用程序,它工作正常。試圖掛鉤WSARecv,WSARecvEx沒有任何運氣。

使用WinAPIOverride32檢查了應用程序,它清楚地表明它使用了recv函數,併成功記錄了使用情況。 Winsock Packet Editor也正在讀取數據。

任何想法?

int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags) 
{ 
    fopen_s(&pRecvLogFile, "C:\\RecvLog.txt", "a+"); 
    fprintf(pRecvLogFile, "%s\n", buf); 
    fclose(pRecvLogFile); 
    return pRecv(s, buf, len, flags); //you need to call recv first 
} 

,而不是做這樣的事情:

+1

我的建議是:寫一個LSP(Layered Service Provider)。修改其中一個LSP樣本將使您獲得更多,並且可能比掛鉤方式更具包容性。將其設想爲TDI驅動程序和朋友的替代用戶模式。 – 0xC0000022L 2012-04-09 00:17:06

+0

該LSP的任何文章或示例代碼?我希望它不那麼複雜。 – methyl 2012-04-09 08:34:12

+0

當然,這個大部分仍然有效:https://www.microsoft.com/msj/0599/layeredservice/layeredservice.aspx,當然還有:http://msdn.microsoft.com/en-us/ library/windows/desktop/bb513664(v = vs.85).aspx – 0xC0000022L 2012-04-09 11:50:07

回答

3

你確定你在鉤正確的dll嗎?我會仔細檢查程序實際使用的是哪個dll:WSOCK32.dll或ws2_32.dll。

編輯:

也許嘗試這樣的事:

typedef int (WINAPI *SendPtr)(SOCKET s, const char* buf, int len, int flags); 
HMODULE hLib = LoadLibrary("wsock32.dll"); 
SendPtr pSend = (SendPtr)GetProcAddress(hLib, "send"); 

然後使用pSend與值(recv的同樣的事情)。不要忘記最後調用FreeLibrary。 如果您確定該dll已經被加載,那麼最好使用GetModuleHandle("wsock32.dll"),因爲在這種情況下您不必調用FreeLibrary。

+0

是的,我檢查了它,並試圖將注入dll中的頭文件和lib更改爲winsock32沒有任何結果。 – methyl 2012-04-12 08:40:05

+0

我認爲這是很好的跟蹤,因爲在EasyHook中我必須將'[Dllimport]'設置爲'wsock32.dll'而不是'ws2_32.dll'。如何在少走彎路? – methyl 2012-04-16 12:10:19

+0

你說得對,但Ivarpoiss第一次有確切的解決方案,所以賞金是他的。感謝幫助! – methyl 2012-04-17 17:02:03

1

您的問題從嘗試寫了一個空的(或甚至未初始化的緩衝區)莖

int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags) 
{ 
    int read = pRecv(s, buf, len, flags); 
    if(read <= 0) 
    { 
     //read error/connection closed 
     return read; 
    } 

    fopen_s(&pRecvLogFile, "C:\\RecvLog.txt", "a+"); 
    fwrite(buf,sizeof(char),read,pRecvLogFile); 
    fclose(pRecvLogFile); 
    return read; 
} 

作爲一個次要問題,你似乎是假設發送或接收的數據純粹是基於字符串的,但通常數據包可能包含零字節,這會過早地結束fprintf輸出,您應該使用fwrite,而不是傳遞發送/接收大小(這也是我mplies以二進制模式打開文件)。

+0

不要認爲這是一個問題,發送工作正常,看起來相同,嘗試通過MessageBox調試它作爲MyRecv中的第一個調用,沒有顯示一個應用程序,另一方面一切正常 - 消息顯示和數據被傾倒。 – methyl 2012-04-09 06:41:16

+0

@methyl:但'send' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * send * '。通過調試器tbh來運行這將是一個好主意。 – Necrolis 2012-04-09 08:59:31

+0

但是,問題是功能不能繞道。該日誌甚至沒有創建。 – methyl 2012-04-09 09:06:37

1

我想你應該一定使用GetProcAddress來獲取鉤子的地址。

喜歡的東西:

int (WINAPI *pRecv)(SOCKET s, char *buf, int len, int flags) = GetProcAddress(GetModuleHandle("ws2_32.dll"), "recv");

編譯器可以拿出從「recv的」加載了該DLL的一個各類野生路線。所以這兩個地址可能有所不同。要測試是否是這種情況,只需使用recv從你的DLL。

您可能還想關注ReadFile/WriteFile。

並且也期望掛鉤是不可靠的。例如,目標可以隨意移除鉤子並做更多事情。

+0

Downvote複製我的解決方案。 – newgre 2012-04-18 12:19:22