
libtalloc ist ein Python-Skript zur Verwendung mit GDB, das zur Analyse des „trivial allocator“ (talloc) verwendet werden kann.
libtalloc ist ein Python-Skript zur Verwendung mit GDB, mit dem der „trivial allocator" (talloc) analysiert werden kann. Eine Einführung in talloc finden Sie hier:
https://talloc.samba.org/talloc/doc/html/index.html
libtalloc wurde von anderen GDB-Python-Skripten zur Heap-Analyse wie unmask_jemalloc und libheap inspiriert. Einige grundlegende Funktionen sind identisch mit diesen Projekten.
https://github.com/cloudburst/libheap
https://github.com/argp/unmask_jemalloc
Bitte beachten Sie, dass ich kein Python-Guru bin und die Codequalität dies widerspiegelt. Wenn Sie etwas sehen, das Sie abstößt, senden Sie ruhig einen Patch oder geben Sie mir ein paar Vorschläge. Jegliches Feedback ist willkommen.
libtalloc wurde mit verschiedenen 2.x-Releases von talloc getestet und unterstützt eine dynamische Versionserkennung, um die unterschiedlichen strukturellen Unterschiede zwischen den Versionen zu überwinden. Es wurde auf 32-Bit und 64-Bit getestet, allerdings nicht erschöpfend, also wundern Sie sich nicht, wenn es gelegentlich nicht funktioniert.
Es wurde bis zu einem gewissen Grad auf x86 und x64 getestet:
Wenn Sie es mit einer anderen Version testen, lassen Sie mich bitte wissen, ob es funktioniert hat oder was kaputtging, und ich werde versuchen, es und/oder die Doku entsprechend zu aktualisieren.
Das Skript benötigt lediglich eine relativ moderne Version von GDB mit Python-Unterstützung.
Einige LTS-Distributionen wie Ubuntu 12.04 verwenden weiterhin GDB mit Python 2.7, während neuere Versionen wie 14.04 Python 3.0 verwenden. Ich habe versucht, dieses Skript mit beiden zum Laufen zu bringen, sodass Sie nur Folgendes benötigen:
(gdb) source libtalloc.py
Ein Großteil der Funktionalität ist an den Ansatz von unmask_jemalloc angelehnt, bei dem ein separater GDB-Befehl anstelle einer komplexen Reihe von Optionen bereitgestellt wird.
Es sind mehrere Methoden verfügbar, die speziell dazu entwickelt wurden, die C-Funktionen der talloc-Bibliothek nachzubilden, um Personen zu helfen, die libtalloc erweitern möchten, falls sie bereits mit der Bibliothek vertraut sind.
Um eine vollständige Liste der Befehle zu sehen, können Sie den Befehl tchelp ausführen:
(gdb) tchelp
[libtalloc] talloc commands for gdb
[libtalloc] tcchunk -v -x <addr> : show chunk contents (-v for verbose, -x for data dump)
[libtalloc] tcvalidate -a <addr> : validate chunk (-a for whole heap)
[libtalloc] tcsearch <addr> : search heap for hex value or address
[libtalloc] tcwalk <func> : walk whole heap calling func on every chunk
[libtalloc] tcreport <addr> : give talloc_report_full() info on memory context
[libtalloc] tcdump -s <addr> : dump chunks linked to memory context (-s for sorted by addr)
[libtalloc] tcparents <addr> : show all parents of chunk
[libtalloc] tcchildren <addr> : show all children of chunk
[libtalloc] tcinfo : show information known about heap
[libtalloc] tcprobe : try to collect information about talloc version
[libtalloc] tchelp : this help message
Einer der wichtigsten Befehle ist tcprobe. Er muss ausgeführt werden, um herauszufinden, welche Version von talloc tatsächlich installiert ist. Die Strukturlayouts verschiedener Versionen können erheblich variieren. Damit die meisten Funktionen funktionieren, muss die Version daher bekannt sein.
Wenn der Befehl funktioniert, sollte er die erkannte Version anzeigen:
(gdb) tcprobe
Version: 2.1.1
File: /usr/lib/libtalloc.so.2.1.1
Der Befehl tcinfo soll so viele gesammelte Informationen über den Heap wie möglich anzeigen, etwa die Informationen von tcprobe, die null_context-Struktur, falls sie gefunden wurde, und mehr. Derzeit zeigt er nur die Version an und ob null_context gesetzt ist. null_context wird für die meisten Funktionen benötigt, die die eigentliche Hierarchie durchlaufen. Um ihn zu finden, versuchen die meisten anderen Funktionen wie tchunk usw., ihn automatisch zu finden.
Nachdem tcprobe ausgeführt wurde, aber bevor tchunk tatsächlich verwendet wird:
(gdb) tcinfo [libtalloc] null_context not yet found yet [libtalloc] Version: 2.0.7 [libtalloc] File: /usr/lib/i386-linux-gnu/libtalloc.so.2.0.7
Dann, nachdem ein Chunk analysiert wurde, etwa so:
(gdb) tcchunk 0xb94a52b0 WARNING: 0xb94a52b0 not a talloc_chunk. Assuming ptr to chunk data 0xb94a5280 sz:0x0000003c, flags:...., name:struct tevent_context
Sie können anschließend mit tcinfo bestätigen, dass er gefunden wurde.
(gdb) tcinfo [libtalloc] null_context: 0xb94a5028 [libtalloc] Version: 2.0.7 [libtalloc] File: /usr/lib/i386-linux-gnu/libtalloc.so.2.0.7
Jetzt, da null_context gesetzt ist, können Sie andere Befehle ausführen, die normalerweise beanstanden würden, dass er nicht gesetzt ist, wie etwa den Befehl tcsearch.
tcchunk kann Ihnen eine Zusammenfassung des Chunks, eine ausführlichere Ausgabe jedes Feldes oder extrem ausführliche Informationen über jeden umgebenden Chunk liefern.
HINWEIS: Ein wichtiger Punkt zu tcchunk ist, dass intern die Methode tc_chunk() verwendet wird, die versucht, Fehler bei der Übergabe der Chunk-Adresse zu korrigieren. Wenn Sie insbesondere die Adresse der Chunk-Daten selbst übergeben und der erwartete talloc-Magic-Wert nicht gefunden wird, sucht die Methode etwas früher im Speicher nach einem legitimen Chunk-Header. Das kann in korrupten Szenarien Probleme verursachen. Stellen Sie also immer sicher, dass Sie die explizite Adresse übergeben, es sei denn, Sie führen nur eine oberflächliche Analyse durch.
Zusammenfassungsausgabe:
(gdb) tcchunk 0x80a13c88
0x80a13c88 sz:0x00000020, flags:..p., name:struct netr_ServerPasswordSet
Das Folgende ist eine Legende für die Chunks in der Zusammenfassungsausgabe:
p - Member of a pool (POOLMEM flag)
P - Chunk is a pool (POOL flag)
F - Chunk is free (FREE flag)
L - Chunk is looped (LOOP flag)
Ausführliche Ausgabe:
(gdb) tcchunk -v 0x80a13c88
struct talloc_chunk @ 0x80a13c88 {
next = 0x0
prev = 0x80a140c8
parent = 0x0
child = 0x80a14088
refs = 0x0
destructor = 0x0
name = 0x807d9f2f (struct netr_ServerPasswordSet)
size = 0x20
flags = 0xe8150c78 (POOLMEM)
limit = 0x0
pool = 0x80a13248
talloc-Chunks enthalten einige Magic-Werte, mit denen überprüft werden kann, ob sie intakt sind. Der Befehl tcvalidate analysiert einen Chunk, um sicherzustellen, dass die Chunk-Magic wie erwartet ist. Zusätzlich analysiert er alle anderen Zeigermember, um sicherzustellen, dass sie tatsächlich in Speicherbereiche fallen (wie von gdb bekannt), ob die Größe gültig ist usw.
Wir verwenden eine eingebaute Methode, um einen Wert zu ändern und zu zeigen, wie es fehlschlagen könnte:
(gdb) python set_destructor(tc_chunk(0x80a13c88), 0x41414141)
(gdb) tcchunk -v 0x80a13c88
struct talloc_chunk @ 0x80a13c88 {
next = 0x0
prev = 0x80a140c8
parent = 0x0
child = 0x80a14088
refs = 0x0
destructor = 0x41414141
name = 0x807d9f2f (struct netr_ServerPasswordSet)
size = 0x20
flags = 0xe8150c78 (POOLMEM)
limit = 0x0
pool = 0x80a13248
(gdb) tcvalidate 0x80a13c88
Chunk header is invalid:
0x80a13c88: Chunk has bad destructor pointer 0x41414141
tcparents kann verwendet werden, um alle Eltern des angegebenen Chunks anzuzeigen: