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

标签 windows tcp winsock socks

我正在使用wpe-pro,我可以捕获数据包并将其发回。我尝试使用winsock 2(和wpe-pro使用的库相同),但我不知道如何像wpe-pro那样将数据包发送到现有的TCP连接。
http://wpepro.net/index.php?categoryid=2
我该怎么做?

最佳答案

你是在问如何让其他人的程序通过其现有的winsock连接发送数据?
我已经做到了,但不幸的是,目前没有手头的代码。如果你给我一两个小时,我可以用c来举一个工作示例;如果你需要一个,请告诉我,我会的。
编辑:如果你或者其他人想的话,可以在页面底部测试示例dll;我不能。我只知道它是编译的。你只需要下载(或者写!)一个免费的dll注入器程序来测试它;有很多。
同时,你需要研究的是:
关于如何执行exe的基本知识。
dll注入
API挂钩
Windows套接字API
1。关于如何执行exe的基本知识:
我要向你们解释的整个过程,归结起来就是这个原理。双击可执行文件时,windows会对其进行解析并将其代码等加载到内存中。这是钥匙。编译后的代码都被放入ram中。这意味着什么?好吧,如果应用程序的代码都在ram中,我们可以在应用程序运行时通过改变一些内存来改变它的代码吗?毕竟,这只是一堆指令。
答案是肯定的,并将为我们提供与另一个应用程序打交道的方法——在本例中,告诉它通过其打开的套接字发送一些数据。
(这个原则也是你必须小心用低级语言编写程序的原因,比如C语言,因为如果你把坏东西放在RAM的坏部分,它可能会使程序崩溃或打开你的外壳代码漏洞)。
2。dll注入:
问题是,我们如何知道要覆盖哪个内存?我们是否可以访问该程序的内存,特别是包含要更改的指令的部分?您可以写入另一个进程的内存,但它更复杂。更改内存的最简单方法(同样,当我说内存时,我们指的是正在执行的机器代码指令)是在该进程中加载并运行一个dll。把你的dll想象成一个.c文件,你可以添加到另一个程序并编写你自己的代码:你可以访问程序的变量,调用它的函数,任何东西;因为它在进程中运行。
dll注入可以通过多种方法完成。通常是通过调用createRemoteThread()api函数。在谷歌上搜索一下。
三。API钩子
什么是API挂钩?更一般地说,这是“函数挂接”,我们只是碰巧对挂接api调用感兴趣;在这种情况下,用于套接字的调用(socket()、send()等)。
我们举个例子。使用winsock用c编写的目标应用程序。让我们看看他们在做什么,然后展示一个我们想让他们做什么的例子:
他们最初的源代码创建了一个套接字:

SOCKET ConnectSocket = INVALID_SOCKET;
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

现在,这是原始程序的源代码。我们的dll无法访问它,因为它是在一个exe中加载的,并且一个exe被编译(duh!)。所以假设在编译为机器代码(程序集)之后,它们对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").

为了让程序发送数据(使用我们的dll),我们需要知道套接字的句柄。所以我们需要拦截他们对socket函数的调用。以下是一些注意事项:
最后一条指令需要更改为:CALL OurOwnDLL.socket。指令只是内存中某个地方的一个值(还记得吗?)所以我们可以用writeprocessmemory来实现这一点。我们会解决的。
我们想要控制目标程序,而不是使其崩溃或使其行为异常。所以我们的代码必须是透明的。我们将注入的dll需要有一个与原始函数相同的CALL函数,返回相同的值等。唯一的区别是,我们将记录返回值(socket),以便稍后在发送数据时使用它。
我们还需要知道套接字是否连接/何时连接,因为除非连接,否则我们无法发送数据(假设我们像大多数应用程序一样使用TCP)。这意味着我们还需要钩住winsockSocketHandleapi函数,并将其复制到我们的dll中。
要插入和监视connectsocket函数的dll(未测试):
这个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);
}

关于windows - 使用现有的TCP连接发送数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23620434/

相关文章:

windows - 丢失批处理文件 FOR 语句的 (set) 元素中命令的错误输出

java - HBase区域服务器无法与主服务器连接

调用 Go RPC TCP 服务时 Ruby Socket 客户端挂起

c++ - 使用 UDP(WinSock 和 C++)发送和接收结构?

windows - 关于Winsock Kernel Buffer和Nagle算法的疑问

android - 为什么 VirtualBox 检测不到我的 Android 设备?

node.js - 我无法在 Heroku 上部署 Alexa 技能(使用 jovo 构建)

python - BlueSocket 在连接到 Python Socket 套接字时说连接被拒绝

linux - 多个并行 tcp 连接

c - 使用 Winsock 接收数据