使用现有的TCP连接发送数据包

Man*_*ani 0 windows tcp winsock socks

我正在使用WPE PRO,我可以捕获数据包并将其发回.我尝试使用WinSock 2(WPE PRO使用的相同的lib),但我不知道如何将数据包发送到现有的TCP连接,如WPE PRO.

http://wpepro.net/index.php?categoryid=2

我该怎么做 ?

小智 5

您是否在询问如何让其他人的程序通过其现有的Winsock连接发送数据?

我已经做到了这一点,但遗憾的是目前没有代码.如果你给我一两个小时,我可以用C做一个工作的例子;如果你需要一个让我知道,我会.

编辑:示例DLL,如果您或其他任何人想要在页面底部进行测试; 我不能.我所知道的只是它编译.您只需要下载(或编写!)一个免费的DLL注入程序来测试它; 那里有很多.

与此同时,您需要研究的是:

  1. 如何执行EXE的基础知识.
  2. DLL注入
  3. API挂钩
  4. Windows套接字API

1. EXE如何执行的基础知识:

我要向你解释的整个过程归结为这个原则.双击可执行文件时,Windows会解析它并将其代码等加载到内存中.这是关键.编译后的代码全部放入RAM中.这意味着什么?好吧,如果应用程序的代码全部在RAM中,我们是否可以通过更改部分内存来更改应用程序的代码?毕竟,这只是一堆指令.

答案是肯定的,它将为我们提供弄乱另一个应用程序的方法 - 在这种情况下,告诉它通过其打开的套接字发送一些数据.

(这个原则也是你必须小心编写像C这样的低级语言的程序的原因,因为如果你把坏东西放在RAM的坏部分,它可能会崩溃程序或打开你的shell代码漏洞).

2. DLL注入:

问题是,我们如何知道要覆盖哪个内存?我们是否可以访问该程序的内存,尤其是包含我们想要更改的指令的部分?你可以写入另一个进程的内存,但它更复杂.更改内存的最简单方法(再次,当我说内存时,我们正在谈论正在执行的机器代码指令)是通过在该进程中加载​​并运行DLL.将您的DLL视为.c文件,您可以将其添加到另一个程序并编写自己的代码:您可以访问程序的变量,调用它的函数,任何东西; 因为它在这个过程中运行.

DLL注入可以通过多种方法完成.通常是通过调用CreateRemoteThread()API函数.对此进行谷歌搜索.

3. API挂钩

什么是API挂钩?更一般地说,它是"函数挂钩",我们碰巧有兴趣挂钩API调用; 在这种情况下,用于套接字(socket(),send()等).

我们来举个例子吧.使用Winsock用C编写的目标应用程序.让我们看看他们在做什么,然后展示我们想要做的事情的一个例子:

他们创建套接字的原始源代码:

SOCKET ConnectSocket = INVALID_SOCKET;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
Run Code Online (Sandbox Code Playgroud)

现在,这是原始程序的源代码.我们的DLL无法访问它,因为它在EXE中加载并且编译了EXE(呃!).所以让我们说它们在编译成机器代码(程序集)后对socket()的调用看起来像这样.我根本不知道装配,但这只是为了说明:

装配/机器代码:

PUSH 06             ; IPPROTO_TCP
PUSH 01             ; SOCK_STREAM
PUSH 02             ; AF_INET
CALL WS2_32.socket ; This is one of the parts our DLL will need to intercept ("hook").
Run Code Online (Sandbox Code Playgroud)

为了让我们使程序发送数据(使用我们的DLL),我们需要知道套接字的句柄.所以我们需要拦截他们对socket函数的调用.以下是一些注意事项:

  1. 那里的最后一条指令需要改为:CALL OurOwnDLL.socket.那个CALL指令只是内存中的一个值(记得吗?)所以我们可以用WriteProcessMemory做到这一点.我们会做到这一点.

  2. 我们希望控制目标程序,而不是使其崩溃或使其行为异常.所以我们的代码需要透明.我们将注入的DLL需要具有原始socket函数相同的函数,返回相同的值等.唯一的区别是,我们将记录返回值(SocketHandle),以便以后在我们想要发送数据时使用它.

  3. 我们还需要知道套接字是否/何时连接,因为我们不能发送数据,除非它是(假设我们像大多数应用程序一样使用TCP).这意味着我们还需要挂钩的Winsock connectAPI函数复制,在我们的DLL.

DLL注入和监视socketconnect功能(未经测试):

这个C DLL将具有挂钩和取消挂钩功能的所有功能.我现在无法测试它,我甚至不是一个C程序员,所以如果你遇到任何问题请告诉我.

将其编译为使用Unicode 的Windows DLL,并将其注入到您知道使用WS2_32的socket()和connect()函数的进程中,并让我知道它是否有效.对不起,我没办法测试.如果您需要进一步的帮助或修复,请告诉我.

/*
    SocketHookDLL.c

    Author:     Daniel Elkins
    License:    Public Domain
    Version:    1.0.0
    Created:    May 14th, 2014 at 12:23 AM
    Updated:    [Never]
    Summary:

    1. Link to the Winsock library so we can use its functions.
    2. Export our own `socket` and `connect` functions so that
        they can be called by the target application instead of
        the original ones from WS2_32.
    3. "Hook" the socket APIs by writing over the target's memory,
        causing `CALL WS2_32.socket` to `CALL SocketHookDLL.socket`, using
        WriteProcessMemory.
    4. Make sure to keep a copy of the original memory for when we no
        no longer want to hook those socket functions (i.e. DLL detaching).
*/



#pragma comment(lib, "WS2_32.lib")
#include <WinSock2.h>

/* These functions hook and un-hook an API function. */
unsigned long hookFunction (const char * dllModule, const char * apiFunction, unsigned char * memoryBackup);
unsigned int unHookFunction (const char * dllModule, const char * apiFunction, unsigned char * memoryBackup);

/* 
    These functions (the ones we want to hook) are copies of the original Winsock's functions from Winsock2.h.
        1. Calls OurDLL.hooked_socket() (unknowingly).
        2. OurDLL.hooked_socket() calls the original Winsock.socket() function.
        3. We take note of the returned SOCKET handle so we can use it later to send data.
        4. OurDLL.hooked_socket() returns the SOCKET back to the target app so everthing works as it should (hopefully!).
        Note: You can change return values, parameters (like data being sent/received like WPE does), just be aware it will
              also (hopefully, intendingly) change the behavior of the target application.
*/
SOCKET WSAAPI hooked_socket (int af, int type, int protocol);
int WSAAPI hooked_connect (SOCKET s, const struct sockaddr FAR * name, int namelen);


/* Backups of the original memory; need one for each API function you hook (if you want to unhook it later). */
unsigned char backupSocket[6];
unsigned char backupConnect[6];

/* Our SOCKET handle used by the target application. */
SOCKET targetsSocket = INVALID_SOCKET;

/* This is the very first code that gets executed once our DLL is injected: */
BOOL APIENTRY DllMain (HMODULE moduleHandle, DWORD reason, LPVOID reserved)
{
    /*
        We will hook the desired Socket APIs when attaching
        to target EXE and UN-hook them when being detached.
    */
    switch (reason)
    {
    case DLL_PROCESS_ATTACH:
        /* Here goes nothing! */
        hookFunction ("WS2_32.DLL", "socket", backupSocket);
        hookFunction ("WS2_32.DLL", "connect", backupConnect);
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_PROCESS_DETACH:
        unHookFunction ("WS2_32.DLL", "socket", backupSocket);
        unHookFunction ("WS2_32.DLL", "connect", backupConnect);
        break;
    case DLL_THREAD_DETACH:
        break;
    }
    return TRUE;
}

unsigned long hookFunction (const char * dllModule, const char * apiFunction, unsigned char * memoryBackup)
{
    /*
        Hook an API function:
        =====================
        1. Build the necessary assembly (machine code) opcodes to get our DLL called!
        2. Get a handle to the API we're hooking.
        3. Use ReadProcessMemory() to backup the original memory to un-hook the function later.     
        4. Use WriteProcessMemory to make changes to the instructions in memory.
    */

    HANDLE thisTargetProcess;
    HMODULE dllModuleHandle;
    unsigned long apiAddress;
    unsigned long memoryWritePosition;
    unsigned char newOpcodes[6] = {
        0xE9, 0x00, 0x00, 0x00, 0x00, 0xC3 // Step #1.
    };

    thisTargetProcess = GetCurrentProcess ();

    // Step #2.
    dllModuleHandle = GetModuleHandle (dllModule);
    if (!dllModuleHandle)
        return 0;

    apiAddress = (unsigned long) GetProcAddress (dllModuleHandle, apiFunction);
    if (!apiAddress)
        return 0;

    // Step #3.
    ReadProcessMemory (thisTargetProcess, (void *) apiAddress, memoryBackup, 6, 0);
    memoryWritePosition = ((unsigned long) apiFunction - apiAddress - 5);
    memcpy (&newOpcodes[1], &apiAddress, 4);

    // Step #4.
    WriteProcessMemory (thisTargetProcess, (void *) apiAddress, newOpcodes, 6, 0);

    return apiAddress;
}

unsigned int unHookFunction (const char * dllModule, const char * apiFunction, unsigned char * memoryBackup)
{
    HANDLE thisTargetProcess;
    HMODULE dllModuleHandle;
    unsigned long apiAddress;
    unsigned long memoryWritePosition;

    thisTargetProcess = GetCurrentProcess ();
    dllModuleHandle = GetModuleHandleA (dllModule);
    if (!dllModuleHandle)
        return 0;

    apiAddress = (unsigned long) GetProcAddress (dllModuleHandle, apiFunction);
    if (!apiAddress)
        return 0;

    if (WriteProcessMemory (thisTargetProcess, (void *) apiAddress, memoryBackup, 6, 0))
        return 1;

    return 0;
}

/* You may want to use a log file instead of a MessageBox due to time-outs, etc. */
SOCKET WSAAPI hooked_socket (int af, int type, int protocol)
{
    targetsSocket = socket (af, type, protocol);
    MessageBox (NULL, "(Close this quickly)\r\n\r\nThe target's socket was hooked successfully!", "Hooked SOCKET", MB_OK);
    return targetsSocket;
}

int WSAAPI hooked_connect (SOCKET s, const struct sockaddr FAR * name, int namelen)
{
    MessageBox (NULL, "(Close this quickly)\r\n\r\nThe target just connected to a remote address.", "Target Connected", MB_OK);
    return connect (s, name, namelen);
}
Run Code Online (Sandbox Code Playgroud)