<summary><strong>Erlernen Sie AWS-Hacking von Grund auf mit</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* Wenn Sie Ihr **Unternehmen in HackTricks beworben sehen möchten** oder **HackTricks im PDF-Format herunterladen möchten**, überprüfen Sie die [**ABONNEMENTPLÄNE**](https://github.com/sponsors/carlospolop)!
* **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repositories senden.
Para confirmar, dass Systemaufrufe korrekt ausgeführt werden, muss das vorherige Programm kompiliert werden und die Systemaufrufe sollten in **strace ./KOMPILIERTE\_PROGRAMM** erscheinen.
Beim Erstellen von Shellcodes kann ein Trick angewendet werden. Die erste Anweisung ist ein Sprung zu einem Aufruf. Der Aufruf ruft den Originalcode auf und legt zusätzlich das EIP im Stack ab. Nach dem Aufruf haben wir den benötigten String platziert, sodass wir mit diesem EIP auf den String zeigen und gleichzeitig den Code weiter ausführen können.
EJ FNSTENV ist ein einfacher Exploit, der die FNSTENV-Anweisung verwendet, um den FPU-Zustand zu speichern. Dieser Exploit ist besonders nützlich, wenn Sie versuchen, Shellcode in einem Umfeld auszuführen, in dem der FPU-Zustand nicht korrekt gespeichert wird.
Besteht aus einem kleinen Code, der die Speicherseiten eines Prozesses nach der darin gespeicherten Shellcode durchsucht (sucht nach einer Signatur im Shellcode). Nützlich in Fällen, in denen nur wenig Platz zum Einspritzen von Code zur Verfügung steht.
Sind verschlüsselte Shells, die über kleine Codes verfügen, die sie entschlüsseln und zu ihnen springen lassen, unter Verwendung des Call-Pop-Tricks wäre dies ein **Beispiel für eine Caesar-Verschlüsselung**:
Nützlich, wenn die Adresse des Stacks nicht in den EIP eingefügt werden kann (überprüfen, dass der EIP nicht 0xbf enthält) oder wenn der Speicherort der Shellcode nicht berechnet werden kann. Wenn die verwundbare Funktion jedoch einen Parameter akzeptiert (hier wird der Shellcode platziert).
Durch das Ändern des EIP in eine Adresse zu einem **ret** wird die nächste Adresse geladen (die Adresse des ersten Arguments der Funktion). Mit anderen Worten, der Shellcode wird geladen.
Der Exploit würde sein: SHELLCODE + Padding (bis zum EIP) + **\&ret** (die nächsten Bytes im Stack zeigen auf den Beginn des Shellcodes, da die Adresse des übergebenen Parameters im Stack platziert wird)
Es scheint, dass Funktionen wie **strncpy** nach Abschluss die Adresse, an der der Shellcode gespeichert war, aus dem Stack entfernen und diese Technik unmöglich machen. Mit anderen Worten, die Adresse, die der Funktion als Argument übergeben wird (die den Shellcode speichert), wird durch eine 0x00 ersetzt, sodass beim Aufruf des zweiten **ret** ein 0x00 gefunden wird und das Programm abstürzt.
Durch das Betrachten des Aufbaus des Stacks eines neuen Prozesses in Linux kann ein Exploit entwickelt werden, sodass das Programm in einer Umgebung gestartet wird, in der nur eine Variable vorhanden ist, nämlich der Shellcode. Die Adresse dieser Variable kann dann berechnet werden als: addr = 0xbfffffff - 4 - strlen(KOMPLETTER\_AUSFÜHRBARER\_NAME) - strlen(shellcode)
Diese Art von Überläufen tritt auf, wenn eine Variable nicht darauf vorbereitet ist, eine so große Zahl zu verarbeiten, wie ihr übergeben wird, möglicherweise aufgrund einer Verwechslung zwischen vorzeichenbehafteten und vorzeichenlosen Variablen, zum Beispiel:
If we pass a negative number as the first parameter, it will show that len <256andwewillbypassthatfilter,andalsostrlen(buffer)willbelessthanl,sincelisanunsignedintandwillbeverylarge.
This type of overflows does not aim to write something in the program's process, but to bypass poorly designed filters to exploit other vulnerabilities.
The value that an uninitialized variable can take is unknown and it could be interesting to observe it. It may take the value that a variable from the previous function took and this may be controlled by the attacker.
Grundsätzlich handelt es sich hierbei um eine Struktur mit **Funktionen, die aufgerufen werden**, bevor das Programm beendet wird. Dies ist interessant, wenn Sie Ihren **Shellcode aufrufen können, indem Sie zu einer Adresse springen**, oder in Fällen, in denen Sie erneut zu main zurückkehren müssen, um die **Format-String ein zweites Mal auszunutzen**.
Hinweis, dass dies **keine****endlose Schleife** erzeugt, da der Canary bemerken wird, dass das Ende des Stapels möglicherweise beschädigt ist und die Funktion nicht erneut aufgerufen wird. Daher können Sie mit diesem **1 weitere Ausführung** der Schwachstelle haben.
Eine Formatzeichenkette kann auch missbraucht werden, um Inhalte aus dem Speicher des Programms zu **dumpen**.\
Zum Beispiel gibt es in der folgenden Situation eine **lokale Variable im Stapel, die auf eine Flagge zeigt**. Wenn Sie herausfinden, wo im **Speicher** der **Zeiger** auf die **Flagge** ist, können Sie **printf** dazu bringen, auf diese **Adresse** zuzugreifen und die **Flagge** auszugeben:
Beachten Sie, dass Sie nach dem **vorherigen Exploit** und der Erkenntnis, dass Sie Inhalte **leaken** können, **Zeiger** auf **`printf`** in den Abschnitt setzen können, in dem das **ausführbare** Programm **geladen** ist, und es **vollständig dumpen**!
Wenn es Ihnen gelingt, eine **Adresse** zu einem **Shellcode** in **`__DTOR_END__`** zu **schreiben**, wird dies **ausgeführt**, bevor das Programm endet.\
In der Regel finden Sie den **DTOR**-Abschnitt **zwischen** den Werten `ffffffff` und `00000000`. Wenn Sie also nur diese Werte sehen, bedeutet das, dass **keine Funktion registriert ist**. Überschreiben Sie also die **`00000000`** mit der **Adresse** des **Shellcodes**, um ihn auszuführen.
**sprintf** kopiert einen formatierten String in eine **Variable**. Daher könnten Sie die **Formatierung** eines Strings missbrauchen, um einen **Buffer Overflow in der Variable** zu verursachen.\
**`atexit()`** ist eine Funktion, der **andere Funktionen als Parameter übergeben werden**. Diese **Funktionen** werden ausgeführt, wenn ein **`exit()`** ausgeführt wird oder das **Hauptprogramm beendet wird**.\
Wenn Sie die **Adresse** einer dieser **Funktionen** beispielsweise auf einen Shellcode zeigen lassen können, erhalten Sie **Kontrolle** über den **Prozess**, aber dies ist derzeit komplizierter.\
Derzeit sind die **Adressen der auszuführenden Funktionen** hinter mehreren Strukturen versteckt, und schließlich sind die Adressen, auf die sie zeigen, nicht die Adressen der Funktionen, sondern sind **verschlüsselt mit XOR** und Verschiebungen mit einem **zufälligen Schlüssel**. Daher ist dieser Angriffsvektor derzeit **zumindest auf x86** und **x64\_86** nicht sehr nützlich.\
Die **Verschlüsselungsfunktion** ist **`PTR_MANGLE`**. **Andere Architekturen** wie m68k, mips32, mips64, aarch64, arm, hppa... **implementieren die Verschlüsselungsfunktion nicht**, da sie das Gleiche zurückgeben wie sie als Eingabe erhalten haben. Daher wären diese Architekturen durch diesen Vektor angreifbar.
Das Problem ist, dass EIP und ESP durch die **`PTR_MANGLE`**-Funktion übergeben werden, daher sind die **Architekturen, die anfällig für diesen Angriff sind, die gleichen wie oben**.\
Jedoch sind nach meinen Recherchen die anderen Register nicht geschützt, **so dass bei einem `call ebx`, `call esi` oder `call edi`** innerhalb der aufgerufenen Funktion die Kontrolle übernommen werden kann. Oder Sie könnten auch EBP ändern, um ESP zu ändern.
Jedes Objekt einer **Klasse** hat einen **VPtr**, der ein **Zeiger** auf das Array seiner Klasse ist. Der VPtr ist Teil des Headers jedes Objekts, daher könnte bei einer **Überschreibung** des **VPtr** dieser auf eine Dummy-Methode zeigen, sodass beim Ausführen einer Funktion der Shellcode aufgerufen wird.
Einige unsichere Funktionen werden durch sichere Funktionen ersetzt. Nicht standardisiert. (nur für x86, nicht für Kompilierungen mit -fomit-frame-pointer, nicht für statische Kompilierungen, nicht alle anfälligen Funktionen werden sicher gemacht und LD\_PRELOAD funktioniert nicht bei SUID-Binärdateien).
Lädt gemeinsam genutzte Bibliotheken von 0x00000000 bis 0x00ffffff, damit immer ein Byte 0x00 vorhanden ist. Dies hält jedoch praktisch keinen Angriff auf, insbesondere nicht bei Little Endian.
Führt ein ROP aus, bei dem die Funktion strcpy@plt (aus der plt) aufgerufen wird und auf den Eintrag der GOT gezeigt wird und das erste Byte der zu aufrufenden Funktion (system()) kopiert wird. Anschließend wird dasselbe mit GOT+1 gemacht und das 2. Byte von system() kopiert... Schließlich wird die in der GOT gespeicherte Adresse aufgerufen, die system() sein wird.
Die freien Stücke sind in einer doppelt verketteten Liste (bin) und es dürfen niemals zwei freie Stücke nebeneinander sein (sie werden zusammengeführt).
Im "size"-Feld gibt es Bits, um anzuzeigen: ob das vorherige Stück verwendet wird, ob das Stück über mmap() zugewiesen wurde und ob das Stück zum primären Arena gehört.
Wenn ein Stück freigegeben wird und eines der benachbarten Stücke frei ist, werden sie durch die Makro unlink() fusioniert und das größere neue Stück wird frontlink() übergeben, um es in den entsprechenden Bin einzufügen.
Daher, wenn es gelingt, P->bk mit der Adresse eines Shellcodes und P->fd mit der Adresse eines Eintrags in der GOT oder DTORS minus 12 zu ändern, wird erreicht:
BK->fd = FD -> \*(\&shellcode + 8) = (&\_\_dtor\_end\_\_ - 12) —> Dies führt dazu, dass 4 Bytes ab dem 8. Byte des Shellcodes geschrieben werden, daher sollte das erste Shellcode-Instruction ein Sprungbefehl sein, um dies zu überspringen und zu den Nops zu gelangen, die zum Rest des Shellcodes führen.
Nach dem Shellcode wird Füllmaterial eingefügt, bis die Felder prev\_size und size des nächsten Stücks erreicht sind. An diesen Stellen werden 0xfffffff0 (um prev\_size zu überschreiben, damit das Bit angezeigt wird, dass es frei ist) und "-4" (0xfffffffc) in die size eingefügt (um sicherzustellen, dass beim Überprüfen des 3. Stücks auf Freiheit des 2. Stücks tatsächlich auf die modifizierte prev\_size verwiesen wird, die angibt, dass es frei ist) -> Wenn free() überprüft, wird zur size des 3. Stücks gegangen, aber tatsächlich wird auf das 2. - 4. Stück verwiesen und es wird angenommen, dass das 2. Stück frei ist. Dann wird **unlink()** aufgerufen.
Beim Aufruf von unlink() werden die ersten Daten des 2. Stücks als P->fd verwendet, sodass die Adresse überschrieben wird, die - 12 (da FD->bk 12 zur in FD gespeicherten Adresse hinzufügt) . An dieser Adresse wird die zweite Adresse im 2. Stück eingefügt, die die Adresse des Shellcodes sein soll (falsches P->bk).
**fake\_size = pack("\<I”, 0xfffffffc) #-4, para que piense que el “size” del 3º trozo está 4bytes detrás (apunta a prev\_size) pues es ahí donde mira si el 2º trozo está libre**
**got\_free = pack("\<I", 0x08048300 - 12) #Dirección de free() en la plt-12 (será la dirección que se sobrescrita para que se lanza la shellcode la 2º vez que se llame a free)**
**payload += prev\_size + fake\_size + got\_free + addr\_sc #Se modifica el 2º trozo, el got\_free apunta a donde vamos a guardar la direccion addr\_sc + 12**
Dann wird das Programm denken, dass "a" frei ist und in einem Bin liegt, daher wird unlink() aufgerufen, um es zu entkoppeln. Da jedoch die Headergröße PREV\_SIZE -4 beträgt, wird angenommen, dass der "a"-Chunk tatsächlich bei b+4 beginnt. Das heißt, es wird ein unlink() auf einen Chunk durchgeführt, der bei b+4 beginnt. Daher wird bei b+12 der "fd"-Pointer und bei b+16 der "bk"-Pointer sein.
Frontlink wird aufgerufen, wenn etwas freigegeben wird und keiner seiner benachbarten Chunks frei ist. Es wird nicht unlink() aufgerufen, sondern direkt frontlink().
Wenn einer erneut verwendet werden soll, wird er ohne Probleme zugewiesen. Wenn der andere verwendet werden soll, wird ihm derselbe Speicherplatz zugewiesen, sodass die "fd"- und "bk"-Pointer mit den Daten gefälscht werden, die die vorherige Reservierung schreibt.
Es ist nur ein Aufruf von free() erforderlich, um die Ausführung beliebigen Codes zu verursachen. Es ist wichtig, einen zweiten Chunk zu finden, der von einem vorherigen überlaufen und freigegeben werden kann.
In \[1] wird das Feld size und das Bit NON\_MAIN\_ARENA überprüft, das geändert werden kann, damit die Überprüfung true zurückgibt und heap\_for\_ptr() ausgeführt wird, das ein "and" auf "mem" ausführt und die 2,5 unwichtigsten Bytes auf 0 setzt (in unserem Fall von 0x0804a000 auf 0x08000000) und auf 0x08000000->ar\_ptr zugreift (als ob es sich um ein struct heap\_info handelt).
Auf diese Weise, wenn wir beispielsweise einen Chunk bei 0x0804a000 kontrollieren und ein Chunk bei **0x081002a0** freigegeben wird, können wir die Adresse 0x08100000 erreichen und beispielsweise **0x0804a000** schreiben. Wenn dieser zweite Chunk freigegeben wird, wird heap\_for\_ptr(ptr)->ar\_ptr den Wert zurückgeben, den wir in 0x08100000 geschrieben haben (da auf 0x081002a0 das zuvor erwähnte "and" angewendet wird und von dort der Wert der ersten 4 Bytes, ar\_ptr, abgeleitet wird).
Daher, wenn wir in av->bins\[2] den Wert von \_\_DTOR\_END\_\_-12 schreiben, wird in der letzten Anweisung in \_\_DTOR\_END\_\_ die Adresse des zweiten Chunks geschrieben.
An der Adresse, an der die Adresse des zweiten Chunks mit den letzten 5 Nullen landet, müssen wir die Adresse dieses ersten Chunks platzieren, damit heap\_for\_ptr() denkt, dass ar\_ptr am Anfang des ersten Chunks liegt und av->bins\[2] von dort abruft.
Auf diese Weise wird \_int\_free(CHUNK1, CHUNK2) aufgerufen und die Anweisungen werden befolgt, um in \_\_DTOR\_END\_\_ die Adresse von prev\_size des CHUNK2 zu schreiben, der dann zum Shellcode springt.
Um diese Technik anzuwenden, müssen einige zusätzliche Anforderungen erfüllt sein, die den Payload etwas komplizierter machen.
Diese Technik ist nicht mehr anwendbar, da fast der gleiche Patch wie für unlink angewendet wurde. Es wird überprüft, ob die neue Site, auf die verwiesen wird, auch auf sie verweist.
Auf diese Weise, wenn "fb" auf die Adresse einer Funktion in der GOT gesetzt wird, wird an dieser Adresse die Adresse des überschriebenen Chunks platziert. Dafür muss die Arena in der Nähe der dtors-Adressen liegen. Genauer gesagt muss av->max\_fast an der Adresse stehen, die wir überschreiben werden.
Deshalb, wenn wir in das Feld size eine Größe von 8 + NON\_MAIN\_ARENA + PREV\_INUSE setzen, wird fastbin\_index() fastbins\[-1] zurückgeben, das auf av->max\_fast zeigen wird.
In diesem Fall wird av->max\_fast die Adresse sein, die überschrieben wird (nicht die, auf die verwiesen wird, sondern diese Position wird überschrieben).
Außerdem muss der benachbarte Chunk des freigegebenen Chunks größer als 8 sein -> Da wir gesagt haben, dass die Größe des freigegebenen Chunks 8 beträgt, müssen wir in diesem falschen Chunk nur eine Größe größer als 8 setzen (da die Shellcode im freigegebenen Chunk sein wird, muss am Anfang ein jmp stehen, der auf nops zeigt).
Aufgrund der Nullen von \_DTOR\_END\_ und der wenigen Adressen in der GOT sind keine dieser Adressen geeignet, um überschrieben zu werden. Sehen wir also, wie wir fastbin anwenden können, um den Stack anzugreifen.
Wenn wir die Größe so ändern, dass sie 16 anstelle von 8 beträgt, dann wird fastbin\_index() fastbins\[0] zurückgeben und wir können dies nutzen, um den Stack zu überschreiben.
Die 4 Nullbytes sind erforderlich, damit der **av** auf diese Adresse zeigt und das erste Element eines **av** ist das Mutex, das den Wert 0 haben muss.
Außerdem wird in **av->system\_mem** (1484 Bytes über der Position auf dem Stack) genügend Müll vorhanden sein, der es uns ermöglicht, die Überprüfung zu umgehen.
Außerdem muss der benachbarte Chunk des freigegebenen Chunks größer als 8 sein -> Da wir gesagt haben, dass die Größe des freigegebenen Chunks 16 beträgt, müssen wir in diesem falschen Chunk nur eine Größe größer als 8 setzen (da die Shellcode im freigegebenen Chunk sein wird, muss am Anfang ein jmp stehen, der auf nops zeigt, die nach dem size-Feld des neuen falschen Chunks stehen).
In diesem Fall möchten wir einen Zeiger auf ein malloc haben, der vom Angreifer veränderbar ist (z. B. dass der Zeiger im Stack unter einem möglichen Überlauf zu einer Variablen liegt).
So könnten wir diesen Zeiger auf beliebige Ziele zeigen lassen. Nicht jeder Ort ist jedoch geeignet, die Größe des gefälschten Chunks muss kleiner als av->max\_fast und genauer gesagt gleich der angeforderten Größe bei einem zukünftigen Aufruf von malloc()+8 sein. Daher, wenn wir wissen, dass nach diesem verwundbaren Zeiger ein malloc(40) aufgerufen wird, muss die Größe des gefälschten Chunks 48 betragen.
Wenn das Programm beispielsweise den Benutzer nach einer Zahl fragt, könnten wir 48 eingeben und den veränderbaren malloc-Zeiger auf die nächsten 4 Bytes zeigen lassen (die möglicherweise zum EBP gehören, sodass die 48 dahinter bleiben, als ob es die Kopfgröße wäre). Außerdem muss die Adresse ptr-4+48 mehrere Bedingungen erfüllen (in diesem Fall ist ptr=EBP), d. h. 8 <ptr-4+48<av->system\_mem.
Wenn dies zutrifft, wird beim nächsten malloc-Aufruf, den wir als malloc(40) angegeben haben, die Adresse auf den EBP gesetzt. Wenn der Angreifer auch kontrollieren kann, was in diesem malloc geschrieben wird, kann er sowohl den EBP als auch den EIP mit der gewünschten Adresse überschreiben.
Ich denke, das liegt daran, dass wenn es freigegeben wird, free() speichert, dass an der Adresse, auf die der EBP auf dem Stack zeigt, ein Chunk mit der perfekten Größe für das neue malloc() gespeichert ist, und weist diesem die Adresse zu.
Zuerst wird die Größe des wilderness-Chunks mit einem sehr großen Wert (0xffffffff) überschrieben, sodass jede ausreichend große Speicheranforderung in \_int\_malloc() behandelt wird, ohne den Heap erweitern zu müssen.
Zweitens wird av->top geändert, damit es auf einen vom Angreifer kontrollierten Speicherbereich zeigt, wie den Stack. In av->top wird \&EIP - 8 platziert.
Victim erhält den Wert der Adresse des aktuellen wilderness-Chunks (des aktuellen av->top) und remainder ist genau die Summe dieser Adresse plus der Anzahl der Bytes, die von malloc() angefordert wurden. Wenn also \&EIP-8 bei 0xbffff224 liegt und av->top 0x080c2788 enthält, dann ist die Menge, die im kontrollierten malloc reserviert werden muss, damit av->top auf $EIP-8 für das nächste malloc() zeigt:
Es ist wichtig zu wissen, dass die Größe des neuen wilderness-Chunks größer sein muss als die Anforderung des letzten malloc(). Das bedeutet, wenn das wilderness auf \&EIP-8 zeigt, wird die Größe genau im EBP-Feld des Stacks liegen.
Die freigegebenen Chunks werden je nach ihrer Größe in den Bin eingefügt. Bevor sie eingefügt werden, werden sie jedoch in unsorted bins gespeichert. Ein Chunk wird nicht sofort in seinen Bin eingefügt, sondern bleibt in unsorted bins. Wenn ein neuer Chunk reserviert wird und der zuvor freigegebene Chunk verwendet werden kann, wird er zurückgegeben, aber wenn ein größerer Chunk reserviert wird, wird der freigegebene Chunk in den entsprechenden Bin verschoben.
Um den anfälligen Code zu erreichen, muss die Speicheranforderung größer als av->max\_fast (normalerweise 72) und kleiner als MIN\_LARGE\_SIZE (512) sein.
Reservieren Sie zwei mallocs, so dass der erste nach der Freigabe des zweiten überlaufen werden kann, nachdem er in seinen Bin eingefügt wurde (dh ein malloc größer als der zweite Abschnitt reserviert wurde, bevor der Überlauf stattfindet).
Das Ziel ist es, wenn wir einen Heap überlaufen können, der darunter einen bereits freigegebenen Abschnitt mit seinem Bin hat, können wir seinen bk-Pointer ändern. Wenn wir seinen bk-Pointer ändern und dieser Abschnitt der erste in der Bin-Liste wird und reserviert wird, wird die Bin getäuscht und glaubt, dass der nächste Abschnitt in der falschen Adresse liegt, die wir angegeben haben (zum Beispiel im Stack oder in der GOT). Wenn also ein weiterer Abschnitt reserviert wird und der Angreifer Berechtigungen dafür hat, wird ihm ein Abschnitt an der gewünschten Position gegeben und er kann darauf schreiben.
Nachdem der modifizierte Abschnitt freigegeben wurde, muss ein größerer Abschnitt als der freigegebene reserviert werden, damit der modifizierte Abschnitt aus den unsortierten Bins entfernt und in seinen Bin eingefügt wird.
Daher muss der Bin warten, bis malloc() ausreichend oft aufgerufen wird, damit der modifizierte Bin erneut verwendet wird und die Bin täuscht, indem sie glaubt, dass der nächste Abschnitt in der falschen Adresse liegt. Dann wird der gewünschte Abschnitt gegeben.
Um die Schwachstelle so schnell wie möglich auszunutzen, wäre ideal: Reservierung des anfälligen Abschnitts, Reservierung des Abschnitts, der geändert wird, Freigabe dieses Abschnitts, Reservierung eines größeren Abschnitts als des zu ändernden, Änderung des Abschnitts (Schwachstelle), Reservierung eines Abschnitts derselben Größe wie der verwundbare Abschnitt und Reservierung eines zweiten Abschnitts derselben Größe, der auf die gewählte Adresse zeigt.
Zum Schutz vor diesem Angriff wird die typische Überprüfung verwendet, dass der Abschnitt "nicht" falsch ist: Es wird überprüft, ob bck->fd auf victim zeigt. Das heißt, in unserem Fall, ob der fd-Pointer des falschen Abschnitts, der im Stack angezeigt wird, auf victim zeigt. Um diesen Schutz zu umgehen, müsste der Angreifer auf irgendeine Weise (wahrscheinlich über den Stack) in der Lage sein, die Adresse von victim an die richtige Adresse zu schreiben. Damit es wie ein echter Abschnitt aussieht.
Der Angriff ist wie zuvor, dh der bk-Pointer muss geändert werden und all diese malloc()-Aufrufe sind erforderlich, aber zusätzlich muss die Größe des modifizierten Abschnitts so geändert werden, dass diese Größe - nb <MINSIZEist.
Zum Beispiel muss die Größe auf 1552 gesetzt werden, damit 1552 - 1544 = 8 <MINSIZE(dieSubtraktionkannnichtnegativsein,daeinunsigned-Wertverglichenwird).
Es besteht im Wesentlichen darin, so viel Speicher wie möglich für Heaps zu reservieren und diese mit einer Schicht von Nops gefolgt von einer Shellcode zu füllen. Außerdem wird 0x0c als Polster verwendet. Es wird versucht, zur Adresse 0x0c0c0c0c zu springen, und wenn also eine Adresse überschrieben wird, die mit diesem Polster aufgerufen wird, wird dorthin gesprungen. Im Wesentlichen besteht die Taktik darin, so viel wie möglich zu reservieren, um zu sehen, ob ein Pointer überschrieben wird, und zu 0x0c0c0c0c zu springen, in der Hoffnung, dass dort Nops vorhanden sind.
Es besteht darin, durch Reservierungen und Freigaben den Speicher so zu strukturieren, dass reservierte Abschnitte zwischen freien Abschnitten verbleiben. Der zu überlaufende Puffer wird in einem der freien Abschnitte platziert.
<summary><strong>Erlernen Sie AWS-Hacking von Grund auf mit</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* Wenn Sie Ihr **Unternehmen in HackTricks beworben sehen** oder **HackTricks als PDF herunterladen** möchten, überprüfen Sie die [**ABONNEMENTPLÄNE**](https://github.com/sponsors/carlospolop)!
* **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an die** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repositories einreichen.