Problems while detouring send() and recv().

02/27/2009 12:38 xUsername#1
Hi there,

i've a problem. I'm not sure if i've done some misstakes. But every time i inject my dll the game will crash while i get or send a packet. Maybe someone can help me? I'll post the source code.

Code:
#include <windows.h>
#include "detours.h"

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

DWORD RecvOffset = 0x00D95060;
DWORD SendOffset = 0x00D950B0;

int (__stdcall *Recv)(SOCKET Socket, char *Buffer, int Length, int Flags);
int XRecv(SOCKET Socket, char *Buffer, int Length, int Flags) {

	return Recv(Socket, Buffer, Length, Flags);
}

int (__stdcall *Send)(SOCKET Socket, char *Buffer, int Length, int Flags);
int XSend(SOCKET Socket, char *Buffer, int Length, int Flags) {

	return Send(Socket, Buffer, Length, Flags);
}

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved) {
	switch(dwReason) {
		case DLL_PROCESS_ATTACH:
			Recv = (int (__stdcall *)(SOCKET, char *, int, int))DetourFunction((PBYTE)RecvOffset, (PBYTE)XRecv);
			Send = (int (__stdcall *)(SOCKET, char *, int, int))DetourFunction((PBYTE)SendOffset, (PBYTE)XSend);			

			break;
		case DLL_PROCESS_DETACH:
			DetourRemove((PBYTE)Recv, (PBYTE)XRecv);
			DetourRemove((PBYTE)Send, (PBYTE)XSend);			

			break;
	}
	return true;
}
I don't know why i'll get a crash. The game log says: "EXCEPTION_ACCESS_VIOLATION". I tried some various types of detouring. I'll ever get a crash.

Here's the assembler part of (ingame) send:
Code:
mov     eax, [esp+len]
push    ebx
push    esi
mov     esi, [esp+8+arg_0]
push    edi
imul    esi, 78h
push    0               ; flags
mov     edi, ecx
mov     ecx, [esp+10h+buf]
mov     edx, [edi+10h]
push    eax             ; len
mov     eax, [edx+esi]
push    ecx             ; buf
push    eax             ; s
call    ds:send
cmp     eax, 0FFFFFFFFh
mov     ebx, [esp+0Ch+arg_C]
mov     [ebx], eax
jnz     short loc_D95100
call    ds:WSAGetLastError
cmp     eax, 2733h
mov     [ebx], eax
jnz     short loc_D950F8
mov     ecx, [edi+10h]
lea     eax, [ecx+esi+50h]
inc     dword ptr [eax]

loc_D950F8:
pop     edi
pop     esi
xor     al, al
pop     ebx
retn    10h

loc_D95100:
pop     edi
pop     esi
mov     al, 1
pop     ebx
retn    10h
endp
I hope someone can help me.

Greetings,
hijax.
02/27/2009 13:06 Bot_interesierter#2
Looks like a calling convetion problem, you're trying to detour a _stdcall to __cdecl call wich is the default calling convetion used by c++ compilers.
You need to define the calling convetion of your XRevc and XSend correctly, try this:
Code:
int _stdcall XRecv(SOCKET Socket, char *Buffer, int Length, int Flags) {

	return Recv(Socket, Buffer, Length, Flags);
}
int _stdcall XSend(SOCKET Socket, char *Buffer, int Length, int Flags) {

	return Send(Socket, Buffer, Length, Flags);
}
This should fix your problem.
02/27/2009 13:13 xUsername#3
This hint wouldn't fix my problem. I always get a game crash.

The log file says:
The reason of a crash is: push esi

This is the 3rd line of the assembler code.
02/27/2009 13:53 Bot_interesierter#4
Quote:
Originally Posted by hijax View Post
This hint wouldn't fix my problem. I always get a game crash.

The log file says:
The reason of a crash is: push esi

This is the 3rd line of the assembler code.
Ich sehe gerade an deiner Signatur das du Deutsch sprichst, hast du meinen Vorschlag probiert weil deiner Formulierung im Englischen nach klingt es so als hättest du es nicht getan, das push esi den crash auslöst bedeutet das der StackPointer falsch ist, was vermutlich daran liegt das du eine _stdcall function zu einer _cdecl function umleitest, übrigens brauchst du keine Adressen für revc und send hardcoden wenn du einfach die Winsock2.h includest, dann sind die Funktionen bekannt und mit ihnen die Adressen.
Natürlich muss dann der DetourFunction aufruf anders aussehen und zwar so:
Code:
Recv = (int (__stdcall *)(SOCKET, char *, int, int))DetourFunction((PBYTE)recv, (PBYTE)XRecv);
allerdings würde ich Recv anders nennen, Recv_trampoline oder so wäre ein passenderer Name.
02/27/2009 17:06 xUsername#5
Nun ja, soweit funktioniert es.

Jedoch habe ich das Gefühl, dass ich die falsche Packete bekomme. :D

Denn das Packet für (Bsp.) Login ist nur ein Zeichen: *

Irgendwie nervt's mich.
02/28/2009 15:39 Bot_interesierter#6
Quote:
Originally Posted by hijax View Post
Nun ja, soweit funktioniert es.

Jedoch habe ich das Gefühl, dass ich die falsche Packete bekomme. :D

Denn das Packet für (Bsp.) Login ist nur ein Zeichen: *

Irgendwie nervt's mich.
Wie ließt du denn die Pakete aus?
ich würde das so machen:
Code:
for(int i=0; i<Length; i++){ cout<<buffer[i];} cout<<endl;
Wenn du einfach cout<<buffer; machst dann ist es klar das du nur ein Zeichen bekommst.