ASM Funktion in C als Function Pointer schreiben

06/01/2013 02:25 vwap#1
Hallo, ich bin gerade dabei, eine reverste ASM Funktion in C als Function Pointer zu schreiben.
Die Funktion:

Code:
CPU Disasm
Address   Hex dump          Command                                          Comments
00467CB0  /.  8B0D C8966E00 MOV ECX,DWORD PTR DS:[6E96C8]
00467CB6  |.  8B41 04       MOV EAX,DWORD PTR DS:[ECX+4]
00467CB9  |.  8B50 10       MOV EDX,DWORD PTR DS:[EAX+10]
00467CBC  |.  83C1 04       ADD ECX,4
00467CBF  |.  6A 0B         PUSH 0B
00467CC1  |.  FFD2          CALL EDX
00467CC3  |.  894424 08     MOV DWORD PTR SS:[ESP+8],EAX
00467CC7  |.  C74424 04 E4F MOV DWORD PTR SS:[ESP+4],0064F8E4
00467CCF  \.- FF25 D0E76400 JMP DWORD PTR DS:[<&python22.Py_BuildValue>]
6E96C8 ist also demnach der class ptr und CALL EDX müsste der Aufruf der Memberfunction sein.
Eigentlich sollte die Function (soll den Geldstand des Spielers zurück geben) keine Parameter nehmen (wüsste nicht welche), was also ist das "PUSH 0B"?

Habe bereits versucht, EDX zu dereferenzieren, allerdings crashed so direkt das Spiel:
Code:
pGetMoney = (GetMoney_t) (*(DWORD*) (*(DWORD*) (ADR_CLASS_GETMONEY + 0x4)) + 0x10);
Mein typedef sieht so aus:
Code:
typedef int (__thiscall *GetMoney_t) (void *_this);
Und so rufe ich den Geldstand ab:
Code:
int money = pGetMoney((void*) ADR_CLASS_GETMONEY);
Wo liegt denn das Problem? :/
06/01/2013 10:34 MrSm!th#2
Wieso dereferenzierst du bis auf den Wert, der als erstes an der Funktion steht? Du hast die Adresse schon mit dem +0x10, dereferenzierst du ein weiteres Mal, liest du an ihr aus und da der Code sehr wahrscheinlich keine Readwrite Protection gesetzt hat, stürzt es dir mit einer Access Violation ab.
06/01/2013 11:27 vwap#3
Alles klar, das Spiel crashed jetzt nicht mehr direkt nach/während der dref, sondern erst beim Aufruf der Funktion.

dref:
Code:
pGetMoney = (GetMoney_t) ((*(DWORD*) (ADR_CLASS_GETMONEY + 0x4)) + 0x10);
Und Aufruf:
Code:
if (GetAsyncKeyState(VK_NUMPAD1) & 1)
        {
            
            int money = pGetMoney((void*) *(DWORD*) ADR_CLASS_GETMONEY);
            char szBuffer[256];

            sprintf(szBuffer, "Money [%d]", money);

            MessageBoxA(NULL, szBuffer, "Debug", NULL);
        }
06/01/2013 14:12 MrSm!th#4
Quote:
*(DWORD*) ADR_CLASS_GETMONEY
Warum dereferenzierst du den Pointer auf das Objekt und castest es in einen Pointer? Lass die Dereferenzierung weg, wenn die Funktion einen Pointer erwartet, es ist doch schon einer oO Hast du überhaupt eine Ahnung, wie man mit Pointern umgeht? :f
Ansonsten sind falsche Calling Conventions ein beliebter Crashgrund.
06/01/2013 14:34 snow#5
Für dich ist ja der Bereich hier relevant:

Code:
MOV ECX,DWORD PTR DS:[6E96C8]
MOV EAX,DWORD PTR DS:[ECX+4]
MOV EDX,DWORD PTR DS:[EAX+10]
ADD ECX,4
PUSH 0B
CALL EDX
In meinen Augen muss man das dann so für die Funktion aufbereiten:

Code:
typedef unsigned long* DWORD_PTR;
    typedef int (*GetMoney_t)(void *t, int param);
    GetMoney_t pGetMoney = nullptr;
    DWORD_PTR ecx = reinterpret_cast<DWORD_PTR>(*reinterpret_cast<DWORD_PTR>(0x6E96C8));
    DWORD_PTR eax = reinterpret_cast<DWORD_PTR>(*(ecx + 0x4));
    DWORD_PTR edx = reinterpret_cast<DWORD_PTR>(*(eax + 0x10));
    pGetMoney = reinterpret_cast<GetMoney_t>(edx);
    pGetMoney(ecx + 0x4 /* this-Pointer */, 0x0B);
Gerade mal mit Clang compiled, das geht schonmal, aber vor allem der Aufruf der Funktion scheint bei dir inkorrekt zu sein, da ja noch 4 Bytes ins ECX-Register addiert werden und der Parameter (push 0Bh) fehlt.

Korrigiert mich, falls ich falsch liege. :)
06/01/2013 14:44 MrSm!th#6
Hat er alles drin, sein Fehler liegt in der Dereferenzierung des Parameters. Und ja, stimmt, das push 0Bh fehlt auch.