[Question] Hooking send() & recv() works, but recv hiding data for co???

05/05/2009 13:10 clintonselke#1
Hey guys, I've been making a DLL to allow another program to intercept the packets of conquer using windows pipes. (Then its the job of the main program to decrypt the packets, the DLL only gives a communication channel for the main program)

(winsock functions btw)

- hooking send() works fine for my internet browser

- hooking recv() works fine for my internet browser

- hooking send() works fine for conquer online

- hooking recv() ??? only 1/2 working for conquer online. When i hook recieve for conquer online, the packets recieved always seem to have size zero and the data is empty... however when i try to comment out call to the original recv() inside my recv() conquer stops working (for checking conquer uses that function). So what i think is going on is conquer is doing some trick with winsock to make the result of a recv() get stored somewhere else.

Any ideas what is up w/ the conquer recv() ? :confused:

Thanks in advance :D, and my code listings are below. :p

DLL that gets injected...
PHP Code:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <windows.h>
#include "types.h"
#include "detours/patcher.h"

/*
int WSARecv(
  __in     SOCKET s,
  __inout  LPWSABUF lpBuffers,
  __in     DWORD dwBufferCount,
  __out    LPDWORD lpNumberOfBytesRecvd,
  __inout  LPDWORD lpFlags,
  __in     LPWSAOVERLAPPED lpOverlapped,
  __in     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
*/

using namespace std;

typedef int (WINAPI *SendFunc)(SOCKET, const char*, intint);
typedef int (WINAPI *RecvFunc)(SOCKETchar*, intint);
typedef int (WINAPI *WSARecvFunc)(SOCKETLPWSABUFDWORDLPDWORDLPDWORDLPWSAOVERLAPPEDLPWSAOVERLAPPED_COMPLETION_ROUTINE);

SendFunc pSend NULL;
RecvFunc pRecv NULL;
WSARecvFunc pWSARecv NULL;

int WINAPI our_send(SOCKET s, const charbufint lenint flags);
int WINAPI our_recv(SOCKET scharbufint lenint flags);
int WINAPI our_wsa_recv(SOCKET sLPWSABUF lpBuffersDWORD dwBufferCountLPDWORD lpNumberOfBytesRecvdLPDWORD lpFlagsLPWSAOVERLAPPED lpOverlappedLPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);

HMODULE hWinsock GetModuleHandle("ws2_32.dll");

CPatch patchForSend((SendFunc)GetProcAddress(hWinsock"send"), our_sendpSend);
CPatch patchForRecv((RecvFunc)GetProcAddress(hWinsock"recv"), our_recvpRecv);
CPatch patchForWSARecv((WSARecvFunc)GetProcAddress(hWinsock"WSARecv"), our_wsa_recvpWSARecv);

fstream sendPipe;
fstream recvPipe;

SOCKET lastSocket INVALID_SOCKET;

int WINAPI our_send(SOCKET s, const charbufint lenint flags)
{
    
DWORD tmp;
    
lastSocket s;
    
sendPipe.write(buflen);
    
sendPipe.flush();
    
/*
    char buf2[len];
    sendPipe.read(buf2, len);
    pSend(s, buf2, sendPipe.gcount(), flags);
    */
    //return len;
    
return pSend(sbuflenflags);
}

int WINAPI our_recv(SOCKET scharbufint lenint flags)
{
    
DWORD tmp;
    
lastSocket s;
    
len pRecv(sbuflenflags);
    if (
len == 0) { return 0; }
    
recvPipe.write(buflen);
    
recvPipe.flush();
    
//recvPipe.read(buf, len);
    
return len;
}

int WINAPI our_wsa_recv(SOCKET sLPWSABUF lpBuffersDWORD dwBufferCountLPDWORD lpNumberOfBytesRecvdLPDWORD lpFlagsLPWSAOVERLAPPED lpOverlappedLPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
    
int x pWSARecv(slpBuffersdwBufferCountlpNumberOfBytesRecvdlpFlagslpOverlappedlpCompletionRoutine);
    for (
int i 0dwBufferCount; ++i) {
        
recvPipe.write(lpBuffers[i].buflpBuffers[i].len);
        
recvPipe.flush();
    }
    return 
x;
}

DWORD WINAPI transmitter(void*);

extern "C"
BOOL WINAPI DllMain(HINSTANCE hinstDLLDWORD fdwReasonLPVOID lpvReserved)
{
    switch (
fdwReason) {
        case 
DLL_PROCESS_ATTACH:
            
// attach to process
            
DisableThreadLibraryCalls((HMODULE)hinstDLL);
            
WaitNamedPipe("\\\\.\\pipe\\ConquerSendPipe"NMPWAIT_WAIT_FOREVER);
            
sendPipe.open("\\\\.\\pipe\\ConquerSendPipe");
            if (!
sendPipe) {
                
MessageBox(NULL"Failed to connect send pipe.""Error"MB_OK);
                return 
FALSE;
            }
            
WaitNamedPipe("\\\\.\\pipe\\ConquerRecvPipe"NMPWAIT_WAIT_FOREVER);
            
recvPipe.open("\\\\.\\pipe\\ConquerRecvPipe");
            if (!
recvPipe) {
                
MessageBox(NULL"Failed to connect recv pipe.""Error"MB_OK);
                return 
FALSE;
            }
            
//CreateThread(NULL, 0, transmitter, 0, 0, NULL);
            
break;
        case 
DLL_PROCESS_DETACH:
            
// detach from process

            
break;

        case 
DLL_THREAD_ATTACH:
            
// attach to thread
            
break;

        case 
DLL_THREAD_DETACH:
            
// detach from thread
            
break;
    }
    return 
TRUE// succesful
}

DWORD WINAPI transmitter(void*)
{
    
char buf[4096];
    
DWORD len;
    while (
1) {
        
sendPipe.read(buf4095);
        
len sendPipe.gcount();
        if (
len == 0) {
            
MessageBox(NULL"Connection to send pipe lost.""Error"MB_OK);
            return 
1;
        }
        
buf[len+1] = 0;
        if (
strcmp(buf"exit") == 0) { break; }
        
pSend(lastSocketbuflen0);
    }
    return 
0;

Test application...
PHP Code:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <windows.h>
#include <conio.h>
#include "types.h"
#include "tools.h"

using namespace std;

static 
void output_packet(char packet[], int len)
{
    for (
int i 0len; ++i) {
        
cout << hex << setw(2) << right << setfill('0') << (int)(unsigned char)packet[i] << " ";
    }
}

DWORD WINAPI server_to_client(void*);
DWORD WINAPI client_to_server(void*);

HANDLE hSendPipe INVALID_HANDLE_VALUE;
HANDLE hRecvPipe INVALID_HANDLE_VALUE;

int main(int argccharargv[])
{

    if (
argc != 2) {
        
cout << "Usage: packetlogger <ProcessID>" << endl;
        return 
1;
    }
    
istringstream is(argv[1]);
    
uint32 processId;
    
is >> processId;

    
// create a named pipe for communicating with the remote process
    
string sendPipeNamerecvPipeName;
    {
        
ostringstream os;
        
os << "\\\\.\\pipe\\ConquerSendPipe";// << processId;
        
sendPipeName os.str();
        
os.str("");
        
os << "\\\\.\\pipe\\ConquerRecvPipe";// << processId;
        
recvPipeName os.str();
    }
    
cout << "send pipe name: " << sendPipeName << endl;
    
cout << "recv pipe name: " << recvPipeName << endl;
    
cout << "Creating & connecting send pipe... ";
    
hSendPipe CreateNamedPipe(sendPipeName.c_str(), PIPE_ACCESS_DUPLEX /*| FILE_FLAG_OVERLAPPED*/PIPE_TYPE_MESSAGE PIPE_READMODE_MESSAGE PIPE_WAIT/*PIPE_UNLIMITED_INSTANCES*/409640960NULL);
    if (
hSendPipe == INVALID_HANDLE_VALUE) {
        
cout << "failed to create send pipe." << endl;
        return 
1;
    }
    if (!
ConnectNamedPipe(hSendPipeNULL)) {
        
cout << "failed to connect client to send pipe." << endl;
        return 
1;
    }
    
cout << "done." << endl;
    
cout << "Creating & connecting recv pipe... ";
    
hRecvPipe CreateNamedPipe(recvPipeName.c_str(), PIPE_ACCESS_DUPLEX /*| FILE_FLAG_OVERLAPPED*/PIPE_TYPE_MESSAGE PIPE_READMODE_MESSAGE PIPE_WAIT/*PIPE_UNLIMITED_INSTANCES*/409640960NULL);
    if (
hRecvPipe == INVALID_HANDLE_VALUE) {
        
cout << "failed to create recv pipe." << endl;
        return 
1;
    }
    if (!
ConnectNamedPipe(hRecvPipeNULL)) {
        
cout << "failed to connect client to send pipe." << endl;
        return 
1;
    }
    
cout << "done." << endl;

    
cout << "ready for data." << endl;

    
HANDLE thread1 CreateThread(NULL0server_to_client00NULL);
    
HANDLE thread2 CreateThread(NULL0client_to_server00NULL);

    while (
WaitForSingleObject(thread11000) != WAIT_OBJECT_0) {}
    while (
WaitForSingleObject(thread21000) != WAIT_OBJECT_0) {}

    
DisconnectNamedPipe(hSendPipe);
    
DisconnectNamedPipe(hRecvPipe);

    
CloseHandle(hSendPipe);
    
CloseHandle(hRecvPipe);

    return 
0;
}

DWORD WINAPI server_to_client(void*)
{
    
char buf[4096];
    
DWORD lentmp;
    while (
1) {
        if (!
ReadFile(hRecvPipebuf4096, &lenNULL)) { break; }
        
cout << "Server --> Client" << endl;
        
output_packet(buflen);
        
cout << endl;
        
//WriteFile(hRecvPipe, buf, len, &tmp, NULL);
    
}
    return 
0;
}

DWORD WINAPI client_to_server(void*)
{
    
char buf[4096];
    
DWORD lentmp;
    while (
1) {
        if (!
ReadFile(hSendPipebuf4096, &lenNULL)) { break; }
        
cout << "Client --> Server" << endl;
        
output_packet(buflen);
        
cout << endl;
        
//WriteFile(hSendPipe, buf, len, &tmp, NULL);
    
}
    return 
0;

05/06/2009 12:09 high6#2
Try doing

Code:
int WINAPI our_recv(SOCKET s, char* buf, int len, int flags)
{
    DWORD tmp;
    lastSocket = s;
    len = pRecv(s, buf, len, flags);
    if (len > 0)
    {
        recvPipe.write(buf, len);
        recvPipe.flush();
    }
    //recvPipe.read(buf, len);
    return len;
}
Why? Because recv is called by conquer asynchronously. Meaning that if there is no data to receive, recv returns -1 right away.
05/06/2009 12:58 clintonselke#3
Quote:
Originally Posted by high6 View Post
Try doing

Code:
int WINAPI our_recv(SOCKET s, char* buf, int len, int flags)
{
    DWORD tmp;
    lastSocket = s;
    len = pRecv(s, buf, len, flags);
    if (len > 0)
    {
        recvPipe.write(buf, len);
        recvPipe.flush();
    }
    //recvPipe.read(buf, len);
    return len;
}
Why? Because recv is called by conquer asynchronously. Meaning that if there is no data to receive, recv returns -1 right away.
high6 high6 high6 !!! UR a Genius!!! IT WORKS NOW... u rock :D

Thank you man! :handsdown:

Edit: I was about to give up and turn it into a proxy lol... then u fixed it :D