Calling Convention Problem bei Hook

05/02/2015 17:00 _asm#1
Hey,
ich versuche derzeit die Argumente einer Funktion von einem Spiel zu bekommen mithilfe eines MS Detours.
Also wenn ich z.B die MessageBoxW Funktion detouren möchte, mache ich es folgendermaßen:
Code:
#include <windows.h>
#include <detours.h>

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

typedef int (WINAPI *MessageBoxType) (HWND, LPCTSTR, LPCTSTR, UINT);

MessageBoxType MessageBox_orig = nullptr;

int WINAPI MessageBoxDetour(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
	lpText = L"Text Parameter hooked";
	lpCaption = L"Caption Parameter hooked";

	return MessageBox_orig(hWnd, lpText, lpCaption, uType);
}

BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID lpReserved)
{
	switch(fdwReason)
	{
	case DLL_PROCESS_ATTACH:
		MessageBox_orig = (MessageBoxType)DetourFunction((PBYTE)MessageBoxW, (PBYTE)MessageBoxDetour);
		break;
	}
	return TRUE;
}
Was auch soweit funktioniert, doch jetzt möchte ich eine Funktion detouren die keinen Rückgabewert hat (void) und davon die Parameter bekommen.
Hier ein Ausschnitt aus OllyDbg von der Funktion:
[Only registered and activated users can see links. Click Here To Register...]

Die 6 Argumente die hier im Disassembly abgebildet sind versuche ich zu bekommen:
Arg1: DWORD
Arg2: DWORD
Arg3: float
Arg4: float
Arg5: float
Arg6: bool (default arg = true)


Und IDA:
[Only registered and activated users can see links. Click Here To Register...]

Mit einem Mid-Function Detour bekomme ich z.B die Werte die im ECX oder EAX Register stehen ohne Probleme zurück, doch mir wäre es lieber mit einem Funktionspointer, anstatt das ganze Inline-Assembler-Gefrickel :D

Ich vermute, dass das ein __thiscall ist, also eine Member-Funktion... doch wie würde jetzt hier der Funktionspointer aussehen?

MfG _asm
05/02/2015 18:08 Jeoni#2
Ja, die Funktion dort scheint in der Tat eine Memberfunktion (thiscall) zu sein.
Ich selber benutze eigentlich immer __fastcall, wenn ich solche Funktionen hooke.
Das erste Argument einer Fastcall-Funktion liegt in ECX, das Zweite in EDX, alle Weiteren, wie bei stdcall auch, auf dem Stack. Zudem räumt der Callee den Stack auf, wie bei stdcall und thiscall (sofern keine variablen Argumentlisten benutzt werden) auch.
In deinem Fall sähe die Hookfunktion also so aus:
Code:
void __fastcall MyFunction0045E200(void* thisptr, void* _edx, DWORD arg0, DWORD arg1, float arg2, float arg3, float arg4, bool arg5)
(den Funktionspointer / -typ daraus zu lesen ist ja trivial)
Das _edx muss sein, sonst würde man arg0 in EDX suchen und alle anderen Argumente einen Platz zu früh auf dem Stack.
Mit freundlichen Grüßen
Jeoni
05/02/2015 18:25 _asm#3
Danke dir Jeoni, hab nochmal die Funktion dekompiliert und mir einen typedef dafür geschrieben, jetzt funktioniert es auch (:

Falls dich das noch interessiert, in IDA:
Code:
int __thiscall sub_45E200(void *this, int a2, int a3, float a4, float a5, float a6, char a7)
#Kann geschlossen werden.

Mit freundlichen Grüßen, _asm :)
05/02/2015 18:35 snow#4
Noch anzumerken wäre, dass __thiscall bei typedefs funktioniert, bei Funktionsprototypen aber wie von Jeoni korrekt geschrieben __fastcall verwendet werden muss, deshalb der Dummy-edx-Paramter.

#closed (on request)