 Der Fortragende hat viel Zeit mit Explorz und jetzt mobiler Sicherheit verbracht, hat auch an der Blackhead schon einen Vortrag gehalten und er wird über Pegasus heute reden und jetzt Max, bitte. Ja, hallo zusammen. Ich heiße Max Basali und wir reden heute über die Interna von Pegasus. Ich komme aus Kiew, Ukraine und arbeite als Sicherheitsforscher bei Lookout und ich habe die letzten Jahre mich um Jailbreak Technik gekümmert und wir haben uns über, also haben diverse iOS Jailbreaks bearbeitet und was ist jetzt Pegasus? Pegasus ist eine hochqualitative Spionagesoftware, die kann komplett ein Gerät überwachen, kann alles Daten stehlen, das Mikrofon aus der Ferne aktivieren, die Kamera aktivieren, ohne dass man das an dem Gerät ablesen könnte. Also damit Pegasus funktioniert muss es das Device as Jailbreak also weil iOS normalerweise verhindert, dass Progame den Nutzer ausspielen. Das heißt, wir brauchen eine komplette Exploit Chain, wir müssen also Routrechte auf den Gerät übernehmen und zwar so, dass wir die auf jedem Device benutzen. Hier gibt es eine angsteinflößende Liste von Apps, auch die wir für sehr sicher halten, die Telegram, WhatsApp und Vibe und ich bin ziemlich sicher, dass ihr euren Lieblingsmessenger in dieser Liste findet und bevor wir uns da jetzt die technischen Details angucken, möchte ich zuerst mal darüber reden, wie wir an Pegasus, eine Kopie von Pegasus kommen. Also Achmed Mansour ist ein Menschenrechtsverteidiger und er hat den Award gekriegt, den man manchmal den Nobelpreis für Menschenrechte nennt und dieses Jahr hat Achmed eine Nachricht bekommen, dass jemand in einem Staatsgefängnis, also jemand ist in einem Gefängnis und er hat eine weitere Nachricht bekommen, am nächsten Tag aber er wurde vorher von Hacking Team angegriffen und von Gamma, also Fintfischer 2011 und jetzt hat er also Citizen Lab kontaktiert und hat diesen Link weiter geschickt, damit Citizen Lab sich das angucken kann und wir als, wir haben bekommen also dieses Sample, also diese Datei zugeschickt und es ging also zuerst mal jetzt um den technischen Teil. Also damit es funktioniert, verlässt sich Pegasus auf eine Exploration, also auf eine Reihe von Dingen um den Exploration durchzuführen und als erstes geht es um eine Speicherkorruption und daraufhin springt es in eine zweite Stufe und benutzt zwei verschiedene Techniken um den Körner zu kompromitieren und das eine ist um die Adress-Randomisierung zu besiegen und den zweiten dann um tatsächlich Code auszuführen im Körner und in der dritten Stufe installiert es dann einen speziellen Trick um auf Dauer auf dem Gerät gespeichert zu bleiben. Die erste Stufe, das ist wie gesagt eine Spearfishing-URL, die nur einmal benutzt wird, da ist JavaScript enthalten, was verschleiert ist und das prüft zuerst, ob es mit dem Gerät kompatibel ist, also iPhone 32 oder 64 Bit und Prozessortyp und besorgt sich dann die richtige Version von dem Code, den er dann ausführt und am Ende wird dann der Code-Execution in einem Webkit-Frame, also für ein Webbrowser ausgeführt. Also was ist der Hintergrund von dieser Sicherheitsproblem? Es kann dazu führen, dass man, wenn man eine Webseite aufruft, direkt Code ausgeführt wird und das Problem ist in einem Puffer, das von, also es geht um benutzerdefinierte Eigenschaften, die also an einem Objekt dran gehängt werden und das hat ein paar Argumente und diese, also Objekte können eine Beschreibung haben und mit dieser Beschreibung kann man dann Eigenschaften modifizieren oder anschauen. Also diese Diskriptoren werden an einem Vektor angehängt und damit die nicht alt werden, muss man dafür sich sorgen, dass sie nicht vom Speicher automatisch aufgeräumt werden, vom Garbage-Collector. Und man kann diesen Puffer benutzen, um Objekte daran zu hindern, aufgeräumt zu werden vom Garbage-Collector. Nachdem also der Garbage-Collector informiert, wo das nicht gelöscht werden musste, wie geht es dann weiter? Wenn Property aufgerufen wird, kann man im Prinzip als Eigenschaft jedes beliebige benutzerdefinierte JavaScript-Objekt verwenden und wenn während das geschehen wird, Garbage-Collection ausgelöst wird, dann werden alle nicht markierten Objekte entfernt. Gehen wir also noch ein bisschen weiter in die Details für diesen Markierungspuffer und den Garbage-Collector. Der Garbage-Collector ist dafür verantwortlich, Objekte zu löschen, wenn sie nicht mehr verwendet werden. Es läuft in zufälligen Intervallen und wenn immer zu viel Speicher verwendet wird oder wenn mehr Speicher benötigt wird. Wenn das Garbage-Collection testet, ob das Objekt wirklich gelöscht zu werden, testet es, ob das Objekt von irgendwo referenziert wird. Und da vertestest die alle eine Liste und in diesem Fall wird wieder eine spezielle Liste verwendet, die nennt sich Slow Append, langsames Anhängen. Wenn der Wert also diesen Markierungspuffer angehängt wird, dann wird das Objekt vom Stack, wo es vorher gespeichert wird, auf den Heap umgeschoben. Deswegen dieses langsame Anhängen, damit das nachher auf dem Heap verfügbar bleibt. Slow Append verschiebt also Puffer vom Stack auf den Heap und dann sind sie nicht mehr automatisch von der Garbage-Collection ausgenommen. Und um sicherzustellen, dass sie nicht gelöscht werden, müssen sie noch einer speziellen Liste, müssen sie den Heap-Kontext hinzugefügt werden. Slow Append versucht also diesen Kontext hinzugefügen und das Objekt der markierten Liste hinzugefügen. Hier gibt es jetzt das Problem, weil wenn der Heap-Kontext angefragt wird, der kann nur für komplexe Objekte angefragt werden. Also nicht für primitive Objekte wie Integers oder Wahrheitswerte oder dergleichen. Für die kann man keinen Heap-Kontext anfragen, die werden nicht markiert. Und es gibt jetzt einen Bug in diesem Slow Append. Wenn also jetzt der Puffer verschoben wird vom Stack-Speicher auf den Heap-Speicher und eine der Eigenschaften, die gesetzt wird, ist eine simpler Eigenschaft, die nicht beschützt werden muss, dann wird die nächste Eigenschaft ebenfalls nicht beschützt, obwohl sie vielleicht beschützt werden müsste, weil sie ein komplexes Objekt ist. Und das ist der Bug. Das heißt also, in Wirklichkeit gibt es nachher die Referenz auf das JavaScript-Objekt noch. Wenn also in einem Aufruf von diesem Define-Property das aufgerufen wird, dann wird eventuell die letzte Referenz auf das Objekt dadurch gelöscht. Dann wird das Objekt gelöscht, obwohl es eigentlich noch von der Property verwendet wird. Und das können wir ausnutzen. Wenn wir also hier unser Subjekt ankommen, was wir eigentlich anschauen, da gibt es ein Objekt, es hat zwölf Diskriptoren, die ersten neun davon sind, sind alle null. Und wenn es der neunte Wert hinzugefügt wird, dann wird das Slow Append ausgelöst wird und der Puffer wird vom Stack-off den Heap verschoben. Und die nächsten, die nächsten beiden, die nächsten Werte, die, das ist die Länge und wie viele Objekte belegt werden oder dergleichen, die werden dann nicht den Merkzeit hinzugefügt. Das ist der Fehler. Wenn wir jetzt also die Markierungen hinzufügen auf den, auf der Länge-Eingeschäft, dann wird diese, wir haben als Länge hier Not-Number hinzugefügt. Das ist noch, Kanazali muss jetzt konvertiert werden. Dafür wird eine Funktion aufgerufen. In dieser Funktion erzwingen wir es, dass der Gabelsch-Charakter aufgerufen wird, indem wir ein riesiges Array anlegen. Was für darum dann dazu führt, dass das alte Objekt, was jetzt inkorrekterweise nicht beschützt wurde, nicht, was wird so freigegeben. Und wir haben auch noch eine Referenz darauf. Wir können es in diesem Objekt jetzt herumschreiben, obwohl es nicht mehr verwendet wird. Und auf die Art und Weise können wir dann tatsächlich im Endeffekt Code ausführen. Die zweite Stufe ist jetzt wie der eigentliche Code, der jetzt hier mit der ausgelöst wird mit der komprimierten Daten. Der wird jetzt den Kernel angreifen, wo wir Code ausgeführt haben, um dann die finale und dritte Stufe, nämlich das herunterladen, das eigentlich ein Systems zu machen. Dafür haben wir hier die Sicherung, die ausgenutzt wird, ist das CVE 4055. Der nutzt aus, dass die Konstruktoren für ein Kernelobjekt nicht korrekt prüft, ob die Grenzen eingehalten werden und sorgt im Endeffekt dafür, dass die Sandbox umgangen werden kann, weil die Grenzen nicht überprüft werden. Es geht hier um die Funktion aus anzuleist binary, die also binär Daten deserialisiert, die unterstützt diverse verschiedene Containertypen, Mengen unter Zuweisungslisten oder Arrays. Wenn man hier die zwei Abjekte übergeben, der Werte und die Länge, und es gibt keine Kontrolle der Länge-Eigenschaft hier. Das heißt, wir können jetzt die Länge des Objektes kontrollieren. Warum ist das ein Problem? Also das hier ist der Konstruktor von OSNumberInnet. Und wie wir es sehen, wird die Länge-Eigenschaft hier verwendet als new number of bits und überschreibt die Größe size. Das Problem ist, dass size in anderen Methoden verwendet wird, um festzustellen, wie groß dieses Objekt ist. Number of bytes ist Objekt. Was heißt, dass diese Angabe number of bytes jetzt komplett vom Objekt von Angreifern kontrolliert wird? Was wirklich schlecht ist? Weil das nämlich dann später hier verwendet wird, um wenn das Objekt kopiert wird, festzustellen, wie viel dort kopiert werden muss. Und das ist jetzt leider ein Puffer, der auf dem Stack liegt. Was also jetzt passiert ist, dass jetzt Speicher kopiert wird vom Kernel Stack auf den Hieb mit der vom Angreifer kontrollierten Länge. Wir können also jetzt festlegen, wie viele Bites vom Kernel Stack ins Usernet kopiert werden. Das ist was passiert. Das erste, was es also macht, ist es erzeugt ein Array von Eigenschaften, ein Addictioner, ein Zuweisungsliste mit dieser OS-Number mit diesem speziellen Typ mit einer sehr großen Länge. Diesen Fall 256. Dann müssen wir einen Client auf der Nutzerseite starten, der das OS-Number-Objekt desialisiert und dem Kernel erzeugt. Und jetzt müssen wir es lesen mit diesem iOS EntryGet property, was dazu führt, dass die 256 Bytes vom Kernel Stack jetzt kopiert werden. Und dieser Stack enthält Punkte auf die Kernelad-Strukturen und auf die Art und Weise können wir ermitteln, an welcher Adresse der Kernel anfängt im Speicher. Ja und damit können wir jetzt endlich im Kernel Code ausführen. Das Problem ist, dass der SetadIndex-Macro nicht wirklich ein Objekt benutzt und das können wir benutzen, um diese OS-Answerers-Binary-Funktion aufzurufen. Also es ist eine Funktion, die passt und deserialisiert Objekte für den Kernel und das Interessante daran ist, dass es auch KIO-Serialize-Objekte unterstützt. Das heißt, wir können auch eine Referenz auf ein anderes Objekt erzeugen und das wird also sehr praktisch werden gleich. Denn, also serialisieren und pausen, da werden immer, also wir benutzen dieses SetadIndex, um da einfach ein Array zu erzeugen, ohne dieses Objekt zu besitzen. Und das ist schlecht, denn der nächste Code der, also was jetzt passiert ist, dass der Object-Pointer released wird, also freigegeben wird. Das heißt, wir haben immer noch ein Objekt, so ein Object-Array und wir haben jetzt einfach eins der Objekte freigegeben, aber es gibt immer noch den Pointer darauf. Und wenn wir jetzt eine Referenz, also auf dieses Objekt erzeugen können, dann können wir den Kernel exploiten. Und das ist möglich, weil wir diese Referenz noch haben auf einem Objekt, was schon freigegeben wurde. Und so sieht dann der Exploit aus. Also zuerst erzeugen wir so einen Objekt, das einen Stringer erzeugt, der gleich weitergegeben wird. Und da sollen wir jetzt unser, also unser Objekt soll jetzt in denselben Bereich im Speicher passen. Das heißt, in unserem Beispiel haben wir 32 bytes, das heißt wir brauchen auch diese Größe. Und dafür ist OSData der optimale Kandidat, denn wir können die Größe von diesem Objekt genau kontrollieren. Und was wir jetzt machen können ist, wir erzeugen jetzt einfach so ein String mit einem falschen, mit einer falschen Tabelle, die irgendwie auf eine Funktion im Kernel zeigt. Das heißt, also OSDstring wird deserialisiert. Wir erzeugen ein neues Objekt, das ein OSData Puffer ist, was auf denselben Bereich im Speicher zeigt und wir benutzen es einfach nur anders. Das heißt jetzt haben wir Use After Free benutzt und jetzt benutzt Pegasus verschiedene Security Checks, zum Beispiel Set UID KPP, um zusätzliche Rechte zu kriegen. Und letztendlich wird dann auch die System-Partitionen schreib- und lesbar gemacht, sodass man dann für die nächste Stufe auch einen Loader runterladen und speichern kann. Die nächste Stufe enthält dann die eigentliche Spionagesoftware, die benutzt wird, um SMS zu lesen, Anrufe, persönliche Daten, all das. Also es gibt drei Gruppe. Die eine Gruppe ist die Prozessgruppe, da sind hauptsächlich Dienste, die Dinge abfuhrwachen, also das SID-Protokoll, um mit dem Commander Control Server zu reden und so weiter. Und die andere interessante Gruppe sind die Dylips, also die dynamischen Bibliotheken. Die wird libt Data umbenannt und die wird dann benutzt, um Zydia in Prozesse direkt zu injizieren. Also es wird dann benutzt, um direkt in dem Programm Funktionsaufrufe zu platzieren. Und die letzte Gruppe sind andere Gruppen, also insbesondere das JavaScript, das auch Code enthalten kann, um das unsignierten Code ausführen kann. Und das schauen wir uns als nächstes an. Also der Bug dazu, der existiert in dem JSC Binary, das ist ein Hilfeprogramm, was von JavaScript benutzt wird und das kann eben zur Ausführung von unsigniertem Code führen. Und mit dem RT-Body-Trick kann man es benutzen, um dauerhaft auf dem Programm, auf dem Gerät Kurtausführung zu bekommen. Und das liegt an einem, es kann Gott sei Dank nur aus dem Kontext von JavaScript-Programmen ausgeführt werden. Was ist jetzt das Problem? Es benutzt so ein Delegate-Problem, also wie bei C++ ein Getter-Setter. Und die so eine Funktion, die da gibt es, das kriegt als erstes Argument so eine Funktion und als zweite dann die Funktion, die dann gesetzt wird als der Getter. Das heißt, wir rufen dieses Set Delegate auf und dieses Ding benutzt ein Set auf und das ruft ein Set Early Value auf. Und hier ist das Problem, es gibt hier keine Prüfung, dass das Objekt tatsächlich auch, also tatsächlich auch ein Setter oder Getter ist. Das heißt, wenn irgendein anderes Objekttyp hier reingegeben wird, dann wird das fälschlicherweise gekastet auf so ein Setter oder Getter. Und wir sehen hier zum Beispiel, es hat kein echtes Objekttyp und wozu das führt ist, wenn wir hier dieselbe Funktion und wir kompilieren sie mal in IDAPRO. Das heißt, bei uns ist der Getter einfach nur eine Variable und der Delegate ist dieses Objekt. Und jetzt sehen wir, dass der Zeiger, der kann ein bliebiger anderer Typ sein. Also wenn wir hier zum Beispiel so eine Klasse schreiben, so eine JS Buffer View, die eigentlich nur hier so Objekte enthält, dann wird das M-Vector-Objekt überschrieben mit so einem Zeiger und das kann dazu führen, dass wir Schreiblesezugriff bekommen. Also wir haben hier zwei Data Views, die nennen wir Data View 1 und Data View 2. Wir überschreiben jetzt hier dieses M-Vector mit einem Zeiger auf das zweite Data View. Und wir können jetzt gleich Felder in diesem Objekt überschreiben. Warum brauchen wir das eigentlich? Wir können den zweiten Data View benutzen, um den Inverse, das gesamte Speicher einzublenden, indem wir den, dem Endeffekt bekommen wir auf die Art der Weise Zugriff auf den kompletten Speicher des Prozesses über diese beiden, über diese beiden Views. Einer von den beiden mappt einfach den kompletten Prozessspeicher von 0 bis 32 Bit für Gigabyte. Außerdem können wir das nicht nur verwenden, um den ganzen Speicher zu mapen oder zu lesen und zu schreiben. Wir können sogar Code ausführen. Dafür rufen wir diese Set impure Getter-Methode zweimal auf und verwenden sie um die, um die Adresse eines Objektes herauszufinden. Und wir verwenden, wir setzen an dort eine Methode, die hunderte von leeren Tri-Catch-Blocken hat. Und wir kompellieren die. Und um das dann passiert ist, dass dann jede Menge von diesen les- und schreibbaren Objekt-Speicher-Bereichen angelegt werden. Und der Just-in-Time-Compiler, Endeffekt, liegt all diese Regionen an und wir können dann dort hereinspringen und natürlich auch Code ausführen. Zum Abschluss gucken wir es noch an, wie wir dafür sorgen, dass wir Persistenz erreichen, dass also der Exploit auch auf dem System nach einem Neustart bestehen bleibt. Dafür verwenden wir diesen Artie-Buddy-Service mit dem speziellen Argument Early-Boot. Was da im Wesentlich passiert ist, wir nehmen irgendeine von Apple signierte Binary und nennen sie Artie-Buddy, dann wird die gestartet. Wir nehmen also hier die JSC, der JavaScript-Interpreter, nennen sie Artie-Buddy, die ist signiert, wird beim Starten ausgeführt. Und wir geben ihnen als JavaScript-Code diesen anverlegten, bösartigen JavaScript-Code, der dann Endeffekt dazu führt, als beliebiger Code ausgeführt wird. Auf die Art und Weise wird also der Kernel-Exploit bei jedem Start das Gerät noch mal neu ausgeführt. Es gibt noch ein paar Tricks, die Pegasus verwendet, damit es schwieriger ist, herauszukriegen, was da eigentlich los ist. Zum Beispiel sind das Einmal-Links, die werden, also wenn sie einmal verwendet werden, werden sie ungültig und können dann verwenden, dann weiß man, auf Google oder dergleichen. Das ist nicht mehr, nicht mehr nachfassend, was passiert ist. Es verschleiert die Objekte jedes Mal neu, wenn es neu verwendet wird. Es verschleiert sich selbst, damit es aussieht, wie eine Systemkomponente. Natürlich blockiert es das Updates von iOS selbst, damit man nicht, also Betriebssystem Updates installiert, damit alles wieder korrigiert wird. Um also Beweise wieder loszuwerden, werden die Caches und der Verlauf vom Safari gelöscht. Es hat außerdem einen Selbstzerstellungsmechanismus, der aus der Ferne oder mit einem Timeout, mit einem Zeitgeber ausgelöst werden kann. Über diese lange Liste von unterstützten Anwendungen hinaus, kann es außerdem die Mikrofon und Kamera zugreifen, kann auf die SIM-Karte zugreifen und dort Positionierungsdaten machen oder auch wie GPS oder Wi-Fi noch weitere persönliche Daten ermitteln. Wie kommt es in die Anwendungen rein? Wie gesagt, iOS hat ja eine Sandbox, die die Anwendung von einer isoliert. Pegasus kann da aus dem Körnerhaus eingreifen und einige kritische Funktionen überschreiben, dafür wird das System Sideya Substrate verwendet. Es funktioniert auf einer hohen Ebene ungefähr so. Auf der Anwendungsebene werden einige wichtige Funktionen der Anwendung und auch das Sandboxing Frameworks von Pegasus eingegriffen und Pegasus kann kontrollieren, was diese Funktionen tun und kann damit Kontrolle über die Anwendung übernehmen. Um das zusammenzufassen, Pegasus ist ein aus der Ferne verwendbarer Jailbreak, der wirklich auch der Praxis eingesetzt wird. Das ist deswegen besonders forschlangflößend, weil überhaupt keine Nutzerentaktion erforderlich ist. Das ist schon einige Jahre her, dass wir das zum letzten Mal gesehen haben. In diesem Fall wurden drei unabhängig voneinander kritische Sicherheitslücken benutzt, um diesen Jailbreak auszuführen. Ich bin besonders dankbar für CitizenLab, das uns dabei geholfen hat. Ein Sample, der malware zu bekommen, dass wir uns analysieren können. Den Leuten bei Lookouts sowie allen Forschern, die bei dieser Aktion beteiligt waren. Hier zum Abschluss noch ein paar nützliche Links, wo es alle Details gibt für die Sicherheitslücken, die ausgenutzt wurden, was genau Unterschied ist bei 32 und 64-Bit-Systemen. Also wenn ihr interessiert seid, dann schaut euch das an. Ich denke, das war es. Wir können jetzt also zu den Fragen übergehen. Also macht bitte schnell, wir haben nur noch wenige Minuten für die Fragen. Bitte geht es um den Mikrofon, es geht zuerst um den Signal-Engel. Und die Frage ist, gibt es irgendwelche Möglichkeiten, Programme zu bauen, sodass sie davor geschützt sind? Ja, das ist möglich, weil Pegasus verwendet eine der bekannten Techniken für Jailbreaks. Man kann also Gegenangriffe starten. Zum Beispiel ist die Systempartition als les- und schreibbar eingehängt, das heißt also man kann das erkennen und zu erkennen, dass ein Jailbreak auf dem Gerät läuft. Oder man kann nach bestimmten Dateien schauen, die Pegasus verwendet, aber wirklich es macht mehr Sinn generell den Kernel nach Patches abzusuchen, wie sie für Jailbreaks rektoristisch sind. Das Publikum wird jetzt noch mal gebeten, ruhig zu sein, bis die Q&A vorbei ist. Frage von Mikrofon 3 ist, was merkt denn der Benutzer während das alles passiert? Also du meinst, wenn das Gerät von Pegasus infiziert wird. Also das Angstanflüssen ist ja gerade, es gibt wirklich kein Anzeichen, dass irgendwas passiert ist. Man klickt auf einen Link, der Webbrowser öffnet sich und schließt sich und crasht und das war's. Es gibt keine neuen Anwendungen, in die man in wieder Liste der Anwendungen sehen kann, nicht zu sehen zumindest, aber im Hintergrund laufen jetzt drei neue Systemdienste, die aber nicht dem Nutzer sichtbar sind. Ich gibt's noch eine Frage vom Internet. Weißt du, ob dieser Exploit tatsächlich auch benutzt wird in der wirklichen Welt? Die Frage wird noch mal wiederholt, weil sie nicht richtig verstanden wurde. Also ich bin mir sicher, dass das sehr gezielte Angriffe sind. Diese Art von Sicherheitsdrucken von Exploids ist sehr teuer. So ein Art von Remote Jailbreak kostet so ungefähr eine halbe Million Dollar, wenn man den kauft. Das heißt, die Autoren dieser Spionagesoftware werden vermutlich nicht diese MyWare allen Verfügung machen, die werden also wahrscheinlich für sehr spezifisch auf bestimmte Ziele zugeschnitten Angriffen verwendet. Es ist schwierig zu sagen, wie viele Geräte von Pegasus infiziert wurden. Also es geht davon aus, dass es sehr sehr spezifisches für bestimmte Angriffsziele, weil es sehr teuer ist. Herzlichen Dank. Die nächste Frage kommt von Mikro5 und es geht darum, hast du irgendwelche Informationen über die Gruppe, die dahinter steht oder benutzen wir auch weitere Software? Ist das verbreitet? Also wir haben uns hier fokussiert vor allem auf die technischen Details, aber CitizenLab hat auch die Gruppe hinter NSO weiter untersucht. Das ist eine Art digitaler Waffendieler. Und da kann man in den CitizenLab Bericht sich anschauen, da gibt es dann die ganzen Details zu der Untersuchung. Dann ist die Frage, ob es noch eine Internetfrage gibt oder aus dem Raum? Nein, dann war es das. Herzlichen Dank. Es gibt Applaus für den Sprecher. Wir waren Ralf