C++ - 绕道WinSock Hooking

发布于 2024-07-19 08:21:24 字数 6569 浏览 12 评论 0原文

我想做的是使用 Detours 库 挂钩应用程序 WinSock2 send() 和 receive() 函数(数据包记录器)。

虽然它确实适用于 send() 函数,但它不适用于 receive() 函数。

这是我的相关代码:

#include <cstdio>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <string>
#include <windows.h>
#include <detours.h>

#pragma comment( lib, "Ws2_32.lib" )
#pragma comment( lib, "detours.lib" )
#pragma comment( lib, "detoured.lib" )
#pragma comment( lib, "Mswsock.lib" )

std::ofstream Logger;

std::string NowToString() {
    time_t rawtime;
    tm *timeinfo = new tm();
    char buffer[32];

    time( &rawtime );
    localtime_s( timeinfo, &rawtime );

    strftime( buffer, 32, "%m/%d/%Y %I:%M:%S %p", timeinfo );

    delete timeinfo;

    return std::string( buffer );
}

std::string TimeToString() {
    time_t rawtime;
    tm *timeinfo = new tm();
    char buffer[32];

    time( &rawtime );
    localtime_s( timeinfo, &rawtime );

    strftime( buffer, 32, "%I:%M:%S %p", timeinfo );

    delete timeinfo;

    return std::string( buffer );
}

void LogPacket( const char *buf, int len ) {
    Logger << "        0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F\n";
    Logger << "       -- -- -- -- -- -- -- --  -- -- -- -- -- -- -- --\n";
    Logger << "0000   ";

    for ( int i = 0; i < len; ++i ) {
        if ( i != 0 && i % 16 == 0 ) {
            Logger << "  ";

            int line = ( i / 16 ) - 1;

            for ( int j = 0; j < 16; ++j ) {
                char c = buf[line * 16 + j];

                if ( c >= 32 && c <= 126 ) {
                    Logger << c;
                } else {
                    Logger << '.';
                }
            }

            Logger << "\n" << std::hex << std::setw( 4 ) << std::setfill( '0' ) << i << std::dec << std::setw( 0 ) << "   ";
        } else if ( i % 16 == 8 ) {
            Logger << ' ';
        }

        Logger << std::hex << std::setw( 2 ) << std::setfill( '0' ) << ( int( buf[i] ) & 0xFF ) << ' ';
        Logger << std::dec << std::setw( 0 );

        if ( i == len - 1 ) {
            int remaining = 16 - ( len % 16 );
            int fill = ( remaining * 3 ) + 2;

            if ( remaining >= 8 ) {
                ++fill;
            }

            for ( int j = 0; j < fill; ++j ) {
                Logger << ' ';
            }

            int line = ( i - ( ( len % 16 ) - 1 ) ) / 16 ;

            for ( int k = 0; k < ( len % 16 ); ++k ) {
                char c = buf[line * 16 + k];

                if ( c >= 32 && c <= 126 ) {
                    Logger << c;
                } else {
                    Logger << '.';
                }
            }
        }
    }

    Logger << "\n\n";
}

int ( WINAPI *Real_Send )( SOCKET s, const char *buf, int len, int flags ) = send;
int ( WINAPI *Real_Recv )( SOCKET s, char *buf, int len, int flags ) = recv;
int ( WINAPI *Real_RecvFrom )( SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen ) = recvfrom;
int ( WINAPI *Real_WSARecvEx )( SOCKET s, char *buf, int len, int *flags ) = WSARecvEx;

int WINAPI Mine_Send( SOCKET s, const char* buf, int len, int flags );
int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags );
int WINAPI Mine_RecvFrom( SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen );
int WINAPI Mine_WSARecvEx( SOCKET s, char *buf, int len, int *flags );

int WINAPI Mine_Send( SOCKET s, const char *buf, int len, int flags ) {
    Logger << TimeToString() << ": Client -> Server (Length: " << len << " bytes)\n\n";
    LogPacket( buf, len );
    Logger << std::endl;

    return Real_Send( s, buf, len, flags );
}

int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags ) {
    Logger << TimeToString() << ": Server -> Client (Length: " << len << " bytes)\n\n";
    LogPacket( buf, len );
    Logger << std::endl;

    return Real_Recv( s, buf, len, flags );
}

int WINAPI Mine_RecvFrom( SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen ) {
    Logger << TimeToString() << ": Server -> Client (Length: " << len << " bytes)*\n\n";
    LogPacket( buf, len );
    Logger << std::endl;

    return Real_RecvFrom( s, buf, len, flags, from, fromlen );
}

int WINAPI Mine_WSARecvEx( SOCKET s, char *buf, int len, int *flags ) {
    Logger << TimeToString() << ": Server -> Client (Length: " << len << " bytes)**\n\n";
    LogPacket( buf, len );
    Logger << std::endl;

    return Real_WSARecvEx( s, buf, len, flags );
}

BOOL WINAPI DllMain( HINSTANCE, DWORD dwReason, LPVOID ) {
    switch ( dwReason ) {
        case DLL_PROCESS_ATTACH:    
            Logger.open( "C:\\Packets.txt", std::ios::out | std::ios::app | std::ios::ate );

            if ( Logger.tellp() > 0 ) {
                Logger << "\n\n\n";
            }

            Logger << "##\n## Logging Started (" << NowToString() << ")\n##\n\n\n";

            DetourTransactionBegin();
            DetourUpdateThread( GetCurrentThread() );
            DetourAttach( &(PVOID &)Real_Send, Mine_Send );
            DetourAttach( &(PVOID &)Real_Recv, Mine_Recv );
            DetourAttach( &(PVOID &)Real_RecvFrom, Mine_RecvFrom );
            DetourAttach( &(PVOID &)Real_WSARecvEx, Mine_WSARecvEx );
            DetourTransactionCommit();

            break;

        case DLL_PROCESS_DETACH:
            Logger << "##\n## Logging Stopped (" << NowToString() << ")\n##";
            Logger.close();

            DetourTransactionBegin();
            DetourUpdateThread( GetCurrentThread() );
            DetourDetach( &(PVOID &)Real_Send, Mine_Send );
            DetourDetach( &(PVOID &)Real_Recv, Mine_Recv );
            DetourDetach( &(PVOID &)Real_RecvFrom, Mine_RecvFrom );
            DetourDetach( &(PVOID &)Real_WSARecvEx, Mine_WSARecvEx );
            DetourTransactionCommit();

            break;
    }

    return TRUE;
}

有什么想法吗?

编辑:所以我也挂钩了recvfrom()和WSARecvEx(),但它仍然不记录传出的数据包! 我已经用我的确切代码更新了我的代码。

What I am trying to do is use the Detours library to hook into an applications WinSock2 send() and recv() functions (a packet logger).

While it does work for the send() function, it does not, however, work for the recv() function.

Here is my relevant code:

#include <cstdio>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <string>
#include <windows.h>
#include <detours.h>

#pragma comment( lib, "Ws2_32.lib" )
#pragma comment( lib, "detours.lib" )
#pragma comment( lib, "detoured.lib" )
#pragma comment( lib, "Mswsock.lib" )

std::ofstream Logger;

std::string NowToString() {
    time_t rawtime;
    tm *timeinfo = new tm();
    char buffer[32];

    time( &rawtime );
    localtime_s( timeinfo, &rawtime );

    strftime( buffer, 32, "%m/%d/%Y %I:%M:%S %p", timeinfo );

    delete timeinfo;

    return std::string( buffer );
}

std::string TimeToString() {
    time_t rawtime;
    tm *timeinfo = new tm();
    char buffer[32];

    time( &rawtime );
    localtime_s( timeinfo, &rawtime );

    strftime( buffer, 32, "%I:%M:%S %p", timeinfo );

    delete timeinfo;

    return std::string( buffer );
}

void LogPacket( const char *buf, int len ) {
    Logger << "        0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F\n";
    Logger << "       -- -- -- -- -- -- -- --  -- -- -- -- -- -- -- --\n";
    Logger << "0000   ";

    for ( int i = 0; i < len; ++i ) {
        if ( i != 0 && i % 16 == 0 ) {
            Logger << "  ";

            int line = ( i / 16 ) - 1;

            for ( int j = 0; j < 16; ++j ) {
                char c = buf[line * 16 + j];

                if ( c >= 32 && c <= 126 ) {
                    Logger << c;
                } else {
                    Logger << '.';
                }
            }

            Logger << "\n" << std::hex << std::setw( 4 ) << std::setfill( '0' ) << i << std::dec << std::setw( 0 ) << "   ";
        } else if ( i % 16 == 8 ) {
            Logger << ' ';
        }

        Logger << std::hex << std::setw( 2 ) << std::setfill( '0' ) << ( int( buf[i] ) & 0xFF ) << ' ';
        Logger << std::dec << std::setw( 0 );

        if ( i == len - 1 ) {
            int remaining = 16 - ( len % 16 );
            int fill = ( remaining * 3 ) + 2;

            if ( remaining >= 8 ) {
                ++fill;
            }

            for ( int j = 0; j < fill; ++j ) {
                Logger << ' ';
            }

            int line = ( i - ( ( len % 16 ) - 1 ) ) / 16 ;

            for ( int k = 0; k < ( len % 16 ); ++k ) {
                char c = buf[line * 16 + k];

                if ( c >= 32 && c <= 126 ) {
                    Logger << c;
                } else {
                    Logger << '.';
                }
            }
        }
    }

    Logger << "\n\n";
}

int ( WINAPI *Real_Send )( SOCKET s, const char *buf, int len, int flags ) = send;
int ( WINAPI *Real_Recv )( SOCKET s, char *buf, int len, int flags ) = recv;
int ( WINAPI *Real_RecvFrom )( SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen ) = recvfrom;
int ( WINAPI *Real_WSARecvEx )( SOCKET s, char *buf, int len, int *flags ) = WSARecvEx;

int WINAPI Mine_Send( SOCKET s, const char* buf, int len, int flags );
int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags );
int WINAPI Mine_RecvFrom( SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen );
int WINAPI Mine_WSARecvEx( SOCKET s, char *buf, int len, int *flags );

int WINAPI Mine_Send( SOCKET s, const char *buf, int len, int flags ) {
    Logger << TimeToString() << ": Client -> Server (Length: " << len << " bytes)\n\n";
    LogPacket( buf, len );
    Logger << std::endl;

    return Real_Send( s, buf, len, flags );
}

int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags ) {
    Logger << TimeToString() << ": Server -> Client (Length: " << len << " bytes)\n\n";
    LogPacket( buf, len );
    Logger << std::endl;

    return Real_Recv( s, buf, len, flags );
}

int WINAPI Mine_RecvFrom( SOCKET s, char *buf, int len, int flags, sockaddr *from, int *fromlen ) {
    Logger << TimeToString() << ": Server -> Client (Length: " << len << " bytes)*\n\n";
    LogPacket( buf, len );
    Logger << std::endl;

    return Real_RecvFrom( s, buf, len, flags, from, fromlen );
}

int WINAPI Mine_WSARecvEx( SOCKET s, char *buf, int len, int *flags ) {
    Logger << TimeToString() << ": Server -> Client (Length: " << len << " bytes)**\n\n";
    LogPacket( buf, len );
    Logger << std::endl;

    return Real_WSARecvEx( s, buf, len, flags );
}

BOOL WINAPI DllMain( HINSTANCE, DWORD dwReason, LPVOID ) {
    switch ( dwReason ) {
        case DLL_PROCESS_ATTACH:    
            Logger.open( "C:\\Packets.txt", std::ios::out | std::ios::app | std::ios::ate );

            if ( Logger.tellp() > 0 ) {
                Logger << "\n\n\n";
            }

            Logger << "##\n## Logging Started (" << NowToString() << ")\n##\n\n\n";

            DetourTransactionBegin();
            DetourUpdateThread( GetCurrentThread() );
            DetourAttach( &(PVOID &)Real_Send, Mine_Send );
            DetourAttach( &(PVOID &)Real_Recv, Mine_Recv );
            DetourAttach( &(PVOID &)Real_RecvFrom, Mine_RecvFrom );
            DetourAttach( &(PVOID &)Real_WSARecvEx, Mine_WSARecvEx );
            DetourTransactionCommit();

            break;

        case DLL_PROCESS_DETACH:
            Logger << "##\n## Logging Stopped (" << NowToString() << ")\n##";
            Logger.close();

            DetourTransactionBegin();
            DetourUpdateThread( GetCurrentThread() );
            DetourDetach( &(PVOID &)Real_Send, Mine_Send );
            DetourDetach( &(PVOID &)Real_Recv, Mine_Recv );
            DetourDetach( &(PVOID &)Real_RecvFrom, Mine_RecvFrom );
            DetourDetach( &(PVOID &)Real_WSARecvEx, Mine_WSARecvEx );
            DetourTransactionCommit();

            break;
    }

    return TRUE;
}

Any ideas?

EDIT: So I've hooked recvfrom(), and WSARecvEx() as well, and it still doesn't log the outgoing packets! I've updated my code with my exact code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

久而酒知 2024-07-26 08:21:24

要有效地使用挂钩,您需要确保真正挂钩所有相关端点或至少确保最终从所有端点调用一个共同点。
对于 recv() ,我认为应用程序实际上可能调用 WSARecv()
您可以使用 depends.exe 来准确找出应用程序/库从 Ws2_32.dll 导入哪些函数知道你需要钩住哪些。

To use hooking effectively you need to make sure you really hook all of the relevant endpoints or atleast a common denominator that is ensured to be called eventually from all of them.
In the case of recv() I think its possible that the application actually calls WSARecv() instead.
You can use depends.exe to find out exactly what functions does the application/library import from Ws2_32.dll to know which ones you need to hook.

游魂 2024-07-26 08:21:24

好吧,几个月后我想通了:当我应该挂钩 WinSock 1.1 的 send()/recv() 时,我却挂钩了 WinSock 2 函数!

Well, a few months later I figured it out: I was hooking WinSock 2 functions when I should have been hooking WinSock 1.1's send()/recv()!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文