Autor |
Beitrag |
Tobi482
      
Beiträge: 135
|
Verfasst: Mo 04.09.06 09:39
Hi Leute,
meine Assemblerkenntnisse sind sehr begrenzt und daher wende ich mich an euch. Zu nächst wüsste ich gern etwa grundlegendes. Dieser Code ist eine CALL mit einer dahinter angehängten Adresse.
Quelltext 1: 2:
| 00XXXXXX E86346FCFF call 004F9EB0 |
Schaue ich mir weitere CALL's an, sehe ich, dass "E8" vermutlich der OpCode für Call ist und der Rest dahinter die Addresse ist "63 46 FC FF".
1 Frage:
Wie wird "63 46 FC FF" in 004F9EB0 umgerechnet?
Dies aber nur am Rande. Der Call und seine Parameter sind mir bekannt und die darunter stehende Zeile zeigt, dass es sich vermutlich um ein Parameter handelt.
Quelltext 1:
| 00XXXXXX 83C404 add esp, 00000004 |
2. Frage
Ich habe einen fertig deklariert den Header für diese Subroutine und würde gerne eine Trampolin-Funktion einbauen, so dass der Aufruf des Calls unweigerlich mit dem Aufruf meiner Trampoling-Funktion verbunden ist, im grunde eine Art Hook.
Gibts es für soetwas fertige Codeschnipsel, Units, Dll's etc?
Wie nennt man soetwas? Patching? Call redirecting?
Hoffe ihr könnte mir weiter helfen.
Schon mal herzlichen Dank im Voraus.
Mit freundlichen Grüßen Tobi
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mo 04.09.06 13:39
Tobi482 hat folgendes geschrieben: | Hi Leute,
meine Assemblerkenntnisse sind sehr begrenzt und daher wende ich mich an euch. Zu nächst wüsste ich gern etwa grundlegendes. Dieser Code ist eine CALL mit einer dahinter angehängten Adresse.
Quelltext 1: 2:
| 00XXXXXX E86346FCFF call 004F9EB0 |
Schaue ich mir weitere CALL's an, sehe ich, dass "E8" vermutlich der OpCode für Call ist und der Rest dahinter die Addresse ist "63 46 FC FF".
1 Frage:
Wie wird "63 46 FC FF" in 004F9EB0 umgerechnet? |
Adresse hinter dem CALL-Befehl + Wert hinter dem CALL. Beispiel ...
Ausgehend von deinem Code stand dieser CALL an Offset $00535818. Da ein CALL mit relativer Adressangabe (Opcode E  5 Bytes lang ist, ist EIP nach der Ausführung $0053581D, was die Ausgangsadresse des Aufrufs ist. Da Du immer LSB-First speicherst, steht hinter dem CALL nicht "63 46 FC FF" sondern die Zahl $FFFC4663, die Du einfach zu der Ausgangsposition hinzuaddierst $0053581D + $FFFC4663 = $004F9EB0
Tobi482 hat folgendes geschrieben: | Dies aber nur am Rande. Der Call und seine Parameter sind mir bekannt und die darunter stehende Zeile zeigt, dass es sich vermutlich um ein Parameter handelt.
Quelltext 1:
| 00XXXXXX 83C404 add esp, 00000004 | |
Nope  Voraussichtlich eine lokale Variable  Wobei dieser Source dazu nicht ganz ausreicht, da man sowohl die Zeilen VOR dem Aufruf, als auch die ersten 5-7 Zeilen der aufgerufnen Funktion benötigt um das ganz genau zu sagen (weil sich daraus auch die Aufrufkonvention ergibt).
Tobi482 hat folgendes geschrieben: | 2. Frage
Ich habe einen fertig deklariert den Header für diese Subroutine und würde gerne eine Trampolin-Funktion einbauen, so dass der Aufruf des Calls unweigerlich mit dem Aufruf meiner Trampoling-Funktion verbunden ist, im grunde eine Art Hook.
Gibts es für soetwas fertige Codeschnipsel, Units, Dll's etc? |
Gibt's massig ... U.a. z.B. die uallCollection, madHook, ...
Tobi482 hat folgendes geschrieben: | Wie nennt man soetwas? Patching? Call redirecting? |
Allgemein Hook, und je nach dem, wie Du umleitest unterscheidet man zwischen IAT, Code Overwriteing, Code Injection und noch diversen anderen Hooks ...
Tobi482 hat folgendes geschrieben: | Hoffe ihr könnte mir weiter helfen.
Schon mal herzlichen Dank im Voraus.
Mit freundlichen Grüßen Tobi |
MfG,
BenBE.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Tobi482 
      
Beiträge: 135
|
Verfasst: Mo 04.09.06 14:26
Supi,
Danke für deine Anwort
So, nun haben sich doch noch ein paar Fragen aufgetan. Der Code sieht wie folgt aus.
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| :00535816 8B45E0 mov eax, dword ptr [ebp-20] :00535819 8B88485F0000 mov ecx, dword ptr [eax+00005F48] :0053581F 034DFC add ecx, dword ptr [ebp-04] :00535822 8B55E0 mov edx, dword ptr [ebp-20] :00535825 898A485F0000 mov dword ptr [edx+00005F48], ecx :0053582B 8B45E0 mov eax, dword ptr [ebp-20] :0053582E 8B4DE0 mov ecx, dword ptr [ebp-20] :00535831 8B90485F0000 mov edx, dword ptr [eax+00005F48] :00535837 3B91505F0000 cmp edx, dword ptr [ecx+00005F50] :0053583D 7526 jne 00535865 :0053583F 8B45E0 mov eax, dword ptr [ebp-20] :00535842 0508400000 add eax, 00004008 :00535847 50 push eax
:00535848 E86346FCFF call 004F9EB0 <--- der erwähnte Call
:0053584D 83C404 add esp, 00000004 :00535850 85C0 test eax, eax :00535852 7504 jne 00535858 :00535854 33C0 xor eax, eax :00535856 EB12 jmp 0053586A |
Ich dachte bisher, das hier ein Parameter, vermutlich ein Pointer zu einem Bytearray, in den Stack geschoben wird.
Quelltext
Und, dass hier der Stack erhöht wird, um den Rückgabewert(4 Byte) des Call's im Stack zu sichern.
Quelltext 1:
| :0053584D 83C404 add esp, 00000004 |
Daher hatte ich eine Function wie hier erwartet.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| var Hook_Next : function(a:Pointer):integer;stdcall;
function Hook_Callback(a:Pointer):integer;stdcall; begin Result := Hook_Next(a); end; |
1 Frage:
Bist du dir ganz sicher, dass es sich dabei wirklich um Variabeln handelt?
Ich habe mir die von dir empfohlenen Units, speziell die uallCollectiont, angesehen.
Die Funktion die dabei für mich interessant ist, ist vermutlich die "uallhook.HookCodeNt"
Die Funktion möchte ein orgFunc:Pointer einen CallbackFunc:Pointer und einen NewFunc:Pointer haben
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| var Hook_Next : function(a:Pointer):integer;stdcall;
...
function Hook_Callback(a:Pointer):integer;stdcall; begin Beep(3000,1000); Result := Hook_Next(a); end;
...
procedure Patch_Func; var p : Integer; begin p := $00535848; if uallhook.HookCodeNt(Ptr(p), @Hook_Callback, @Hook_Next) then begin Beep(1000,1000); end; end; |
2 Frage:
Wo startet die Originalfunktion? Bei p := $00535848; ??? Davor? Dahinter? Die anderen Parameter kann ich über den @-Operator bestimmen.
Mit freundlichen Grüßen
Tobi
|
|
uall@ogc
      
Beiträge: 1826
Erhaltene Danke: 11
Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
|
Verfasst: Mo 04.09.06 14:45
Hi Tobi,
wenn du die uallCollection dafür verwendest (uallHook.HookCode) [das NT wird nur intern verwendet] dann solltest du immer die Adresse angeben wo die Funktion anfängt.
D.h. in deinem Fall ist es nicht 00535848 sondern 004F9EB0.
Für einen E8 hook kannst du das natürlich selbst berechnen.
Delphi-Quelltext 1: 2: 3: 4: 5:
| myFunctiob := Addr; origFunction := Addr; nextFunction := Pointer(PInteger(Integer(origFunction)+1)^+Integer(origFunction)+5); PPointer(Integer(origFunction)+1)^ := Pointer(Integer(myFunction)-Integer(orgFunction)-5); |
Bauchst natürlich noch Schreibrechte die du mit VirtualProtect bekommst.
_________________ wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mo 04.09.06 15:10
Tobi482 hat folgendes geschrieben: | Supi,
Danke für deine Anwort  |
NP.
Tobi482 hat folgendes geschrieben: | So, nun haben sich doch noch ein paar Fragen aufgetan. Der Code sieht wie folgt aus. |
k, kommentieren wir erstmal den Source ein wenig
Tobi482 hat folgendes geschrieben: | Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| :00535816 8B45E0 mov eax, dword ptr [ebp-20] //Lokale Variable lesen (wahrscheinlich Objekt) :00535819 8B88485F0000 mov ecx, dword ptr [eax+00005F48] //Feld dieses Objekts lesen :0053581F 034DFC add ecx, dword ptr [ebp-04] //Zu diesem Wert eine lokale Var addieren :00535822 8B55E0 mov edx, dword ptr [ebp-20] //Objekt wieder lesen :00535825 898A485F0000 mov dword ptr [edx+00005F48], ecx //Und geänderten Wert schreiben ...
:0053582B 8B45E0 mov eax, dword ptr [ebp-20] //Man ist Delphi ineffizient!!! :0053582E 8B4DE0 mov ecx, dword ptr [ebp-20] //mov ecx, eax wär schneller gewesen ... :00535831 8B90485F0000 mov edx, dword ptr [eax+00005F48] //Man hätte auch gleich sich ECX von oben merken können :00535837 3B91505F0000 cmp edx, dword ptr [ecx+00005F50] //Wert mit dem von oben vergleichen :0053583D 7526 jne 00535865 //wenn die sich unterschieden nach unten springen ...
//Hier kommt jetzt der CALL (incl. Vorbereitungen) :0053583F 8B45E0 mov eax, dword ptr [ebp-20] //Objekt lesen :00535842 0508400000 add eax, 00004008 //Adresse auf das zu bearbeitende Feld berechnen :00535847 50 push eax //Als Parameter für STDCALL speichern :00535848 E86346FCFF call 004F9EB0 //Aufruf ausführen, EAX enthält ergebnis
//Prüfung des Ergebnisses :0053584D 83C404 add esp, 00000004 //Weiß nicht, welchen Müll Delphi hier coded ...* :00535850 85C0 test eax, eax //Ergebnis auf <> 0 prüfen :00535852 7504 jne 00535858 //Bei ungleich 0 springen ... :00535854 33C0 xor eax, eax //EAX := 0, ZF setzen :00535856 EB12 jmp 0053586A | |
*Dieser ESP-Befehl ist kein Stack-Cleanup de Aufrufs, sondern gehört zu einem anderen Stack-Frame, dass von Delphi im Laufe des Codes angelegt wurde ... Bei STDCALL müssen sich die aufgerufenen Funktionen nämlich selbstständig um das Aufräumen kümmern (durch ein RET(F) 04 in diesem Fall)
Tobi482 hat folgendes geschrieben: | Ich dachte bisher, das hier ein Parameter, vermutlich ein Pointer zu einem Bytearray, in den Stack geschoben wird.
Quelltext |
Jup, wird er auch ...
Tobi482 hat folgendes geschrieben: | Und, dass hier der Stack erhöht wird, um den Rückgabewert(4 Byte) des Call's im Stack zu sichern.
Quelltext 1:
| :0053584D 83C404 add esp, 00000004 | |
Kurz zum Merken: Wenn ESP kleiner wird, wird auf den Stack gespeichert, wird ESP vergrößert, wird gelöscht
Tobi482 hat folgendes geschrieben: | Daher hatte ich eine Function wie hier erwartet.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| var Hook_Next : function(a:Pointer):integer;stdcall;
function Hook_Callback(a:Pointer):integer;stdcall; begin Result := Hook_Next(a); end; | |
Jup, korrekt.
Wobei der Result sogar nur Boolean zu sein scheint (bestenfalls LONGBOOL).
Tobi482 hat folgendes geschrieben: | 1 Frage:
Bist du dir ganz sicher, dass es sich dabei wirklich um Variabeln handelt? |
Siehe meine Kommentare im Source *g*
Tobi482 hat folgendes geschrieben: | Ich habe mir die von dir empfohlenen Units, speziell die uallCollectiont, angesehen.
Die Funktion die dabei für mich interessant ist, ist vermutlich die "uallhook.HookCodeNt" |
Allgemein HookCode, da uall automatisch die richtige für das Betriebssystem unterscheided ...
Tobi482 hat folgendes geschrieben: | Die Funktion möchte ein orgFunc:Pointer einen CallbackFunc:Pointer und einen NewFunc:Pointer haben
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| var Hook_Next : function(a:Pointer):integer;stdcall;
...
function Hook_Callback(a:Pointer):integer;stdcall; begin Beep(3000,1000); Result := Hook_Next(a); end;
...
procedure Patch_Func; var p : Integer; begin p := $00535848; if uallhook.HookCodeNt(Ptr(p), @Hook_Callback, @Hook_Next) then begin Beep(1000,1000); end; end; | |
Jain ... Die Funktion möchte den Pointer auf das Ziel des CALLs ...
Tobi482 hat folgendes geschrieben: | 2 Frage:
Wo startet die Originalfunktion? Bei p := $00535848; ??? Davor? Dahinter? Die anderen Parameter kann ich über den @-Operator bestimmen. |
Delphi-Quelltext 1:
| p := PInteger($00535849)^; |
Tobi482 hat folgendes geschrieben: | Mit freundlichen Grüßen
Tobi |
HTH.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Tobi482 
      
Beiträge: 135
|
Verfasst: Mo 04.09.06 20:38
Oh Mann, Jungs ihr seid Klasse
da bin ich ja direkt an zwei Spezialisten geraten.
VIELEN VIELEN DANK an euch beiden ihr habt mir sehr
geholfen. Der Hook Funktioniert jetzt
Also programmieren ist eine Sache für sich, aber
ASM verstehen ist noch viel schwieriger, also meinen
größten Respekt an euch beide.
Mit freundlichen Grüßen
Tobi
|
|
|