Verständnisproblem: CALL und Adresse
-
Guten Tag,
ich bin aktuell dabei mich etwas mit Reverse Engineering auseinander zu setzen und habe dazu eine (vermeintlich) einfache Frage.
Ich habe diese Befehlszeile:
Adresse Op-Codes Darstellung von OllyDbg --------------------------------------------------------- 102C83D0 /$ 8B5424 04 MOV EDX,DWORD PTR SS:[ESP+4]
Mein nächstes Ziel ist, alle Codestellen zu finden, die auf diese Adresse "zeigen". Genauer genommen gibt es im Code einige Stellen, die einen
CALL
auf die Adresse0x102C83D0
absetzen.Im Debugging-Programm OllyDbg kann ich einfach Rechtsklick auf den Befehl machen und "Find references to -> Selected command" auswählen. Ich habe nun versucht das nachzubauen, scheitere aber daran, zu verstehen, wie der ASM Code aussehen muss.
Beispiel: Eine Referenz sieht so aus:
Adresse Op-Codes Darstellung von OllyDbg --------------------------------------------------------- 103340AF ./ E8 1C43F9FF CALL meinedll.102C83D0
Also befindet sich die Referenz an der Stelle
0x103340AF
- das ist soweit richtig, oder?
Der erste Op-Code ist derE8
. Das ist dann vermutlich derCALL
-Befehl.
Und nun komme ich zu der Stelle, die nicht verstehen kann: Woher weiß der Computer, dass die Op-Codes1C43F9FF
auf die Stelle0x102C83D0
zeigen?Ich müsste nun wissen, wie man die Op-Codes berechnet, damit ich danach suchen kann.
Ein Hinweis noch: Es gibt mehrere Referenzen, die ich alle benötige. Bei allen sieht der Op-Code nach dem
E8
-Befehl _anders_ aus. Meine Vermutung: Das ist irgendeine relative Berechnung der Adresse - fragt sich nur, wie.Ich bin dankbar für eine ausführliche Erklärung oder eine kurze Antwort. Aber ich möchte es möglichst auch verstehen.
Gracias!
-
[url=http://www.intel.com/products/processor/manuals/]Intel
64 and IA-32 Architectures Software Developer's Manual
Volume 2A: Instruction Set Reference, A-M[/url] (Seite 190):A relative offset (rel16 or rel32) is generally specified as a label in assembly code. But
at the machine code level, it is encoded as a signed, 16- or 32-bit immediate value.
This value is added to the value in the EIP(RIP) register. In 64-bit mode the relative
offset is always a 32-bit immediate value which is sign extended to 64-bits before it
is added to the value in the RIP register for the target calculation. As with absolute
offsets, the operand-size attribute determines the size of the target operand (16, 32,
or 64 bits). In 64-bit mode the target operand will always be 64-bits because the
operand size is forced to 64-bits for near branches.Daher:
0x103340AF (Adresse von E8) + 0x5 (Größe von E8 + Operand in Bytes) + 0xFFF9431C (Operand (Low-Endian!)) = 0x[u]1[/u]102C83D0 (die 1 steht, da nur 32 Bit große Register, ins S-Flag)
-
Danke, das hat mir auf jeden Fall schon mal geholfen, und ich verstehe das auch
Nun ist aber die Frage, wie ich mit der Zusätzlichen
1
umgehe.Mein aktueller Ansatz ist: Nach allen
E8
suchen, dann bei jedem Fund:(0x102C83D0 + 4294967296L) - E8-Position - 0x5 = Op-Codes-Big (Big-Endian oder wie?)
Dazu zwei Fragen:
1.) Wie kriege ich die Op-Codes-Big nun zu einem Low-Endian umformen, so dass aus
fff9431c
das wird:1c43f9ff
?
2.) Wie löse ich das _ordentlich_ mit der Zahl4294967296L
?Gruß und Danke
-
Ich muss mich kurz noch berichtigen: diese zusätzliche 1 ist natürlich am gesetzten Carry- und nicht am Sign-Flag zu erkennen.
Die Reihenfolge der Bytes kannst du mit der x86-Anweisung BSWAP (Seite 174 in dem oben genannten "Buch") beeinflussen.
Wenn du in C oder x86-ASM codest kann dir diese 1 egal sein. Bei C nimmst du einfach einen vorzeichenlosen 32 Bit großen Typ (z.B. unsigned int).
Was du mit 4294967296L und der Gleichung machen möchtest versteh ich nicht. Soll der Operand von CALL (E8) ermittelt werden?
unsigned __int32 operand = 0x1102C83D0 - 0x103340AF - 0x5;
Du solltest aber auch beachten, dass diverse CALLs existieren und deren Operanden nicht nur 16, 32 oder 64Bit groß sein können, sondern auch relativ oder absolut! Weiteres steht ja in dem PDF.
-
Hi,
die große Zahl brauch ich ja, damit ich die "1" da vorne weg kriege. Ich programmiere in C (bzw. C++) und habe von ASM noch nicht wirklich die Ahnung.
Hintergrund ist wie gesagt, dass ich die Adresse zu der ich die Referenzen suchen möchte, erst zur Laufzeit herausbekomme (durch Suche nach bestimmten Bytes im Memory des Programms). In meinem Fall wäre das halt
0x102C83D0
. Jetzt müsste ich ja (aus meiner Sicht) das ganze mit der Zahl4294967296L
addieren, um auf0x1102C83D0
zu kommen. Dann müsste ich nach allenE8
im Memory suchen, um dann irgendwie zu berechnen, ob derCALL
auf meine gesuchte Stelle zeigt. Man, ist das alles kompliziert. Und wenn es dann noch mehrere Fälle gibt, dass eine Adresse auch absolut sein kann... Oh man.Gracias!
-
Versuchs doch mal per Breakpoints