 So, damit begrüßen wir euch auch aus der Übersetzer-Kabine zum Talk Modern Windows User Space Exploitation von Saar Ammar. Mein Name ist Problame, mein Name ist Advin und wir setzen den Talk für euch von Englisch nach Deutsch. Okay. Hi. Okay. Hi zusammen. Also, zuerst mal vielen Dank dafür, dass ihr alle hier seid. Ich weiß, dass es durchaus großen Wettbewerb in diesem Slot gibt. Mein Name ist Saar Ammar. Ich bin am MSRC-IL aus Israel und ich spreche heute darüber, wie man beliebigen Code auf aktuellen Windows-Systemen laufen lassen kann. Ich bin ein Sicherheitsforscher und im Prinzip kümmere ich mich darum, Exploits zu finden und sie dann lauffähig zu machen. Ich mache auch bei Capstone Reflect Teams mit, CTF Teams. Davon habt ihr bestimmt schon mal gehört. Und ja, für diesen Talk ist es sehr wichtig, dass ihr euch folgende Frage stellt, worum geht es eigentlich im Leben? Ja, also, worum geht es eigentlich im Leben? Es geht darum, beliebigen Code ausführen zu können. Und es ist tatsächlich ziemlich einfach, dafür ein Prozess zu finden. Es geht darum, dass man zuerst eine Zero-Day Sicherheitsdücke findet, dann irgendwas in der Mitte macht und dann davon profitiert. Ja, und das war früher alles ziemlich einfach. Ich hoffe, ihr erinnert euch dann auch alle dran. Man konnte im Prinzip einfach irgendwo keinen ASLR haben, wenig Sicherheitsmitgationen usw. Und ja, im Prinzip hat einem nichts gestoppt. Aber das war alles sehr schön, aber auch gleichzeitig alles ziemlich gefährlich. Und heute haben wir das nicht mehr. Denn heute gibt es Mitigations, also Gegenmaßnahmen überall. Und zwar wirklich überall. Wir haben diese ganze lange Liste hier. Und worüber ich heute sprechen möchte, sind die internen von diesen Gegenmaßnahmen. Zunächst schauen wir uns erstmal die Prämitive an, um sie dann zu umgehen. Wir schauen uns die Grundlagen an, um sie zu umgehen, weil das kein einfacher Prozess ist. Und ja, da geht es eben darum, eine bestimmte Sicherheitsdücke zu finden und sie dann auf vielen verschiedenen Betriebszielen zu exploiten mit vielen verschiedenen Gegenmaßnahmen. Meine ursprüngliche Absicht war, eine richtige Windows-Connevalability zu nutzen und sie zu exploiten, aber das wäre dann ziemlich zeitaufwendig gewesen. Es braucht ungefähr drei Stunden und ich muss danach wieder mit etwas anderem weitermachen. Und stattdessen werden wir uns eine Windows CTF Challenge vornehmen aus 2017 und unterwegs schauen wir uns im Prinzip immer an. Ja, was ich damit noch irgendwie vermitteln möchte, ist, dass Windows CTF super sind. Ja, und dann gehen wir durch viele, viele Mitigations durch. So, die WinWorld Challenge, was war das? Es war eine Geschichte basierend auf Westworld, eine Serie aus dem Fernsehen. Die Herausforderung war, man hat einen Erzähler und der kann Roboter und Menschen erstellen. Sie können miteinander kämpfen oder miteinander reden. Aber sowohl Roboter als auch Menschen haben eine gemeinsame Basisklasse, die Person ist. Diese Operation kann man auf jeder Personinstanz ausführen. Für jede Personinstanz kann man das machen, egal ob Roboter oder Menschen sind. Das ist jetzt nicht, wie man eine Verwundbarkeit findet. Das ist, wie man ein Exploit findet. Und wir schauen uns also die Verwundbarkeit an. Wir haben ein uninitialisiertes Attribut in der Personinstanz. Es gibt die Membervariable ist bewusst. Im Roboter wird es mit falsch initialisiert, beim Personen wird es aber gar nicht initialisiert. Also haben wir hier eine uninitialisierte Variable, was ziemlich gut ist. Außerdem haben wir ein UseAfterFree, ein Benutzen nach dem Free-Bug. Wir teilen Referenzen zu Personeninstanten in vielen, vielen Plätzen. Aber man muss trotzdem wissen, wann man etwas frehen kann. Also haben wir hier ein SharedPointer, das ist ein Rapper um ein Pointer mit einem ReferenceCount. Jedes Mal, wenn wir einen Referenz dazu nehmen, wird der ReferenceCounter erhöht. Wenn der ReferenceCount 0 erreicht, wird das gefreet. Aber das Problem ist, es gibt hier einen Ort, wo ein Roboter in einen Menschen transformiert wird. Aber das Problem ist, dass der Code, der das macht, SCDMove benutzt. Und das ist sehr schlecht, weil das ist nicht das, was man mit SharedPointer machen sollte, sondern wir. Dann haben wir zwei verschiedene SharedPointer und die zeigen den gleichen Chunk vom Speicher. Und einer dieser SharedPointer kann dann irgendwann 0 erreichen und dann wird eben dieser Speicherbereich freigegeben. Und dann haben wir auf einmal einen Denkling Pointer, also einen Pointer, der auf einen bereits gefreeten Chunkzeit. Und das heißt, wir können einen DoubleFree haben. Ja, super. Also, das Problem ist, dass, wenn man nicht wirklich sagen kann, dass man eine Sicherheitslücke hat, wenn man nicht auch eine Möglichkeit hat, diesen bestimmten ExecutionFlow auszulösen. Das heißt, wir müssen diesen Roboter irgendwie in einen Menschen transformieren, bevor wir dann tatsächlich das ausführen können. Und ja, wir haben dann eben genau diese Bedingungen, die hier aufgelöst sind, die ein Zutreffen müssen. Zum Beispiel muss Person is Conscious nicht Fault sein, also es muss gesetzt sein. Und das heißt, und wir müssen halt eben auch noch diese uninzellisierten Wert vulnerability kombinieren. Und nur, wenn wir die beiden kombinieren, dann haben wir eben den Denkling Pointer vulnerability und die nicht gesetzten Conscious-Variable, die dann diesen Flow trägert. Also, nachdem wir jetzt so eine Use After Free vulnerability haben, lasst uns mal mit dem eigentlichen Spaß anfangen. Also, fangen wir mit Windows 7 an. Was wir zuerst verstehen ist, ist der Windows 7 Heap Allocator. Denn eine Basis für jede Use After Free Allocator ist, dass wir eine Allokation, die freigeben wurde, genau diese Stelle wiederverwenden für eine neue Allokation. Und das müssen wir irgendwie kontrollieren. Das ist genau der Weg, wie man Use After Free Bugs ausnutzt. Und wir haben in Windows 7 ziemlich viele verschiedene Allokatoren mit jeweils eigener Logik und eigenen Chunkgrößen und so weiter. Und da muss man irgendwie mit klarkommen, wenn man diese Variabilities exploiten möchte. Und in Windows gibt es dann zum Beispiel diesen Low Fragmentation Heap. Und das ist der ganze Punkt von diesem Allokator. Im User Space sind es Windows Vista. Und da möchte ich jetzt gar nicht so genau darüber reden, weil das eigentlich überall im Internet gut dokumentiert ist. Es ist im Prinzip wie Jay Malok. Aber es gibt dann noch so Structs, die heißen User Blocks, was ein Satz von gleichgroßen Blöcken im User Space Heap ist. Und jedes Mal, wenn man Malok Aufruf, bekommt man einen Block daraus. Und dann, wenn man Free Offruf, gibt man den wieder zurück. Und das heißt, man hat da keinerlei Fragmentierung und so weiter. Das ist ganz praktisch. Das Problem ist, in Windows 7 gibt es Metadaten, die heißen Free Entry Offset, in den ersten zwei Bytes in einem freien Chunk nach dem Chunkheader. Das heißt, das ist überhaupt nicht geschützt. Und diese Metadaten sind ein Indikator für den Allokator, welcher Chunk zum User in der nächsten Allokation zurückgegeben werden soll. Und das ist ein ziemlich starkes Primitiv. Dann ist das zweite Problem noch der LFH, also wieder Low Fragment Langtation Heap Allokator, dass der bewusst fragmentiert. Und man sieht das zum Beispiel, wenn man hier diesen Test-Code hier nimmt und den ausführt auf ein Windows 7-System, dann sieht man auf der linken Seite halt, dass wir eine Gehieballokation machen. Und auf der rechten Seite sieht man die Adressen davon. Wir sehen, dass die alle genau nebeneinander liegen und alles sehr vorhersagbar ist. Und der interessanteste Teil dabei ist, dass der LFH sich dabei in Last In First Out im Fall, also nach dem Last In First Out Prinzip arbeitet. Und das heißt, man kann hier einen User auf der Freebug sehr einfach ausnutzen. Nachdem wir jetzt andere Objekte auf den gleichen Ort allokieren können und falsches arbitrary Code execution wollen, haben wir ein arbitrary read. Wir nehmen ein SDD String. Man kann einfach ein SDD String auslesen mit dem Infokommando, nämlich den Namen einer Person oder eines Robotos. Aber dort kann ich irgendwas reinschreiben. Ich kann jedes einzelne Byte dort kontrollieren. Ich kann dort einfach den Point nehmen und es irgendeine Adresse setzen und beliebige Adressen lesen. Die Länge des Strings ist auch ein Feld, was da drin ist. Das heißt, wir haben hier beliebige lange Auslese gefällt. Wir können mit Update auch einen beliebigen Schreibvorgang machen, auch mit beliebiger Länge. Das ist natürlich noch nicht genug, weil wir Code ausführen wollen. Wir haben eine virtual Funktion in der Klasse, die es uns erlaubt. Wir haben, wenn zwei Personen sich treffen, dann wird ein Callback aufgerufen. Das geht über ein V-Table, und deswegen können wir den Funktionspointer benutzen, um an beliebigen Adressen zu springen und dort Code auszuführen. Aber ich brauche wahrscheinlich mehr als eine Adresse. Ich muss wahrscheinlich mehr als einmal lesen. Wir können jetzt hier einen sehr eleganten Trick machen. Wir können die Unencounterfunktionen korrupten. Jedes Mal, wenn zwei Personen sich treffen, dann wird die Unencounter aufgerufen. Als ersten Parameter kriegt sie eine Person. Dann schreiben wir alle Personen Instanz. Ich löse einfach diese Funktion einmal aus, und dann kann ich überall hinschreiben. Tricks wie diese sind genau die, die Exploits zuverlässig machen. Wir versuchen, die Verrundung zu selten wie möglich auszulösen. Wir haben jetzt dieses Primitiv für uns gebaut, Read-Draid-Jump-Promitiv. Aber es gibt ja ASNR, also Adress-Space-Layout-Randomisierung. Das bedeutet, dass wir überhaupt nicht wissen, wo alles möglich hier ist. Wir müssen uns irgendwie pointergenauer angucken. Das Problem ist, dass wir hier für noch gar kein Primitiv haben. Wir lesen die ganze Zeit absolute Adressen, und wir wissen nicht, welche Adressen wir da hinschreiben müssen. Zum Beispiel an der Unencounter-Adresse. Das heißt, es gibt eben andere ... Das heißt, die Punkte sind nicht wirklich vorhersackbar. SCD-Vector zum Beispiel macht das sogar undemant. Das heißt, man kann SCD-Vector nutzen, um folgende Tricks zu verwenden. In der Read-Hit hat eine Person zum Beispiel Freunde und Personen in der Challenge haben auch Freunde, und jede Person hat einen Vector von all ihren Freunden. Das heißt, wenn wir eine Person haben und der dann sieben Freunde hinzufügen, enthält dieser SCD-Vector dann genauso viele ... Ah, genau, dann enthält der SCD-Vector genauso viele Personen wie ein einzelnes Personenobjekt groß ist. Und das ist sehr, sehr wichtig. Merk durch das, bitte. Das heißt, wir können die Allokation von einem SCD-Vector triggern, indem wir eben Freundinnen zufügen, und können damit dann nachher die V-Table von SCD-Vector dampen. Das ist ja auch relativ möglich, weil es in der Erdata-Section ist. Und dann müssen wir nur noch die Attribute von SCD-Vector kontrollieren. Und dann gibt es zum Beispiel halt das Feldlänge vom SCD-Vector, das eventuell in eine große Zahl sein könnte, und da haben wir keine Kontrolle drüber. Aber das ist okay, weil wir ja gerade in einem CTF sind und die Prozesse einfach widerstarten, wegen der Adresse bei SCD-Randomization wird aber nach jedem Restart jedes ... Ja, ist das Layout dann wieder anders. Aber jeder ... Okay. Jeder Pointer, der vorher so war, erinnert sich nicht, weil diese Bibliothekspointer sich nur nach einem Reboot ändern. Wenn wir jetzt das haben, dann können wir eine DLL laden, wir können V-Tables corrupten, wir können ganz viele Sachen tun, wir können was auch immer tun und nichts hindert uns daran. So, machen wir jetzt einen Rob- und Return-orientierte Programming, wir schreiben Shellcode, und das wird jetzt Zeit für die Demo. Ich hoffe, dass die Demo jetzt genauso funktioniert, wie nicht auf der Bühne. Ich werde all diesen Code veröffentlichen. Ihr könnt es zu Hause ausführen, bitte macht das. Jetzt lasst uns zu den Windows 7-Explodes gehen. Okay, awesome. Jetzt starten wir die Wirtel in der Maschine, weil wir hier in CTF sind. Da habe ich entschieden, das beliebige Code, den wir ausführen, eine Flagg sein. Und die Flagg ist Eider, weil wir alle Eider mögen. Lass uns das ausführen. Nur, um sicherzugehen. Okay. Hoffen wir mal, dass das jetzt funktioniert, so wie nicht auf der Bühne. Wir liegen in ein paar Addressen. Und jetzt haben wir den Point zum Heap, zum Stack usw. Und jetzt haben wir die Flagg, nachdem wir den Rob ausgeführt haben. Und jetzt gehen wir auf unsere Reise zum nächsten Betriebssystem. Wenn ihr das ausführt, dann wird das auf jeden Fall schief gehen, weil Shape failed. Wir haben einen riesigen Unterschied zwischen dem LFH, zwischen Windows 7 und Windows 10. Da haben ein paar gute Ingenieure dran gearbeitet und viel Zeit dran reingesteckt. Und der LFH sieht jetzt sehr kompliziert aus. Als erstes haben wir nicht mehr dieses Free Entry-Feld. Wir haben stattdessen ein Bitmap, die sagt, wo Dinge alluziert sind und wo nicht. Außerdem sind alle die Allocations randomisiert. Also man kann nichts voraussagen, wie in Windows 7. Und wenn wir jetzt denselben Test haben, wie in Windows 7, und den auf Windows 10 ausführen, oder Windows 8 ist quasi das Gleiche, dann sehen wir auf der rechten Seite, dass die Addressen im kompletten Chaos sind. Und wir sehen, dass der Ausgabe nicht voraussehbar ist. Und das ist schwer, etwas in den gleichen Orts zu bekommen. Deswegen ist es auch sehr unwahrscheinlich, dass man den Glitzenschrank wiederkriegt. Wie können wir jetzt diese Medikation umgehen? Weil das Ziel im Leben ist sehr, dass die Medikation, die wir hier haben, umgehen, weil das Ziel im Leben ist, Exploits und beliebige Codes auszuführen. Also versuchen wir jetzt, die Implementation von dem zufälligen Allocator zu verstehen. Es ist sehr, sehr interessant. Wir haben jetzt eine Bitmap, die sagt für jeden Teil, ob es Allociert ist oder nicht. Also sucht der Allocator einen zufälligen Ort und scannt von dort aus nach einem Bit, was nach einem Efrain-Chunk aussieht. Und dann returnt das das. Weil die Position im Bitmap zufällig ist, wird natürlich auch die Allocation zufällig sein. Aber wie ist dieser Zufall gewählt? Wir haben dafür ein fixes Pool von Zufall, der am Start des Prozesses gewählt wird. Und das ist okay, denn das ist ein kryptografischer Zufall, das ist safe. Und jedes Mal, wenn wir ein Alloc machen, dann nehmen wir den aktuellen Zufallswert aus diesem Array. Und das ist benutzt als der Index zum Scan der Allokations-Bitmap. Ja, daran kann man halt eben sehen, dass die Allokationsreinfolge komplett zufällig ist. Also sehen wir hier an dem Beispiel. Auf der rechten Seite sehen wir die Userblocks, also die Heap-Blocke, die verteilt werden. Und auf der linken Seite die korrespondierte Bitmap. Das heißt, jetzt rufen wir Maloc auf, wählen eine Zufällig-Position in der Bitmap und fangen dann an von dort zu scannen. So, jetzt wählen wir zum Beispiel mal ein Null, das heißt der Freier-Chunk, also Freier-Block, und das heißt, wir flippen die Bits und geben diesen Teil dann an den Nutzerzeug. So, jetzt ein anderer Wert. Jetzt sind wir zum Beispiel bei einem allizierten Chunk und das heißt, wir fangen an von dort zu scannen, bis wir einen freien Chunk finden und flippen dann eben wieder das Bit und geben den entsprechenden Chunk zurück. Dabei gibt es jetzt ein relativ großes Problem, denn alle der zufälligen Werte sind in einem staatlichen Array. Und das heißt, was passiert denn jetzt, wenn wir mehr als die Größe des Arrays-Allokationen durchführen. Das passiert tatsächlich relativ schnell, denn viele Prozesse machen sehr viele Allokationen und das heißt, wir haben dann Rapping von dem Array, das heißt, wenn wir am Ende sind, fangen wir wieder am Anfang an. Das heißt, dass wir dann ziemlich schnell wieder die gleichen Werte verwenden. Das heißt, wenn man eben zum Beispiel dann dieses Proof-Concept ausführt, was ich hier gezeigt habe, was im Prinzip eine Allokation ausführt, den wieder freigibt und dann macht es 0xff mal genau das. Dann kann man tatsächlich sehen, dass die zweite Ausführung der Schleife tatsächlich genau wieder die gleichen Werte aus diesem Zufall-Index-Array nimmt. Und der ganze Sinn dieser Schleife ist eben diesen Pointer in diesem Zufall-Start-Array zu inkrementieren und das ist tatsächlich ziemlich deterministisch. Es ist ziemlich cool und es macht mich ziemlich froh, Tricks wie diese funktionieren zu sehen. Und natürlich hat das jetzt genau mein Problem hier gelöst, denn ich kann das jetzt ausführen und ich sehe, dass es mit einer Wahrscheinlichkeit von 1 funktioniert. Super. Das heißt, wir haben dieses Shaping-Issue, also das Shaping-Problem gelöst. Und jetzt wissen wir tatsächlich mal einen Code auszuführen. Und jetzt könnte ich eine Funktion aufrufen, die mir vielleicht die Adresse vom Stack oder so geben könnte, denn es ist relativ einfach, solche Funktionen aufzurufen. Also Stack-Keeping ist einfach, aber Stack-Leaking ist einfach, aber Heap-Leaping ist komplizierter. Das heißt, wir nutzen jetzt mal RTLP Stack-Limits verwenden und tatsächlich Crash das aber. Und in 29, wahrscheinlich Version 29, gibt es irgendeinen Feature, das Fast-Fail heißt und dann eben zu diesem Crash wird. Und dieser Fehler sagt im Prinzip, irgendetwas sehr Schlimmes ist passiert. Ich habe keine Ahnung, wie ich weiter machen soll. Hören wir auf und machen zu. Und wenn ein Prozess das macht, dann ist auf jeden Fall etwas Schlechtes passiert. Aber gehen wir einfach ein paar Bits hoch im Stack und schauen, was passiert oder wo das herkommt. Man sieht hier, dass das von Guard Check, I-Call, FPTR. Das heißt, wir sehen hier, dass es tatsächlich a Bytecode in NTDLL ist. Und dann gibt es noch CFG, das ist Control Flow Guard. Die Aufgabe von Control Flow Guard ist, dass jeder indirekte Verzweigungsaufruf okay ist. Also jeder Indirekt Branch ist okay. Und das heißt, wenn wir einen Funktionspunker aufrufen, dann gibt es im Prinzip eine White List von Funktionen, die aufrufen werden dürfen, über einen direkten Funktionsaufruf. Und wenn dieser Aufruf nicht darin enthalten ist, dann gibt es eben zu dem Crash, den wir gesehen haben. Dann kommt es zu diesem Crash, den wir gesehen haben. Es gibt da dann zahlreiche Internets. Schaut euch das vielleicht mal an, wenn es euch interessiert. Das ist auf jeden Fall ziemlich cool, der Talk, den ich da verlinkt habe. Aber es geht ja eigentlich darum, dass wir Aborträern Code ausführen können. Das heißt, wir müssen jetzt irgendwie um das Control Flow Guard drum herum arbeiten. Es stimmt tatsächlich, dass Control Flow Guard uns das Leben tatsächlich sehr viel schwieriger macht. Das heißt, wir können nicht mehr zu beliebigen Funktionen springen, denn die sind alle nicht mehr in der White List. Ich kann nicht mehr einfach irgendwo in die NTDLL reinspringen und so weiter. Und all die Funktionen, die mir den Stack Pointer geben könnten, sind eben jetzt nicht mehr verfügbar. Aber wir haben noch immer, aber es fehlt immer noch was, um die Return Adressen auf dem Stack zu modifizieren. Das heißt, wenn wir im Prinzip einfach wieder auf Return-Oriented Programming, also Rob zurückfallen, dann könnte das wieder funktionieren. Also, probieren wir das mal. Machen wir mal wieder eine Demo. Das ist sehr wichtig dafür. Ich hatte ein bisschen was Zufälliges hier am Laufen mit Windows 10 TH1. Schauen wir mal, ob es jetzt funktioniert. Ansonsten, wie gesagt, der Code wird veröffentlicht, und ihr könnt es dann zu Hause ausprobieren. Also, probieren wir mal TH1 aus. Also, wir haben jetzt hier wieder so ein Flag. Ja, genau. Hier, I Love Ida, blablabla. So, versuchen wir mal, diesen Angriff auszuführen. Das ist die richtige IP. Und hoffen wir mal, dass jetzt alles funktioniert. Wir leaken die Adresse vom Binary. Und wir leaken die Adresse von UserRT von IntelliD. Ah, okay, StartRob hat nicht funktioniert. Manchmal macht die VM da Probleme. Okay. Ja, also die VM macht hier manchmal Probleme. Sorry. Ja, wie gesagt, der könnte es so ausführen. Ja, schauen wir mal, ob es jetzt funktioniert. Ja, der Code hat eben da eben zuvor drinnen. Das ist ein Problem. Okay. Ja, so, uns hat funktioniert, und wir haben das Flag. Ehrlich gesagt, denke ich, dass ich jetzt eine ... Okay, fantastisch. I Love Ida so much, und sorry, Ida, ich liebe Ida, das ist eine gute Flagge. So, lasst uns weitermachen. Windows 10 erst 2, erst 5. Das Letzte. Wenn wir diesen Proof of Concept jetzt auf Windows 10 erst 5 ausführen, dann sehen wir, dass es nicht klappt, und zwar deterministisch nicht klappt, weil wieder was sich geändert hat, nämlich der Zufall, den wir ausgenutzt haben, der wurde jetzt gefixt, seit Bild 16.179. Wenn ihr das euch anschauen wollt, dann schaut euch diesen Link hier an. Das alles, bitte schaut's euch an. Aber wieder müssen wir bloß das, den Zufall umgehen. Das was ich brauche ist nicht, dass zwei Dinge direkt hintereinander kommen, sondern alles was ich brauche ist, dass ich an Locations über den Heapspray möchte und irgend eine davon muss den free, den freien Schank überschreiben. Ich kann es einfach versuchen, ob es funktioniert. Weil es bloß eine Allokation ist, könnte es funktionieren. Wenn es so und direkt danach wird es wahrscheinlich funktionieren, viel später wahrscheinlich nicht. Und ich habe mal geschaut, wie oft das funktioniert. Und hier seht ihr die Anzahl der Allocations, die ich machen musste, um den letzten freien Schank zu kriegen. Und das ist gar nicht so schlecht, wenn ihr euch das anschaut. Schauen wir uns also einfach mal an auf Fitness 10. Also schauen wir uns einfach mal an, 255 davon zu sprayen. Es funktioniert hauptsächlich indem wir den Spraycode multiplizieren, mehrfach ausführen. Und jetzt versuchen wir wieder arbitrarien Codes auszuführen. Alles sollte okay sein. Warte. Wir crashen schon wieder, weil wir ACG haben beliebiger Codes Schutz. Es tut genau das, was der Name sagt. Es versucht die blibige Codes Ausführung zu verhindern. Es gibt neue Beschränkungen für Pages, nämlich Virtual Alloc fails, falls man ausführbare Seite kriegen möchte. Es gibt Workgrounds, aber die werde ich erst später publishen. Außerdem kann vorhandener Code nicht verändern. Das wird auch von diesem Schutz gesichert. Also natürlich gibt es wieder Workgrounds, aber es gibt auch, sie sind häufig auch wieder gefixt. Aber es gibt wieder nichts, was die Integrität der Return Adresse checkt. Es hat vor 2000 Jahren funktioniert, es funktioniert heute und es ist gut. Ich kann einfach Load Library aufrufen und irgendeine signierte DLL laden. Code Integrity Guard verhindert das Laden von unsignierten DLLs. Ich wollte wirklich über Edge reden, denn Edge ist ein sehr cooles Gesetz für das. Sie hat ACG, ACG, ACG und so weiter. Es hat viele, viele Schütze, aber ich habe keine Zeit, darüber zu reden. Viele Grüße an Ivan Frantick. Er hat viele, viele Fehler gefunden und hat ein sehr cooles PDF darüber geschrieben. Bitte schaut es euch an, ich habe keine Zeit dafür. Hier habt ihr die Links und kriegt ihr einfach an. Dann gab es noch Alex Ionesco, mein guten Freund, der einen coolen Code für Edge befunden hat, für ACG im Betriebsturm tatsächlich. Er hat tatsächlich einen sehr coolen Talk darüber gehalten, der ist hier verlinkt. Alex, ich liebe dich. Jetzt müssen wir zum Grundlagen zurückkommen, Arbitrere Code Execution. Noch mal sicherzustellen, dass wir irgendwas machen können. Machen wir jetzt Robb auf dem Stack, aber das ist vielleicht cool für CTS oder so was, wenn man eine sehr kurze return-oriented Procarving-Chain hat. In der echten Welt wird man tatsächlich sehr viel komplexere Angriffs-Kette haben. Das sieht man zum Beispiel auch im iOS-Exploit. Also versuchen wir mal, Create Process oder so was auszuführen, um sich hier zu stellen, dass wir tatsächlich noch in der Kontrolle sind, darüber, was hier eigentlich abläuft. Also noch eine Demo. Gehen wir in Redstone 5. Und lass uns versuchen, ein System aufzurufen. Ich veröffentliche das. Ihr seht, dass der Proof-of-Concept tatsächlich ziemlich elegant ist. Und der Robb-Attack ist dann tatsächlich einfach nur System. Das seht ihr hier. Das ist DVM. Super, wir haben jetzt keinen Speicher. Dann sind wir fertig irgendwann. Das ist doch für die Verspätung. Also sagen jetzt mal, die Flag ist A. Und hier seht ihr, dass es tatsächlich D ist. Und wir haben jetzt eben hier die Challenge. Und jetzt versuchen wir mal, den PRC auszuführen. Da war jetzt noch die Finder IP. Das funktioniert. Das ist eine Basis-Adresse, UCRT und so. Kommt schon. Super. Und ich baue auch NTDL. Und jetzt, bevor wir die Attacke ausführen, lass mich mal irgendwas ausführen hier. Ein Debugger an den Prozess dran hängen. Und lass uns Breakpointen auf System. Ich bin so sorry für die Team. Es ist wie in DVM. Und wir haben einen Hitz auf System. Und jetzt haben wir tatsächlich einen Hit bei System. Aber es ist bei System Core System. Und das haben wir im Debugger gesehen. Jetzt sollten wir hier das Flag sehen. Und wir sehen Access Violation in der Prozessstür. Das heißt, wir waren in System. Also, was ist hier eigentlich abgegangen? Natürlich gibt es hier noch eine weitere Mitigation. Also Gegenmaßnahme. Die heißt Child Process Restriction. Und das ist genau das richtige Verhalten, das ich erwarte. Denn du solltest normalerweise gar nicht die Erlaubnis dafür haben, aufzurufen. Also, normalerweise sollte eine Anwendung das nicht machen. Du willst normalerweise nicht, dass ein beliebiger Editor oder irgendwas einfach System aufrufen kann. Und Child Process Restriction ist tatsächlich eine ziemlich coole Gegenmaßnahme, also Mitigationsmaßnahme, weil die einfach ziemlich einfach ist. Die verbietet einfach einen Prozess, beliebige Kindprozesse, zu sparen. Und das macht tatsächlich sehr viele Exploits sehr viel schwerer. Natürlich kann ich die Flag jetzt für Redstone 5 nicht direkt vor allen Augen liegen. Haben wir noch ein bisschen Zeit dafür. Wir haben tatsächlich noch einen Exploit. Jetzt solltet ihr das ja auch wieder sehen. Der Laptop antwortet irgendwie nicht. Sorry. So, wer melzt. Ihr wisst ja schon, wie ich die Flag liegen möchte. Und im Prinzip läuft es immer auf derselbe Technik hinaus. So, in stead of the detailed Roche, that I just showed you. It's very, very short. It's very, very elegant. Die Robattacke, die ich euch eben gezeigt habe, die ist ziemlich elegant. Stattdessen habe ich jetzt noch eine andere Robattacke. Die Main-Routine sieht ziemlich endlich aus. Adresse liegen und Rob ausführen. Wir machen da jetzt Open, Read, Put, Flash, All, um die Flag zu legen. Also, wir starten jetzt keinen Child-Prozess mehr, sondern hoffentlich hat sich die Data-System-Zugriff-Funktionen auf. In der echten Welt, also das ist jetzt eher so ein Beispiel für ein CTF, und in der echten Welt hätte man dann, wie gesagt, deutlicher, eleganter oder kompensierterer Sache. So, schauen wir mal, ob das jetzt funktioniert. Ja, Adresse vom Main-Binary liegen, hat geklappt. UCRT-Base liegen. Komm schon, super. Entweder liegen, Rob ausführen, und das hat geklappt. Super. Vielen Dank. Vielen Dank. Wie gesagt, alles wird veröffentlicht. Es ist eine CTF-Harausforderung. Aber man kann es auch auf eine gute Art und Weise machen. Das ist jetzt die Demo gewesen. Gut. Was passiert denn jetzt, bevor wir wieder zu dem CTF zurückgehen? Es gibt noch viel, viel mehr, was ich euch nicht in diesem 45-Minuten-Talk erzählt habe. Aber ich hatte einfach nicht die Zeit. Ihr könnt mich einfach eine Nachricht schreiben auf Twitter oder zu mir kommen und reden. Und wir können reden. Wir haben Container, Sandboxing. Die arbeiten auch an sehr wichtigen Dingen für die Sicherheit. Wir werden euch davon erzählen. Wir haben immer noch nichts, was die Integrität der Return-Adresse überprüft. Es gibt einen neuen Control-Flow Guard. Wir mussten es ausschalten, weil es eine sehr zuverlässige Race-Condition gab. Jemand hat einen Talk darüber gehalten mit den internen Details. Schaut euch den Talk an. Es ist wundervoll. Deswegen warten wir auf Zett von Intel. Es ist implementiert als Schatten-Stack, parallel zu dem normalen Stack. Dann schaue ich mir die Return-Adresse vom Haupt-Stack und vom Schatten-Stack an. Falls sie nicht gleich sind, brechen wir den Prozess ab. Es gibt dort eine Race-Condition, aber das will Intel jetzt im Prozess implementieren und dann sollte Damage-Robs komplett ausgeschlossen werden. Ich mag eigentlich sehr gerne Kernel und darunter. Wir haben LFG im Kernelspace eingeführt. Und das haben wir gemacht, weil LFH eingeführt, weil das viel sicherer ist als das, was wir jetzt vorher gemacht haben. Wir haben für Aufrufer, Flows, auch noch was. Es gibt sehr große, sehr gute Dokumentationen hier rüber. Schaut es euch an. Aber am wichtigsten, wir würden gerne eure Hilfe haben. Ich mag es am Morgen aufzuwachen und mit Leuten über tollen Zeug zu reden. Falls ihr also eine Umgehung dafür findet, cool, kommt zu mir. Ihr könnt mich auf Twitter benachrichtigen. Ich liebe es, darüber zu reden, über Exploits und so weiter. Es gibt noch etwas anderes, was wir tun. Es ist eine klasse Komplette zu zerstören, indem wir beim Alucieren immer alles auf Null setzen, was sehr viele Exploits entfernen sollte. Wir haben einen write-up gemacht. Und jetzt ist es standardmäßig SDL da. Das heißt, alles, was aluziert wird, wird geserert, genullt. Wir können die Verwundbarkeit nicht mehr ausnutzen, weil es alles Nullen sind. Das heißt, wir müssen das Flag irgendwie deaktivieren. Es ist sehr schön zu sehen, dass so ein cooles Zeug passiert. Es gibt Zeit, Danke zu sagen. AWE ist derjenige, der die Challenge geschrieben hat. Bitte schreibt mir Windows CTF Challenges. Ich bin Tom41sh für Hilfe und Whiskey. Vielen Dank für die brillanten Ingenieure, die an den Schützen arbeiten. Es ist sehr interessant in unserem Leben. Wir exploiten etwas und dann sehen wir irgendwie den Fix. Sie tun einfach sehr cooles Zeug. Das sind die Referenzen, alles, was wir gesehen haben. Ich glaube, der letzte Link ist down. Ich habe eine Nachricht an die Leute geschrieben. Mal gucken, ob es wieder da ist. Ansonsten, ja, weiß ich nicht. Sie sind eigentlich sehr nette Leute. Vielen Dank.