Wo Disassembler ansetzen?



  • Hallo,

    habe ein zumindest für mich äußerst kniffliges Problem.
    Mein Programm analysiert Programmabstürtze duch z.B. Access Violations. Über einen StackWalk bekomme ich die Stellen der zuletzt aufgerufenen Funktionen.

    Nun wollte ich den Bereich um die Stelle der Exception disassemblieren. Dazu verwenden ich derzeit die Distorm Library und der Bereich nach der Exception ist kein Problem, da weiß ich von wo ich anfangen kann, das Problem ist der Bereich vor der Stelle der Exception. Derzeit verwende ich den letzten Aufruf einer Funktion vor der Exception und disassembliere den gesamten Bereich dazwischen. Diese Methode ist aber meiner Meinung nach nicht zuverlässig, da der disassemblierte Code zwar teilweiße, aber eben nicht komplett richtig ist.

    Hat da jemand eine Idee dazu, wäre wirklich super?!



  • Weiß den wirklich keiner eine Antwort?
    Es kann doch nicht sein, dass ich das ganze File disassembleiren muss?!



  • Wenn in der Datei noch Symbole enthalten sind, dann suchst du einfach in welcher Funktion die Exception aufgetreten ist. Dann bekommst du die Startadresse der Funktion und kannst von da ab disassemblieren. Wenn in der Datei allerdings keine Symbole mehr enthalten sind, wird dir wohl nichts anderes übrigbleiben, als die ganze Datei zu disassemblieren.



  • Ah ok. Danke erstmal.
    Angenommen es wären Debug Symbole vorhanden, ne Idee wie ich den Startpunkt der Funktion herausfinden kann?



  • Das kommt wohl auf das Dateiformat an... Ich kenn mich nur mit elf einigermaßen aus. Aber am besten schaust du dir einfach die Specs zu dem Dateiformat, welches du benutzt, an 😉



  • Ich verwende VC++ und daher sidn die Debug Symbole in *.pdb Datein abgespeichert.
    Auf die Symbole greife ich derzeit über die Debghelh Funktionen SymGetSymFromAddr64 usw. zu.

    Kann ich mit diesen auch den Anfang der Funktion herausfinden?



  • Der Member "Address" aus SYMBOL_INFO sollte das doch sein...



  • Genau das wars! Danke vielmals!



  • So ich bins noch mal. Hab die Sache nun mal ein bisschen weiter gedacht und bin auf das nächste Problemchen gestoßen.
    Wenn in der Datei Debug Symbole vorhanden sind, kann in den Startpunkt der Funktion herausfinden, wenn nicht muss ich die gesamte Datei disassemblieren.
    So nun stimmt die Stelle im Speicher aber natürlich nicht mit der Stelle in der Datei überein.
    Allerdings scheint mir der Unterschied immer gleich zu sein, denn z.B. IDA kann mir den Offset im Speicher anzeigen, wenn er nur das File disassembliert hat.

    Kann mir jemand sagen wie ich diesen Unterschied herausfinden kann? Und ändert sich dieser in bestimmten Fällen (EXE/DLL, 64Bit...)?

    Danke schonmal...



  • Das offset in der Datei und das Debugsymbol haben aber sehr wenig miteinander zu tun. Ein Debugsymbol bezieht sich immer auf eine Sektion/Segment. Du musst halt das Dateiformat richtig auslesen. Du kannst nicht einfach nur das Debugsymbol hernehmen und dann an der Stelle in der Datei lesen. Das Symbol gibt nähmlich eine virtuelle Adresse im Addressraum an, nicht in der Datei und eine exe/elf kann ja auch an andere Adressen gelinkt werden.



  • Hmm ich glaube wir reden etwas aneinandern vorbei. Die Adresse die ich über das Debugsymbol bekommen kann stimmt schon, da fängt die Funktion im Speicher an. Das Problem ist wenn ich die Datei disassemblieren muss, dass natürlich der Offset im File nicht mit dem Offset im Speicher übereinstimmt. Aber wie komm ich jetzt vom Offset im Speicher auf den Offset in der Datei?



  • Hallo,

    ich denke nun, dass ich herausgefunden habe wie mein Disassembler die korrekte Adresse des Codes in der Binary auch für den Speicher anzeigen kann. Im Header müsste die Imagebase Adresse (oder Größe?) stehen und diese wird zum Offset des Codes in der Datei dazuaddiert und schon erhalten wir den korrekten Offset des Codes im Speicher. Kann mir jemand sagen wie ich diese Größe auslesen kann? Und ob sich dieses "Verhalten" für andere Dateien (DLLs usw.) oder für 64 Bit ändert?



  • Hallo,

    ich bin es schon wieder. So nach längerem lesen zahlreicher Tutorials und rumprobieren mit verschiedenen Tools denke ich, dass ich jetzt wirklich weiß wie man den passenden Offset im File zum Offset im Speicher berechnen kann.

    Soweit meine Erkentnisse:
    Man nehme den Offset im Speicher der mir über den StackWalk gegeben wurde (angenommen 0x603C1446), dann zieht man davon die Image Base ab (0x603C0000).
    Dann davon noch die Virtuelle Adresse des Code Segmentes abziehen (0x1000) und auf das Ergebniss noch den Pointer zu den RAW Daten des Segmentes (0x400) addieren. Dadurch erhalten wir die Stelle im File (0x846). Was mir mein Disassembler auch anzeigt.

    Ist das soweit richtig? Muss man möglicherweiße auch noch die Base Relocation mit einrechnen?

    Wäre super wenn jemand der da Ahnung hat, kurz schreibt ob das nun stimmt, sonst gurke ich da noch ne Woche dran rum. Danke.


Log in to reply