2016-08-06 94 views
0

Wenn eine Funktion, die Sie 5 Byte der ursprünglichen Funktion zu überschreiben müssen Einhaken, es nicht über die Ersteinrichtung des Stapelrahmens egal wie die Signaturen und Aufrufkonventionen das gleiche von der ursprünglichen Funktion, um Ihre Ersatzfunktion sind, aber Was ich nicht bekomme ist, dass Sie die ersten paar Bytes der ursprünglichen Funktion überschreiben. 55 (push ebp) 8B EC (mov ebp, esp), also brauchst du 2 mehr? Warum ist es egal, dass Sie diese 2 Byte extrahieren, die für die Funktion kritisch sind?Beim Hacken einer Funktion ist es egal, ob Sie die ersten 5 Bytes überschreiben.

00440112       ; int __cdecl function(int, FILE *) 
.text:00440112       var_410   = byte ptr -410h 
.text:00440112       var_310   = byte ptr -310h 
.text:00440112       var_210   = byte ptr -210h 
.text:00440112       var_110   = byte ptr -110h 
.text:00440112       var_10   = byte ptr -10h 
.text:00440112       var_4   = dword ptr -4 
.text:00440112       arg_0   = dword ptr 8 
.text:00440112       arg_4   = dword ptr 0Ch 
.text:00440112 
.text:00440112 55          push ebp 
.text:00440113 8B EC         mov  ebp, esp 
.text:00440115 81 EC 10 04 00 00      sub  esp, 410h 
.text:0044011B 53          push ebx 
.text:0044011C 56          push esi 
.text:0044011D 8B 75 0C        mov  esi, [ebp+arg_4] 
.text:00440120 80 7E 04 00        cmp  byte ptr [esi+4], 0 
.text:00440124 57          push edi 
.text:00440125 C7 86 10 01 00 00 63 00+    mov  dword ptr [esi+110h], 63h 
.text:0044012F 74 0F         jz  short loc_440140 
.text:00440131 83 3D 7A 4E 4B 00 00     cmp  dword_4B4E7A, 0 
.text:00440138 7F 06         jg  short loc_440140 
.text:0044013A 83 65 FC 00        and  [ebp+var_4], 0 
.text:0044013E EB 07         jmp  short loc_440147 

Nehmen Sie die obige Baugruppe. 'E9 ?? ?? ?? ?? ' ersetzt "55 8B EC 81 EC" (?? ?? ?? ?? ist die Adresse der Funktion zu springen zu), so wie ich es sehe, ist die Zuweisung von 0x410 auf dem Stapel für die lokalen vars nicht auftreten wenn die neue Funktion bei 0x44011B auf das Original zurückspringt; Warum ist das egal? Ich sehe nicht, was mir fehlt.

Wenn Sie die Funktion Code reproduzieren möchten, dass Sie eine Funktion mit dieser Methode Haken ermöglicht, sehen dann MyUsername112358 Antwort HERE

+1

Wenn Ihr Haken nie wieder in die ursprüngliche Funktion springt, alles nach dem 5 Byte 'jmp rel32' keine Rolle spielt. Es ist nur wichtig, was die ursprünglichen Anweisungen waren, wenn Sie versuchen, sie auch * als Ihren Haken auszuführen. –

+1

Ja, ich muss die ursprüngliche Funktion nach dem Haken aufrufen; In dem Beispiel, das ich oben verlinkt habe, ruft er auch die ursprüngliche Funktion auf, aber es scheint ihm egal zu sein, dass er 2 zusätzliche Bytes überschreibt. – MikeO

+2

Ich denke, er weiß entweder, dass er die zusätzlichen Bytes außer Kraft setzt, und er berücksichtigt sie, wenn er die ursprüngliche Funktion aufruft, oder er hat nur Glück und nichts bricht. Der 5-Byte-Hook war populär, da die meisten Routinen, die von DLLs exportiert wurden, den Prolog 'mov edi, edi; push ebp; mov ebp, esp (wahrscheinlich wegen der stdcall-Konvention), die genau 5 Bytes lang ist, also schadet es dir nicht, wenn du es durch den Sprung ersetzst. –

Antwort

2

Wie Sie bemerkt haben, wenn Sie beabsichtigen, den ursprünglichen Code ausführen zu können, müssen Sie kann nicht einfach an der 5-Byte-Grenze abgeschnitten werden. Sie müssen die Anweisungen, die die ersten 5 Bytes als Ganzes abdecken, zerlegen und kopieren.

Sie können meine ia32hook, die OllyDbg 's verwendet, um herauszufinden, wo zu schneiden. The relevant snippet:

#include "ollydisasm/disasm.h" 

static inline unsigned long CleanBiteOff(const unsigned char *ptr, size_t amount) 
{ 
    static t_disasm disasm; 
    unsigned long size = 0; 
    do {size += Disasm(ptr+size, 16, ptr+size, &disasm, DISASM_SIZE);} while(size < amount); 
    return size; 
} 

Die size zurückgegeben wird, ist die Anzahl der Bytes, die Sie kopieren müssen. Am Ende des Trampolins, wo du über diese Bytes kopierst, springst du zurück auf (char*)func+size und alles ist wieder gut.

Die Antwort, die Sie verknüpfen, auch den Befehls-Cache nicht leeren und ein ernsthaftes Problem haben würde, wenn der Befehlszeiger auf Punkt an dem Bytes geschehen Sie zu Patch sind. Sie sollten die Threads pausieren und bestätigen, dass eip nicht auf die Bytes zeigt, die Sie patchen werden.

Ist dies nicht zu Lernzwecken ist, sollten Sie stattdessen eine Lösung wie Microsoft Detours verwenden.

+1

Sie brauchen nicht die ersten 3 Bytes, da die Umleitungsfunktion die gleiche Signatur und Aufrufkonvention wie das Trampolin haben wird. Ansonsten danke für deine Antwort, es wurde schön erklärt. – MikeO

+0

Warum ist der dritte Parameter 'ip' eine fest codierte Adresse? '0x00401AAC' – MikeO

+0

@MikeO Ich kann mich nicht erinnern, warum ich bei diesem Wert 'ip' gesetzt habe. Da Sie nur daran interessiert sind, die Befehlsgrößen herauszufinden, können Sie sie ignorieren. Wenn der Disassembler sich nicht um eine Null kümmert, sollten Sie lieber eine Null eingeben, um anzuzeigen, dass dies keine Rolle spielt. – a3f