Question

I'm using WPE PRO, and I can capture packets and send it back. I tried do it using WinSock 2(The same lib which WPE PRO use), but I don't know how to send packet to a existent TCP connection like WPE PRO does.

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

How can I do it ?

Was it helpful?

Solution

Are you asking how to make someone else's program send data over its existing Winsock connection?

I've done exactly this but unfortunately do not have the code on-hand at the moment. If you give me an hour or two I can put up a working example using C; if you need one let me know and I will.

Edit: sample DLL to test at the bottom of the page if you or anyone else wants to; I can't. All I know is that it compiles. You just need to download (or write!) a freeware DLL injector program to test it; there are tons out there.

In the meantime, what you need to research is:

  1. The very basics of how EXEs are executed.
  2. DLL injection
  3. API hooking
  4. Windows Sockets API

1. The very basics of how EXEs are executed:

The whole entire process of what I'm about to explain to you boils down to this very principal. When you double-click an executable, Windows parses it and loads its code, etc. into memory. This is the key. The compiled code is all being put into RAM. What does this imply? Well, if the application's code is all in RAM, can we change the application's code while it's running by just changing some of its memory? After all, it's just a bunch of instructions.

The answer is yes and will provide us the means of messing with another application - in this case, telling it to send some data over its open socket.

(This principal is also the reason you have to be careful writing programs in low-level languages like C since if you put bad stuff in bad parts of RAM, it can crash the program or open you up to shell code exploits).

2. DLL injection:

The problem is, how do we know which memory to overwrite? Do we have access to that program's memory, especially the parts containing the instructions we want to change? You can write to another process' memory but it's more complicated. The easiest way to change their memory (again, when I say memory, we're talking about the machine code instructions being executed) is by having a DLL loaded and running within that process. Think of your DLL as a .c file you can add to another program and write your own code: you can access the program's variables, call its functions, anything; because it's running within the process.

DLL injection can be done through numerous methods. The usual is by calling the CreateRemoteThread() API function. Do a Google search on that.

3. API Hooking

What is API hooking? To put it more generally, it's "function hooking", we just happen to be interested in hooking API calls; in this case, the ones used for Sockets (socket(), send(), etc.).

Let's use an example. A target application written in C using Winsock. Let's see what they are doing and then show an example of what we WANT to make it do:

Their original source code creating a socket:

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

Now, that's the original program's source code. Our DLL won't have access to that because it's loaded within an EXE and an EXE is compiled (duh!). So let's say their call to socket() looked something like this after being compiled to machine code (assembly). I don't know assembly at all but this is just for illustration:

The assembly/machine code:

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").

In order for us to make that program send data (using our DLL), we need to know the socket's handle. So we need to intercept their call to the socket function. Here are some considerations:

  1. The last instruction there would need to be changed to: CALL OurOwnDLL.socket. That CALL instruction is just a value in memory somewhere (remember?) so we can do that with WriteProcessMemory. We'll get to that.

  2. We want to take control of the target program, not crash it or make it behave strangely. So our code needs to be transparent. Our DLL which we will inject needs to have a socket function identical to the original, return the same value, etc. The only difference is, we will be logging the return value (SocketHandle) so that we can use it later when we want to send data.

  3. We also need to know if/when the socket connects since we can't send data unless it is (assuming we're using TCP like most applications do). This means we need to also hook the Winsock connect API function and also duplicate that in our DLL.

DLL to inject and monitor the socket and connect functions (untested):

This C DLL will have everything in place to hook and unhook functions. I can't test it at the moment and I'm not even much of a C programmer so let me know if you come across any problems.

Compile this as a Windows DLL not using Unicode and inject it into a process that you know uses WS2_32's socket() and connect() functions and let me know if it works. I have no means to test, sorry. If you need further help or fixes, let me know.

/*
    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);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top