4

Winsock 2.0recv関数を使用するアプリケーションがあり、たとえばRedox Packet Editorで出力をキャッチできます。これにより、バージョンが2.0であることが確認されます。

関数をフックするための次のコードがあります。

#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。Winsockの1.1バージョンを使用して別のアプリケーションで試しましたが、問題なく動作します。WSARecv、WSARecvExを運がなくフックしようとしました。

WinAPIOverride32でアプリを確認したところ、recv関数を使用していることが明確に示され、使用状況が正常にログに記録されました。WinsockPacketEditorもデータをよく読み取っています。

何か案は?

4

3 に答える 3

4

正しい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を呼び出す必要がないため、おそらく使用することをお勧めします。

于 2012-04-11T22:46:30.363 に答える
1

問題は、空の(または初期化されていないバッファ)を書き出そうとすることに起因します。

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
}

代わりに、次のようなことを行います。

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、代わりに送信/受信サイズを渡す必要があります(これは、ファイルをバイナリモードで開くことも意味します)。

于 2012-04-09T06:08:42.417 に答える
0

フックするアドレスを取得するには、確かにGetProcAddressを使用する必要があると思います。

何かのようなもの:

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

コンパイラは、「recv」からdllがロードされたルートまでのあらゆる種類のワイルドルートを考え出すことができます。したがって、これら2つのアドレスは異なる場合があります。その場合をテストするには、dllのrecvを使用します。

また、ReadFile/WriteFileにも注意を払うことをお勧めします。

また、フッキングの信頼性が低いことも期待してください。たとえば、ターゲットはフックを自由に削除して、さらに多くのことを実行できます。

于 2012-04-16T21:35:07.573 に答える