如何获取ConnectEx()指针

时间:2017-01-19 03:08:24

标签: c++ detours

我正在使用 MS Detours ,我希望得到 ConnectEx()指针但是在运行时加载,如何获取指针并与 MS Detours ?

1 个答案:

答案 0 :(得分:1)

ConnectEx()不是导出的DLL函数。根据{{​​3}}文档:

  

注意 必须通过ConnectEx调用ConnectEx()函数,在运行时获取SIO_GET_EXTENSION_FUNCTION_POINTER函数的函数指针指定操作码。传递给WSAIoctl函数的输入缓冲区必须包含WSAID_CONNECTEX,这是一个全局唯一标识符(GUID),其值标识ConnectEx扩展函数。成功时,WSAIoctl函数返回的输出包含指向ConnectEx函数的指针。 WSAID_CONNECTEX GUIDMswsock.h头文件中定义。

例如:

#include <winsock2.h> // Must be included before Mswsock.h
#include <mswsock.h>

#pragma comment(lib, "ws2_32.lib")

...

LPFN_CONNECTEX GetConnectExPtr(SOCKET s)
{
    LPFN_CONNECTEX lpConnectEx = NULL;
    GUID guid = WSAID_CONNECTEX;
    DWORD dwNumBytes = 0;
    WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &lpConnectEx, sizeof(lpConnectEx), &dwNumBytes, NULL, NULL);
    return lpConnectEx;
}

指向ConnectEx()后,您可以绕道而行。根据您使用的MSDetours版本,您可以:

使用DetourFunction()

#include <winsock2.h> // Must be included before Mswsock.h
#include <mswsock.h>
#include <detours.h>

#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "detours.lib")

...

LPFN_CONNECTEX Real_ConnectEx = NULL;
LPFN_CONNECTEX Trampoline_ConnectEx = NULL;

BOOL WINAPI MyConnectEx(SOCKET s, const struct sockaddr *name, int namelen, PVOID lpSendBuffer, DWORD dwSendDataLength, LPDWORD lpdwBytesSent, LPOVERLAPPED lpOverlapped)
{
    // do something...
    return Trampoline_ConnectEx(s, name, namelen, lpSendBuffer, dwSendDataLength, lpdwBytesSent, lpOverlapped);
}

...

SOCKET s = ...;
Real_ConnectEx = GetConnectExPtr(s);
if (Real_ConnectEx)
{
    Trampoline_ConnectEx = (LPFN_CONNECTEX) DetourFunction((PBYTE)Real_ConnectEx, (PBYTE)MyConnectEx);
}

...

if (Trampoline_ConnectEx)
    DetourRemoveTrampoline(Trampoline_ConnectEx);

使用DetourAttach/Ex()

#include <winsock2.h> // Must be included before Mswsock.h
#include <mswsock.h>
#include <detours.h>

#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "detours.lib")
#pragma comment(lib, "detoured.lib")

...

LPFN_CONNECTEX Real_ConnectEx = NULL;
LPFN_CONNECTEX Trampoline_ConnectEx = NULL;

BOOL WINAPI MyConnectEx(SOCKET s, const struct sockaddr *name, int namelen, PVOID lpSendBuffer, DWORD dwSendDataLength, LPDWORD lpdwBytesSent, LPOVERLAPPED lpOverlapped)
{
    // do something...
    return Trampoline_ConnectEx(s, name, namelen, lpSendBuffer, dwSendDataLength, lpdwBytesSent, lpOverlapped);
}

...

SOCKET s = ...;
Real_ConnectEx = GetConnectExPtr(s);
if (Real_ConnectEx)
{
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());

    // using DetourAttach()...
    Trampoline_ConnectEx = Real_ConnectEx;
    DetourAttach((PVOID*)&Trampoline_ConnectEx, MyConnectEx);

    // using DetourAttachEx()...
    // DetourAttachEx(&Real_ConnectEx, MyConnectEx, (PDETOUR_TRAMPOLINE*)&Trampoline_ConnectEx, NULL, NULL);

    DetourTransactionCommit();
}

...

if ((Real_ConnectEx) && (Trampoline_ConnectEx))
{    
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());

    // if using DetourAttach()...
    DetourDetach((PVOID*)&Trampoline_ConnectEx, MyConnectEx);

    // if using DetourAttachEx()...
    // DetourDetach((PVOID*)&Real_ConnectEx, MyConnectEx);

    DetourTransactionCommit();
}