SEMINARARBEIT im Studiengang Informationsmanagement und Computersicherheit Lehrveranstaltung AK Informationsmanagement und –Sicherheit 1 Exploit Generatoren und Obfuscation Tools (1) Ausgeführt von: Hermann Wagner, BSc Jovica Zuljic-Suljuzovic, BSc Marko Buczolich, BSc Begutachter: Ing. Thomas Mandl Wien, 08.02.2015 (1410303021) (1410303028) (1410303018) Kurzfassung Um Antivirensoftware und Intrusion Detection Systeme zu täuschen verwenden MalwareHersteller diverse Verschleierungstechniken (Obfuscation), damit ihre Schadprogramme und deren Kommunikation nach außen unentdeckt bleiben. So wird zum Beispiel DatenKomprimierung oder Verschlüsselung bei zu übermittelnden Daten verwendet, um Daten unbemerkt an Intrusion Detection Systemen und Paketfiltern vorbei zu schleusen und um die signaturbasierte Erkennung von Schadsoftware von Antivirensoftware zu umgehen. In dieser Arbeit werden die verschiedenen Verschleierungstechniken genannt und diese erläutert. Ziel ist es, dem Leser zu vermitteln wie einfach es ist einen frei verfügbaren und bekannten Exploit (der von allen gängigen Virenherstellern erkannt wird) zu nehmen, diesen mit Obfuscation-Techniken zu verändern und ihn anschließend unbemerkt von der Antivirensoftware zu downloaden und auszuführen. Dazu wurde in einem Proof-of-Concept genau dieses Szenario konstruiert und die Ergebnisse in dieser Arbeit dokumentiert. Zu den Ergebnissen gehören sowohl die detaillierte Vorgehensweise, als auch Angaben über verwendete Tools, benötigter Zeitaufwand und benötigtes Know-How. Basierend auf den Ergebnissen folgt eine Einschätzung der Bedrohung und eine Betrachtung und Bewertung von möglichen Gegenmaßnahmen. 2 Inhaltsverzeichnis 1 Einleitung ............................................................................................................... 4 1.1 Motivation .............................................................................................................. 4 1.2 Vorgehensweise und Gliederung ........................................................................... 4 2 Theoretischer Hintergrund ..................................................................................... 6 2.1 Exploits .................................................................................................................. 6 2.2 Code Obfuscation .................................................................................................15 2.2.1 Obfuscator ............................................................................................................15 2.2.2 Obfuscation in verschiedenen Programmiersprachen ...........................................17 2.2.3 Packer ..................................................................................................................34 2.2.4 Virtualisierung .......................................................................................................36 2.2.5 Deobfuscation .......................................................................................................37 2.3 3 Malware vs. Antivirus ............................................................................................37 Proof of Concept ...................................................................................................48 3.1 Vorgehensweise ...................................................................................................48 3.2 Durchführung ........................................................................................................49 3.3 Ergebnisse ............................................................................................................60 4 Gegenmaßnahmen ...............................................................................................61 4.1 Verbreitung von Malware ......................................................................................61 4.2 Verteidigungsmaßnahmen ....................................................................................63 5 Zusammenfassung ...............................................................................................72 6 Future Work ..........................................................................................................73 Literaturverzeichnis ..............................................................................................................74 Abbildungsverzeichnis ..........................................................................................................79 Tabellenverzeichnis ..............................................................................................................80 3 1 Einleitung 1.1 Motivation Nach einer Malware-Infektion stellt sich oft für die Betroffenen die Frage wie es die Schadsoftware auf ihr System geschafft hat, obwohl sie ihre Software immer upgedatet und eine angesehene und aktuelle Antivirensoftware installiert haben. Vor allem für Systemadministratoren und IT-Verantwortliche kann so ein Vorfall eine sehr unangenehme Situation darstellen, wenn sie dem Management erklären müssen wieso ihre teuren Sicherheitsvorkehrungen, wie Firewalls, Intrusion Detection Systeme und Virenscanner nicht Alarm geschlagen haben. Die Antwort ist, dass die Hersteller von Exploits und Malware diverse Verschleierungstechniken (Obfuscation) einsetzen damit ihre Schadprogramme und deren Kommunikation nach außen unentdeckt bleiben. So wird zum Beispiel DatenKomprimierung oder Verschlüsselung bei zu übermittelnden Daten verwendet, um Daten unbemerkt an Intrusion Detection Systemen und Firewalls vorbei zu schleusen. Verschlüsselung und Komprimierung der Malware selbst kann weiters dazu verwendet werden um die signaturbasierte Erkennung von Schadsoftware von Antivirensoftware zu umgehen. Neben den beiden bereits erwähnten Techniken gibt es noch einige weitere Maßnahmen, die verwendet werden. Die Hersteller von Antivirussoftware versuchen natürlich ihre Erkennungsmechanismen zu verbessern, es hat jedoch den Anschein als seien die Blackhats ihnen immer einen Schritt voraus. Basierend auf dem oben genannten Problem werden in dieser Arbeit die verschiedenen Techniken betrachtet, welche moderne Malware benutzt um unentdeckt zu bleiben. In einem Proof of Concept wird anschließend gezeigt wie einfach es ist Exploits und Malware für ein bestimmtes Programm zu finden und herunterzuladen und mit Obfuscation Techniken so zu verändern, dass diese anschließend unbemerkt von Antivirensoftware ausgeführt werden können. Um nachvollziehen zu können wie diese Obfuscatoren und Exploits funktionieren werden zuerst die theoretischen Grundladen erläutert. Zuletzt wird natürlich auch noch auf mögliche Gegenmaßnahmen eingegangen. 1.2 Vorgehensweise und Gliederung Ausgehend von der Problemstellung und den Zielen gliedert sich die Arbeit wie folgt: Kapitel 2 – Theoretischer Hintergrund Die Arbeit ist so ausgelegt, dass sie auch für NICHT-Security-Experten gut lesbar und nachvollziehbar ist. Daher orientiert sich das erste Kapitel an den Grundlagen zu Exploits, Code Obfuscation, Malware und Virenschutzsoftware und richtet sich vor allem an Leser die zwar aus der Informatik kommen, aber deren täglich Brot nicht die IT-Sicherheit darstellt. Für Penetration Tester, Malware-Programmierer und AntivirusEntwickler dürfte das zweite Kapitel bloß eine Auffrischung ihres Wissens darstellen. 4 Kapitel 3 – Proof of Concept Dieses Kapitel erläutert Schritt für Schritt wie eine vorhandene und den Antivirenherstellern bekannte Malware mit Obfuscation Tools so verändert werden kann, dass diese durch einen umfassenden Virenscan (zum Beispiel auf VirusTotal oder Anubis) nicht mehr erkannt wird. Kapitel 4 – Gegenmaßnahmen Um den Leser nicht mit der Erkenntnis zurückzulassen, dass die Abwehr eines gezielten Angriffes ohnehin nicht möglich ist, werden im Kapitel 5 mögliche Gegenmaßnahmen unter die Lupe genommen und erläutert. 5 2 Theoretischer Hintergrund In diesem Kapitel werden Exploits, Code Obfuscation, Malware und Virenschutzsoftware behandelt. Die Recherche über die theoretischen Grundlagen hat auch den Einstieg der Autoren in diese Thematik dargestellt. 2.1 Exploits Unter einem Exploit versteht man die Möglichkeit systematisch Schwachstellen in Programmen auszunutzen. Das systematische Ausnutzen wird dabei mit Hilfe eines speziell dafür angefertigten Programms oder Skripts bewerkstelligt, dem Exploit. Als Schwachstellen werden Sicherheitslücken (engl. vulnerabilities) und Fehlfunktionen (engl. bugs) bezeichnet, die bei der Entwicklung des Systems nicht berücksichtigt, übersehen, fälschlicherweise oder auch absichtlich (z.B. backdoor) implementiert wurden. Ziel eines Exploits ist sich Zugang zu Ressourcen zu verschaffen für die der Angreifer (Hacker) keine Berechtigung besitzt, das Erlangen von Privilegien, das System zu beeinträchtigen (zum Beispiel: Denial of Service). [1], [2] Sicherheitsexperten bzw. Sicherheitsforscher (Whitehat Hacker), die eine Schwachstelle finden, bedienen sich aber ebenso Exploits um Sicherheitslücken aufzuzeigen und zu dokumentieren. Dabei hat es sich eingebürgert, dass der Entdecker einer ausnutzbaren Schwachstelle auch gleich einen Exploit für diese schreibt und somit dem SoftwareHersteller und Benutzern der Software beweisen kann, dass die Schwachstelle auch tatsächlich ausnutzbar ist (engl. Proof of Concept). Umstritten ist weiterhin die Frage ob gefundene Schwachstellen und Exploits veröffentlicht werden sollen oder nicht. Aktuell geht die Tendenz in Richtung Veröffentlichung, da es den Anschein hat, dass die „Bad Guys“ ohnehin immer einen Schritt voraus sind und die gefundenen Fehler und Schwachstellen zum Teil schon kennen und auch ausnutzen. Zusätzlich wird durch die Verheimlichung von gefundenen Schwachstellen nur das falsche Gefühl von vorhandener Security gestärkt. Unterschieden werden muss jedoch auch im Falle einer Veröffentlichung, in welcher Art der Whitehat den Exploit veröffentlicht: Responsible Disclosure Sehr häufig werden dem Hersteller Fristen gesetzt, innerhalb welcher er auf die Meldung des Problems reagieren muss. Google setzt sich zum Beispiel für diese Vorgehensweise stark ein und hilft den betroffenen Unternehmen mitunter auch die Lücken zu schließen. Obwohl das Projekt schon länger am Laufen ist, hat Google es erst im Juli 2014 mit dem Namen 6 „Project Zero“ offiziell vorgestellt. Ziel ist es, das Internet zu einem sichereren Ort zu machen indem Software-Fehler von (speziell dafür angeheuerten) Experten gefunden und veröffentlicht werden. [3] Dabei verfolgt Google den Ansatz, dass der betroffene Hersteller innerhalb von 60 Tagen einen Bugfix beziehungsweise ein Update zur Verfügung stellen muss. Sobald die Frist abgelaufen ist oder der Hersteller das Problem gelöst hat, veröffentlichen die Sicherheitsexperten von Google den Exploit. Sollte die Schwachstelle bereits aktiv ausgenutzt werden, so verkürzt Google die Schonfrist bis zur Veröffentlichung auf 7 Tage. Die Webseite auf der Google Details zu den gefundenen Schwachstellen veröffentlicht, ist unter folgendem Link zu finden: http://googleprojectzero.blogspot.de/ [4], [5], [6] Full Disclosure Als Full Disclosure wird die Praktik bezeichnet, die Analyse von Softwareschwachstellen so früh wie möglich und ohne Einschränkungen der Öffentlichkeit zur Verfügung zu stellen. Der Zweck dahinter ist, dass die möglichen Opfer einer Schwachstelle so bald wie möglich darüber Bescheid wissen, um Gegenmaßnahmen, wie zum Beispiel das Abschalten beziehungsweise Umstellen eines Services oder das Verwenden eines anderen Services, gegen bevorstehende Angriffe ergreifen zu können. Es gibt einige sehr bekannte Vertreter von Full Disclosure, zum Beispiel Bruce Schneier, die darauf verweisen, dass „Security by Obscurity“ noch nie der richtige Weg für bessere Security war. Und obwohl Google ein Vertreter von Responsible Disclosure ist, kann man bei ihrer 7 Tage Schonfrist bei Gefahr in Verzug, eigentlich von Full Disclosure sprechen. Weiters haben sich auch schon diverse Experten aus dem Hause Google den ein oder anderen Full Disclosure erlaubt (siehe [4]). Die Veröffentlichungen von Vulnerabilities und Exploits werden meist in den Blogs der Sicherheitsexperten als auch unter anderem auf folgenden Webseiten durchgeführt: http://www.securityfocus.com/, http://seclists.org/fulldisclosure, https://cve.mitre.org/, http://www.cvedetails.com/ Bug-Bounty Bug-Bounty-Programme sind Aufforderungen von Softwareentwicklern (meist Webapplikationen) an die Community gefundene Bugs und Schwachstellen im System zu melden. Im Gegenzug dafür erhält der Finder Anerkennung und eine kleine Aufwandsentschädigung. Kann die Schwachstelle für einen Exploit benutzt werden, so fällt der Finderlohn natürlich entsprechend höher aus. Die Applikationsentwickler können so die Community dazu verwenden Probleme zu erkennen und dann in weiterer Folge diese frühzeitig beheben, bevor jemand sie für böswillige Zwecke verwendet. Zu bekannten Vertretern von Bug Bounty Programmen zählen Facebook, Yahoo! und Google. Inzwischen gibt es auch schon Webseiten, die zwischen den Unternehmen und Researchern als 7 Vermittlungsstelle dienen (z.B. https://hackerone.com/, https://bugcrowd.com/). Auf diesen Webseiten hat man auch einen guten Einblick wie viele Software-Bugs gefunden werden und wie schnell die Unternehmen auf gemeldete Fehler und Schwachstellen reagieren. Sicherheitsfirmen, Malware Hersteller & Bundestrojaner Die wohl lukrativste Möglichkeit für Sicherheitsforscher Geld zu verdienen ist das Geheimhalten der Schwachstelle vor dem Hersteller und der anschließende Verkauf von Exploits an Geheimdienste und andere Organisationen. Hier sind vor allem Exploits für weit verbreitete Programme wie Browser oder PDF-Reader sehr gefragt und können um bis zu 100.000 US-Dollar pro Schwachstelle verkauft werden. So hat zum Beispiel die NSA alleine im Jahr 2013 mehr als 25 Millionen US-Dollar für den Kauf von noch unbekannten Exploits (0-day-Exploits) ausgegeben, obwohl die großen ITUnternehmen wie Microsoft und Apple dem Geheimdienst bestimmte Schwachstellen ohnehin schon vor der Veröffentlichung der Software Updates mit den Bugfixes bekannt geben. [7] Auch das Bundesamt für Sicherheit in der Informationstechnik (BSI) in Deutschland hatte in den Jahren 2011 bis 2014 einen Vertrag mit der französischen Firma Vupen und hat von dieser Berichte über Schwachstellen als auch Exploits bezogen [8]. Doch nicht nur das BSI macht dubiose Geschäfte mit Malware-Herstellern. Auch der deutsche Bundesnachrichtendienst (BND) hat laut dem Nachrichtenmagazin „Der Spiegel“ vor, Zero Day Exploits zu kaufen. Zwischen 2015 und 2020 stehen dem BND 4.5 Millionen Euro dafür zur Verfügung. Ziel ist es „künftig auf Augenhöhe mit führenden westlichen Nachrichtendiensten kooperieren“ zu können. [9] Bekannte Vertreter solcher „Sicherheitsfirmen“ sind zum Beispiel Vupen (Frankreich), Gamma Group (United Kingdom) und FinFisher (Deutschland). Laut Dokumenten von WikiLeaks soll es weltweit an die 100 Unternehmen geben, die sich auf elektronische Überwachung spezialisiert haben und ihre Programme und Know-How an die Höchstbietenden verkaufen. Im April 2013 wurde auf der Website von Citizen Lab ein Report mit dem Namen „For Their Eyes Only: The Commercialization of Digital Spying“ veröffentlicht, in dem eine Analyse der FinFisher Suite zu finden ist. Daraus geht hervor, dass in mehr als 36 Ländern FinFisher Command & Control Server zu finden sind (darunter auch Österreich) und sich die Spyware unter anderem als Mozilla Firefox tarnen kann. [10] Im August und September 2014 haben sowohl Wikileaks als auch ein Hacker auf Twitter geheime Dokumente und Software-Programme von FinFisher veröffentlicht. Dazu gehört auch eine Kundenliste, die unter anderem folgende Kunden aufführt: „Slovakia, Mongolia, Qatar State Security, South Africa, Bahrain, Pakistan, Estonia, Vietnam, Australia NSW Police, Belgium, Nigeria, Netherlands KLPD, PCS Security in Singapore, Bangladesh, Secret Services of Hungary, Italy and Bosnia & Herzegovina Intelligence“.Die Software als auch Dokumente sind unter nachfolgenden Verweisen zum Download verfügbar. [11] [12] [13] [14] 8 Rein rechtlich gesehen liegt dieser gesamte Markt in einer Grauzone, die jedoch sehr stark von den Regierungen und Geheimdiensten gefördert wird. Im Endeffekt geht das Ganze auf die Kosten der Bürger und Unternehmen, denn dadurch, dass die Lücken geheim gehalten werden, können diese natürlich auch von jedem anderen Hacker ausgenutzt werden. Als weitere Gefahr für Unternehmen kommt hinzu, dass die Spionagesoftware natürlich auch an gut zahlende Kundschaft aus der Industrie verkauft wird und daher zur Industriespionage verwendet werden wird. Solche zielgerichteten Angriffe auf die IT-Infrastruktur und geheimen Daten von Unternehmen und Behörden werden als Advanced Persistent Threat (APT) bezeichnet. Ziel sind meist Unternehmen die einen Technologievorsprung gegenüber der Konkurrenz aufweisen. Spätestens seit bekannt werden des Computerwurms Stuxnet ist weltweit bekannt, dass solche Angriffe aber auch zur Sabotage von Industrieanlagen verwendet werden und erheblichen Schaden anrichten können. http://de.wikipedia.org/wiki/Stuxnet Exploits Arten Bis jetzt wurde erklärt was Exploits überhaupt sind, wer sie erstellt, wer sie verwendet, wo man sie findet und wie sie eingesetzt werden. Nun wird es Zeit ein wenig näher auf die verschiedenen Arten von Exploits einzugehen. In der Praxis wird zwischen folgenden Exploits unterschieden: Lokale Exploits – Ein lokaler Exploit versteckt sich hinter einer harmlos aussehenden Datei (z.B. „Angebot.pdf“, „Urlaubsfoto1.jpg“, „Ausarbeitung.docx“) und versucht Sicherheitslücken in dem Programm auszunutzen mit dem die Datei vom Benutzer geöffnet wird (z.B Adobe PDF Reader, Windows Fotoanzeige, MS Word). Der Exploit ist dabei der Code der die Schwachstelle ausnutzt und der Payload ist die Aktion, die durch Ausnutzen der Sicherheitslücke ausgeführt wird, wie zum Beispiel das Starten einer Reverse Shell. Der Angriff kann zum Beispiel über das Senden einer Mail mit Anhang oder eine präparierte Webseite erfolgen. Remote-Exploits – Ein Remote-Exploit nutzt Schwachstellen in Netzwerksoftware aus. Das heißt, es werden bestimmte Datenströme mit einer bestimmten IP-Adresse und Port-Nummer an einen Host oder Server gesendet, was zu einem Fehler in der Netzwerksoftware des Computers führt, die an diesem Port Daten entgegennimmt (zB. SLmail 5.5 Mailserver, Port 110 [POP3], Bufferüberlauf beim PASS Kommando). DoS-Exploits – Denial of Service Exploits überlasten die Anwendung und/oder bringen sie zum Absturz. Es erfolgt jedoch keine Ausführung von Schadcode. SQL-Injection-Exploits – Beziehen sich auf Webanwendungen mit SQL-Datenbank. Es werden Anfragen an die Webanwendung so gestellt, dass von der SQLDatenbank Daten zurückkommen, auf denen normalerweise weder Lese- noch Schreibzugriff bestünde. Nimmt eine Webanwendung beispielsweise in einem 9 Formular Login-Daten entgegen und validiert diese nicht entsprechend, so kann ein Angreifer sich mittels SQL-Injection dennoch erfolgreich einloggen. Zero-Day-Exploits – Als 0-Day wird ein Exploit bezeichnet, der eingesetzt wird bevor es für die ausgenützte Schwachstelle einen Patch als Gegenmaßnahme gibt. Es bleibt den Entwicklern also keine Zeit um die Benutzer der Software vor Angriffen zu schützen. Zero-Day-Exploits werden von Blackhats meist geheim gehalten, damit die Schwachstellen möglichst lange unbemerkt ausgenutzt werden können. Wie weiter oben schon erwähnt, kann diese Art von Exploit dem Finder auch sehr viel Geld einbringen, da insbesondere auch staatliche Einrichtungen bereit sind eine Menge Geld dafür zu investieren. [1] Exploit Beispiel anhand eines Buffer Overflow Sehr oft basieren Exploits darauf, dass ein Computer nicht zwischen Programmcode und Daten unterscheidet (Von-Neumann-Architektur). Bei einem Buffer Overflow wird zum Beispiel vom Angreifer gezielt Code in einen nicht für Code vorgesehenen Speicherbereich geschrieben, um eine Anwendung dadurch manipulieren zu können oder seinen eigenen Code zur Ausführung zu bringen. Das Nachfolgende soll anhand eines sehr einfachen Beispiels zeigen, wie ein Exploit anhand eines Buffer-Überlaufs funktioniert. Programmbeschreibung Das Beispiel (geschrieben in C) soll folgende Funktions-Aufruf-Reihenfolge vorweisen: main() -> receice() -> strcpy() In der main()-Funktion wird die receive()-Funktion aufgerufen. Die receive()-Funktion allokiert Speicher am Stack für zwei Strings (Character-Arrays) mit den Namen var1 und var2, wobei sich ein Fehler eingeschlichen hat und das var1-Array größer sein kann als das var2-Array. Anschließend wird var1 von einer beliebigen anderen Funktion mit Daten gefüllt (zum Beispiel von einem Stream Socket oder einer Benutzereingabe). Nun benötigt das Programm jedoch eine Kopie der Daten in var1 auf var2. Dazu wird die strcpy()-Funktion aufgerufen und beide Arrays werden als Zeiger übergeben. Danach werden die Daten in irgendeiner Form von der receive()-Funktion weiterverarbeitet. Das Problem Für jede der 3 aufgerufenen Funktionen (main, receive und strcpy) wird am Stack ein eigenes Stackframe angelegt. Jedes dieser Stackframes enthält die Übergabeparameter, die Rücksprungadresse und den vorherigen Framepointer. Das erste Bild zeigt den Stack unter der Annahme, dass das var1-Array folgende Daten enthält: „AAAAAAAAAAA…AAAABBBBDDDDEEEEEEEE…..EEEE“, wie er aussieht wenn das Programm gerade mitten in der strcpy() – Funktion ist, und anfängt die Zeichen von var1 10 auf var2 zu kopieren (in der Abbildung wurden erst 8 Bytes kopiert). Da der Buffer, auf den kopiert werden soll, die lokale Variable var2 der receive()-Funktion ist und der strcpy()Funktion nur die Anfangsadresse des char-Arrays übergeben wird, schreibt die strcpy()Funktion die Zeichen direkt in den dafür reservierten Bereich im Stackframe der receive()Funktion. 1 2 Abbildung 1: Darstellung eines Buffer Overflow 3 Der zweite Schritt zeigt den Stack und die Registerwerte im Moment in dem die strcpy()-Funktion gerade verlassen wird. Am Stack sind bereits die abgelegten Werte des Stackframes der receive()-Funktion und der main()-Funktion überschrieben. Das heißt, dass die strcpy()-Funktion zwar normal returned, jedoch in der receive()-Funktion schon mit falschen Stackwerte gerechnet wird, falls nach dem strcpy()-Funktionsaufruf noch Operationen mit lokalen Variablen der receive()-Funktion durchgeführt werden. Im dritten Bild, also beim Verlassen der receive()-Funktion, kommt es dann zum Programmabbruch, da beim Verlassen mit ret, nicht die ursprünglich abgelegte Rücksprungadresse in den EIP geladen wird, sondern die Adresse 0xBBBB, auf die das Programm keinen Zugriff hat. In diesem Beispiel wird auf die Rücksprungadresse nur der Wert 0xBBBB geschrieben. Ein Exploit-Entwickler würde stattdessen eine gültige Sprungadresse an dieser Stelle platzieren. 11 So könnte er sich zum Beispiel aus einer Windows-DLL die Adresse eines ‚JMP ESP‘ (= Springe zum Stackpointer) Befehls heraussuchen und auf diese Adresse verweisen. Anstatt des Rücksprungs in die main()-Funktion würde dann nach der receive()-Funktion ein Sprung in die Windows-DLL erfolgen und der Befehl ‚JMP ESP‘ ausgeführt werden. Dies führt dazu, dass der nächste Befehl der ins Instruktionsregister (EIP) geladen wird, von der Stelle im Speicher genommen wird, auf die der ESP zeigt. In diesem Beispiel wäre dies der Wert 0xDDDD (siehe Schritt in der Abbildung 3). Steht an dieser Stelle nun nicht 0xDDDD, sondern ein gültiger CPU-Befehl, so wird dieser von der CPU interpretiert und ausgeführt. Nach der Ausführung des Befehls wird dann der EIP um eine Adresse erhöht und würde den nächste Befehl vom Stack ausführen (hier: 0xEEEE), usw. Das heißt, in einem richtigen Exploit würde also anstatt 0xDDDD, gefolgt von mehreren 0xEEEE, der Payload (Shellcode) am Stack stehen, der somit von der CPU ausgeführt wird. Dies ist eine vereinfachte Darstellung, wie ein Exploit einen Stack Overflow ausnutzen kann, um auf einem System dieselben Rechte zu bekommen wie die, die das angegriffene Programm hat. Wird das Programm unter Windows zum Beispiel als Dienstprozess vom Benutzer SYSTEM ausgeführt, so wird auch der Payload mit SYSTEM-Rechten ausgeführt, welche sogar noch eine Ebene über den Administrator-Rechten angesiedelt sind. Hat der ausgenutzte Prozess nur Benutzer-Rechte, so kann der Angreifer in weiterer Folge mit Hilfe von Privilege Escalation versuchen Administrator-Rechte zu erlangen. Damit dieser Beispiel-Exploit so funktionieren kann, wurde zum leichteren Verständnis angenommen, dass beim angegriffenen Programm weder Data Execution Prevention (DEP) noch Address Space Layout Randomization (ASLR) aktiviert wurden, die beide Gegenmaßnahmen für Bufferüberläufe darstellen und diese deutlich erschweren. Wie kann man einen Exploit finden? Im Grunde gibt es drei Wege um an einen Exploit für ein bestimmtes Programm, Betriebssystem oder Webseite zu kommen: Entweder man sucht in den diversen Datenbanken im Internet nach einem bereits bekannten Exploit, oder man findet und schreibt selbst einen neuen Exploit, oder man verwendet ein sogenanntes Exploit Kit. Einen Exploit downloaden Dieser Weg stellt definitiv die einfachere Möglichkeit dar. Wie schon erwähnt stehen auf diversen Webseiten (z.B. http://www.securityfocus.com/, http://seclists.org/fulldisclosure, http://www.exploit-db.com, http://secunia.com, http://1337day.com) sowohl Vulnerabilities als auch Exploits (falls es dazu schon welche gibt) zur Verfügung. Die Suche kann entweder über den Hersteller, das Produkt oder die CVE Nummer (Common Vulnerabilities and Exposures) durchgeführt werden. CVE ist dabei ein Standard für eine einheitliche Namenskonvention für Sicherheitslücken und Schwachstellen in Computersystemen. Dadurch wird die Mehrfachbenennung von verschiedenen Unternehmen für gleiche 12 Schwachstellen ausgeschlossen und es ist ein reibungsloser Informationsaustausch zwischen verschiedenen Datenbanken möglich. Die Verwaltung der CVE übernimmt die MITRE Cooperation in Zusammenarbeit mit Behörden, Sicherheitsunternehmen, Experten und Bildungseinrichtungen. Hat man erst einmal einen Exploit für das entsprechende Programm gefunden, so sind meist noch kleine Anpassungen notwendig, damit der Exploit auch von einem selbst verwendet werden kann. So muss man den Shellcode (also den Payload), sowie die IP-Adressen (des Ziels und seine eigene) anpassen und eventuell noch ein paar weitere Kleinigkeiten, damit man den Payload am Zielsystem zum Laufen bekommt. Die Anpassungsnotwendigkeit kommt natürlich daher, dass die zur Verfügung gestellten Exploits meist nur zum Proof of Concept dienen und nicht die Einladung zur Begehung von Straftaten sein sollen. Ein Hauptproblem ist, dass wenn ein Exploit einen Buffer Overflow ausnutzt (meistens der Fall), der Exploit-Entwickler mit Sprungadressen arbeiten muss um seinen im Datenspeicher (Stack oder Heap) abgelegten Payload zur Ausführung bringen zu können. Ändert sich nun aber das Zielsystem ein wenig (z.B. andere Windows-Version, andere Sprache, …) so ändern sich auch sehr wahrscheinlich die Speicheradressen (auf ASLR soll an dieser Stelle gar nicht eingegangen werden) und schon funktioniert der Code am Zielsystem nicht mehr. Als Folge muss für jede Plattform auf der das anfällige Programm läuft, aufs Neue der Exploit angepasst und getestet werden. An dieser Stelle sei schon einmal das Metasploit Framework erwähnt. Dieses Framework erleichtert dem Exploit-Entwickler und -Verwender das Handwerk gehörig. Es ist in erster Linie eine Sammlung von Exploits, die aber zwischen dem eigentlichen Code für den Angriff (dem Exploit) der speziell für eine Sicherheitslücke geschrieben wurde und dem Shellcode (also dem Payload) der dann nach dem Ausnutzen der Sicherheitslücke zur Ausführung kommt. Aktuell enthält das Framework in der Version 4.11 an die 1400 Exploits und 350 Payloads die frei zur Verfügung stehen. All diese Exploits und Payloads aus der Metasploit-Datenbank kann man mit wenigen Befehlen konfigurieren und direkt an ein angegebenes Ziel senden. Und will man einen ganz neuen Exploit aus einer der zuvor erwähnten Datenbanken verwenden, kann man dies gleich mit Hilfe des Metasploit Framesworks machen und braucht sich nicht einmal um den Payload kümmern. Zusätzlich kann der neu erstellte Exploit auch den Rest der Community zur Verfügung gestellt werden. Einen neuen Exploit erstellen Um einen neuen und gänzlich unbekannten Exploit zu finden und zu erstellen wird wesentlich mehr Know-How und Aufwand benötigt, als bei der einfachen Verwendung eines bereits existierenden Exploits. Dennoch lohnt sich der Aufwand für einen Hacker sehr oft, da er im Endeffekt einen ZeroDay-Exploit erstellt, sollte er eine zuvor unbekannte Schwachstelle entdecken. Und wie schon erwähnt wurde, kann ein Zero-Day-Exploit einiges wert sein, vor allem wenn er in einer sehr häufig installierten Desktop-Anwendung gefunden wird. 13 Wie ein Exploit im Detail erstellt wird und auf dessen detaillierte Funktionsweise können die Autoren in dieser Arbeit leider nicht eingehen, da Exploits einerseits nicht das primäre Thema der Arbeit darstellten und andererseits der Umfang einer genauen Beschreibung über die Erstellung von Exploits ein ganzes Buch füllen würde. Deshalb sei an dieser Stelle der Vollständigkeit halber an frei verfügbare Literatur zu diesem Thema verwiesen: [15], [16], [17]. Obwohl die Verwendung von bereits vorhandenen Exploits sicher die einfachere Methode ist um einen Exploit einzusetzen, hat sie einen entscheidenden Nachteil gegenüber einem selbst erstellten Exploit: der Exploit ist bereits bekannt und es gibt höchstwahrscheinlich schon Updates des Herstellers dagegen. Das heißt, besonders bei Servern wird man geringe Chancen haben, auf einen nicht gepatchten zu stoßen. Bei normalen Client-PCs sieht es da schon ein wenig besser aus, da nicht alle Benutzer ihre Applikationen immer up-to-date halten. Auch veraltete Betriebssysteme wie Windows XP, die wesentlich weniger Schutzmechanismen als neue Systeme aufweisen, sind noch weit verbreitet und spielen dem Angreifer natürlich in die Hände. Zusammenfassung Exploits stellen eine sehr gute Möglichkeit dar um unbemerkt von Benutzer und Antivirussoftware in ein System einzudringen und dieses zu übernehmen. Dazu werden Fehler und Schwachstellen in Programmen ausgenutzt die auf dem angegriffenen Host installiert sind. Der Vorteil von Exploits liegt darin, dass das Opfer nicht irgendeine ausführbare Datei (zB. exe, jar oder Batch-Datei) auf seinen System öffnen muss, damit die Malware ihn infizieren kann, sondern es kann lediglich ein unscheinbar wirkender EmailAnhang, wie zum Beispiel eine modifizierte Excel-, Word-, Pdf- oder Bilddatei geöffnet werden um das System zu infizieren. Noch einfacher geht es, wenn der Webbrowser oder eines der darin verwendeten Plugins (zB. Flash-Player, Java) eine Schwachstelle haben. Dann genügt ein sogenannter Drive-By-Download um das System wiederum unbemerkt zu infizieren, während der Benutzer auf einer unscheinbaren Webseite surft. Um direkt auf einen Web-Server zu gelangen sind Exploits ohnehin fast die einzige Möglichkeit, da es am Server meist keine unvorsichtigen Benutzer gibt, die einfach so mit Malware befallene ausführbare Dateien öffnen. Hier werden meist direkt Netzwerkprogramme angegriffen oder es wird sich Zugang über Code-Injection in den Web-Applikationen verschafft. Aus diesen Gründen machen heutzutage laut einer Studie vom Unternehmen Malwarebytes, Exploit-basierte Angriffe mehr als 90% der Gefahren aus, die auf die Benutzer von Computersystemen zukommen. [18] Gegenmaßnahmen gegen solche Angriffe sind zum einen regelmäßige Softwareupdates und zum anderen gibt es Programme wie Microsoft EMET und Malwarebytes ANTI-EXPLOIT, die einen zusätzlichen Schutz mit verschiedenen Techniken wie Data Execution Prevetion 14 (DEP), SEHOP (Structured Exception Handler Overwrite Protection) und ASLR (Address Space Layout Randomization) versprechen. Diese werden im Kapitel Gegenmaßnahmen genauer behandelt. Zur Vollständigkeit sei hier noch erwähnt, dass nicht alle Exploits dazu genutzt werden um unbefugt in ein System einzudringen. Auch das Jailbreaking (zum Beispiel eines Apple Smartphones) wird mit Hilfe von Exploits durchgeführt. Das Ziel dabei ist es jedoch, einen Nutzen für den Smartphone-Besitzer zu generieren, da zusätzliche (gesperrte) Funktionen dadurch freigeschaltet werden können. 2.2 Code Obfuscation Code Obfuscation (engl. „Verschleierung“) bezieht sich auf die Transformation von Programmcode. Ziel ist es, die Ermittlung der Semantik und der Funktionalität eines Programms zu erschweren, jedoch dessen Funktionalität zu erhalten. Dabei kann die Verschleierung auf die Verwirrung von Maschine als auch Mensch abzielen. Prinzipiell kann Obfuscation auf zwei Bestandteile eines Programms angewandt werden: Kontrollfluss Auf den chronologischen und kausalen Ablauf des Programms (Sprungpunkte, Verzweigungen, Ausführungsreihenfolge der Anweisungen). Datenstrukturen Die Umkehr von Obfuscation wird als Code De-Obfuscation bezeichnet. Je höher der Aufwand für die De-Obfuscation ist, desto besser ist die Güte der Obfuscation. Dieses Kapitel gibt einen Überblick über die verschiedensten Obfuscation-Techniken und erklärt kurz wie diese funktionieren. 2.2.1 Obfuscator Ein Obfuscator (Deutsch: Quelltextverschleierer) dient dazu, wie der Name schon sagt, den Quelltext oder Maschinencode von Programmen zu verschleiern. Meist verfolgt die Verschleierung das Ziel ein Programm vor Reverse Engineering oder Manipulation zu schützen. Dies wird dadurch erreicht, dass der gut lesbare, kommentierte und nachvollziehbare Source Code von Obfuscatoren so verändert wird, dass er für Menschen nur mehr sehr schwer und mit großem Aufwand lesbar ist. Dabei ist es jedoch wichtig, dass nach der Verschleierung der Code einerseits noch dieselbe Funktionalität wie der Originaltext hat und andererseits auch noch gleich schnell beziehungsweise nur unwesentlich langsamer als der ursprüngliche Code ausgeführt werden kann. Je nach verwendeter Technik erzeugt der Verschleierungsvorgang längeren oder kürzeren Source Code und führt daher zu mehr oder weniger Speicherverbrauch. Zum Beispiel können 15 Variablen entweder durch viel längere, zufällige Zeichenfolgen ersetzt werden, oder auch durch ganz kurze Zeichenfolgen. Nachfolgend sind einige Beispiele für Methoden von Code Obfuscation aufgelistet: Verwenden von äquivalenten Formeln und konstante Transformationen Anstatt zu einem Register die Zahl 10 zu addieren, wird die Operation in zwei Schritte aufgeteilt und zuerst die Zahl 15 addiert um danach wiederum 5 zu subtrahieren. Umordnen von Anweisungen Verändern der Reihenfolge von Anweisungen ohne das Programm selbst zu beeinflussen. Zum Beispiel können die Übergabeparameter bei Funktionen oft in willkürlicher Reihenfolge angegeben werden. Variablensubstitution (Symbol Renaming) Umbenennen von Bezeichnern (Variablen, Funktionen, Methoden, Klassen, …). So kann zum Beispiel nachfolgende Variablendeklaration wie folgt verändert werden: var Postleitzahl; var lasjfkasjfuewfkjas; (Mehr Speicherverbrauch) var a; (Weniger Speicherverbrauch) Wie weiter unten noch gezeigt wird, ist eine gute Variante davon, so viele Bezeichner wie möglich mit demselben Namen zu versehen. Entfernen von Einrückungen und Zeilenumbrüchen function NewObject(prefix) { if(prefix === “test”){ alert(„This is a test!“); }else{ alert(“This is not a test!”); } } ↓ function NewObject(prefix){if(prefix === “test”){alert(„This is a test!“);}else{alert(“This is not a test!”);}} Bedingte Anweisungen und Sprünge Zum Beispiel Vergleiche und Bedingungen, die stets ‚true‘ beziehungsweise ‚false‘ ergeben, Links oder Pointer. Spaghetti Code (Control Flow Obfuscation) Die Control Flow Obfuscation hat das Ziel, das Programm so umzustrukturieren, dass es unmöglich wird daraus gut geformten Source Code zu dekompilieren. Das führt wiederum dazu, dass für den Menschen das Programm viel schwieriger zu verstehen ist. Die meisten Obfuscatoren bewerkstelligen dies, indem zum Beispiel anstatt Funktionsaufrufen, Returns, Schleifen und Abfragen immer gotos verwendet werden. 16 Aufruf von Subroutinen Im Prinzip kann jede einzelne Anweisung auch durch eine Subroutine (Funktion) ersetzt werden. Einfügen von Leercode Zwischen den eigentlichen Anweisungen wird überflüssiger Code eingefügt. Dieser trägt nichts zur eigentlichen Funktionalität des Programms bei und führt lediglich triviale und irrelevante Berechnungen durch. Verschlüsselung (Ressource/String/Assembly Encryption) Verschlüsselung wird zur Tarnung von einzelnen Bytes oder Strings eingesetzt, welche zum Beispiel hardcodiert im Code abgelegt sind. (zB: Passwörter). Mischen von Funktionen Alternierende Schreibweise der Anweisungen zweier Funktionen um die Grenzen zwischen den Funktionen verschwimmen zu lassen. Spalten von Variablen Umstrukturierung von Arrays ein eindimensionales Array Aufspaltung in mehrere eindimensionale Arrays ein eindimensionales Array Ausweitung in ein mehrdimensionales Array ein mehrdimensionales Array Schrumpfen in ein eindimensionales Array zwei oder mehrere eindimensionale Arrays Zusammenführung zu einem eindimensionalen Array Anti-Debugs Spezielle Routinen welche eine Ausführung durch einen Debugger erkennen und das Programm daraufhin frühzeitig beenden. Dazu wird beispielsweise der Speicher nach Suchstrings diverser Debugger gescannt. Anti Decompiler/Disassembler Verändern des kompilierten Codes, sodass dieser von bestimmten Decompilern oder Disassemblern nicht verarbeitet werden kann. [19], [20], [21] 2.2.2 Obfuscation in verschiedenen Programmiersprachen Interpretiert vs. kompiliert Es gibt verschiedene Möglichkeiten um aus Quelltext ein auf der CPU ausführbares Programm zu erstellen. Bevor Programmiersprachen wie Java und C# bekannt wurden, gab es im Endeffekt 2 Möglichkeiten: Den Quellcode zu kompilieren oder zu interpretieren. So werden Sprachen wie C, C++, Fortran und Pascal fast immer direkt in Maschinencode kompiliert, während der Quellcode von Sprachen wie Basic, VBScript, JavaScript, Perl, PHP, 17 Ruby und Python normalerweise von einem sogenannten Interpreter interpretiert werden. Ganz grundsätzlich ist eine Programmiersprache nicht an eine Implementierung und damit Art der Ausführung gebunden. Für mehrere Sprachen existieren daher verschiedenartige Implementierungen. Zum Beispiel ist die Sprache C zwar stark auf eine Kompilierung ausgelegt, jedoch existieren auch C-Interpreter wie CINT und Ch. [22] Nachfolgend werden kurz die Methoden wie aus Quelltext ein Prozess entsteht und deren Unterschiede zueinander vorgestellt: Compiler (1) Schreiben/Bearbeiten des Quelltextes (2) Kompilieren der Quelltext-Dateien in Maschinencode-Dateien (3) Verknüpfen der Maschinencode-Dateien mittels dem Linker in eine ausführbare Datei (zB: .exe, elf-File) (4) Ausführen oder debuggen der ausführbaren Datei Prozess Maschinencode-Dateien enthalten Instruktionen die direkt von der CPU verstanden werden können. Daher müssen sie für jeden Prozessor, der einen anderen Instruktionssatz besitzt, extra mit einem für diesen Prozessor passenden Compiler kompiliert werden. Der Grund dafür, dass es meist pro Quelltextdatei eine Maschinencode-Datei gibt und dadurch viele Maschinencode-Dateien erst zu einer gemeinsamen ausführbaren Datei gelinkt werden müssen, ist die Effizienz: Dadurch müssen bei jeder Änderung nur die geänderten Quellcodedateien neu kompiliert werden und die nicht geänderten Module können einfach erneut genutzt werden. Dieses Vorgehen wird auch als „Make“ bezeichnet, während das Kompilieren des gesamten Source Codes als „Build“ oder „Rebuild“ bezeichnet wird. Der Linkvorgang selbst ist dabei ein technisch sehr komplexer Prozess bei dem die Funktionsaufrufe zwischen den verschiedenen Maschinencode-Dateien aufgelöst werden, die Speicherpositionen für die Variablen zugewiesen werden und der gesamte Code schließlich in den Speicher als fertiges Programm abgelegt wird. [23] Interpreter (1) Schreiben/Bearbeiten des Quelltextes (2) Ausführen oder Debuggen der Quelltext-Datei Diese Vorgehensweise führt natürlich sehr viel schneller zu einer Programmausführung nachdem der Programmierer Änderungen am Souce Code vorgenommen hat, da vor der Ausführung der Code nicht kompiliert und gelinkt werden muss. Natürlich führt das wiederum zum Nachteil, dass die Programmausführung selbst 5 bis 10 mal langsamer erfolgt, da bei jeder Programmausführung zur Laufzeit jede Quelltextzeile zuerst vom Interpreter gelesen, interpretiert, analysiert und ausgeführt werden muss. [23] 18 Just in Time Compiler Ein Kompromiss zwischen reiner Kompilierung und Interpretierung sind sogenannte Just in Time Compiler (JIT). Dabei wird das Programm, wie beim Interpreter, erst zur Laufzeit übersetzt, dafür aber gleich wie beim Compiler direkt in Maschinensprache. Der bereits kompilierte Maschinencode wird dabei während der Programmausführung zwischengespeichert, wodurch mehrfach aufgerufene Programmteile nur einmal übersetzt werden müssen. Weiters ist eine bessere Optimierung des Programmes möglich, als bei einem reinen Interpreter. Ein Nachteil der Kompilierung ist jedoch, dass JIT-Compiler gleich wie normale Compiler für jede Rechnerarchitektur eigens implementiert werden müssen. Bytecode Interpreter Bei einem Bytecode Interpreter wird der Quelltext schon vorab in einen einfacheren Zwischencode (Bytecode, Intermediate Language) übersetzt, um dann schneller von einem Interpreter (= Process Virtual Machine) ausgeführt werden zu können. Die Intermediate Language ist dabei unabhängig von der zugrunde liegenden Hardware auf der das Programm ausgeführt wird. Dadurch können Programme sehr leicht zwischen verschiedenen Prozessorarchitekturen portiert werden, solange es einen Interpreter für diese Architektur gibt. Meist werden Bytecode Interpreter zusammen mit Just in Time Kompilierung eingesetzt, um die Ausführungsgeschwindigkeit zu erhöhen. Bekannte Beispiele für Process Virtual Machines sind die Java Virtual Machine (JVM) und die Common Language Runtime (CLR), auf welcher das .NET Framework aufbaut. Das heißt also, dass Programmiersprachen wie Java und C# beide einen Bytecode Interpreter als auch einen Just in Time Compiler für die Ausführung von Programmen verwenden und daher der Quellcode in einen zweistufigen Prozess übersetzt wird. Dadurch dass sowohl Java als auch C# verschiedene Techniken zur Steigerung der Ausführungsgeschwindigkeit anwenden, werden die Programme beider Abbildung 2: Common Language Infrastructure (CLI) [27] Programmiersprachen beinahe mit derselben Geschwindigkeit ausgeführt wie Programme in rein kompilierten Sprachen [22]. 19 Compiled Languages (C, C++, Objective-C, Fortran, …) Native kompilierte Sprachen wie C und C++, bei denen der Compiler aus dem Source Code direkt Maschinensprache erzeugt, sind per Default nur sehr schwierig bis gar nicht vernünftig zu dekompilieren (von Maschinen-,/Objectcode in Hochsprachen Source Code). Im Gegensatz dazu ist das Disassemblieren, bei dem binäre Maschinenbefehle, in für Menschen lesbaren Assembler Code umgewandelt wird, meist keine große Herausforderung und wird sogar von den meisten Debuggern, wie zum Beispiel GCC, zur Verfügung gestellt. Aus diesem Grund verwenden Code-Analysten meist Assemblercode um ein Reverse Engineering zu betreiben. Dadurch, dass Assembler-Programme um einiges schwieriger zu lesen sind und sowohl Bezeichner als auch Kommentare im generierten Assemblercode fehlen, stellt sich das Reverse Engineering bei solchen Programmen als sehr zeitaufwändig heraus. Aufgrund des aufwändigen Reverse Engineerings besteht häufig kein Bedarf gesonderte Maßnahmen wie Obfuscation zu treffen, um das Reverse Engineering von Programmen zu verhindern. Nur bei Kopierschutz- oder Lizenzmechanismen findet man oft Obfuscation Maßnahmen (siehe zum Beispiel StarForce) wie Verschlüsselung, damit es schwieriger wird diese zu umgehen. Prinzipiell ist bei kompilierten Sprachen zu unterscheiden, zu welchem Zweck und zu welchem Zeitpunkt die Obfuscation – Techniken verwendet werden: Source Code Obfuscation – Verschleiern des eigentlichen Hochsprachen Programm Codes. Diese Technik kann bei kompilierten Sprachen sehr hilfreich sein, wenn der Software Quellcode an andere (Unternehmen) weitergegeben werden muss, diese jedoch nicht nachvollziehen können sollen, was der Code genau macht, beziehungsweise die Gefahr besteht, dass geistiges Eigentum gestohlen werden könnte. Dies kann zum Beispiel bei Cross-Plattform-Software der Fall sein, da es in solchen Fällen sinnvoll ist, dass der Kunde den Build auf seinen Plattformen selbst durchführt. Wie weiter unten noch ersichtlich ist, ist die Source Code Obfuscation für Sprachen die in Bytecode übersetzt werden, die einzige Möglichkeit ihr Verhalten zu verschleiern. Ein Obfuscated C-Source Code kann zum Beispiel wie in Abbildung 3 und Abbildung 4 aussehen. Der abgebildete C-Code wurde mit dem Tool Stunnix C++ Obfuscator [24] verschleiert, welches von Unternehmen wie DELL, Siemens, Bosch, Broadcom, NEC, usw. verwendet wird. Weiter Beispiele für C/C++ Obfuscatoren wären der StarForce C++ Obfuscator und der Mangle-It C++ Obfuscator. Alle drei angeführten Tools sind kommerzielle Produkte. Da die Obfuscation von C/C++ Quellcode nur das Layout des Source Codes verändert, jedoch kaum Auswirkungen auf den Output vom Compiler hat (Maschinencode von Abbildung 3 und Abbildung 4 ist derselbe), machen Source Code Obfuscatoren nur im kommerziellen Bereich Sinn. Daher scheint es auch keine Open Source Projekte in diese Richtung zu geben. 20 Abbildung 3: Einfaches C++ Beispiel mit einer globalen Variable und zwei Funktionen, die auf diese globale Variable zugreifen [24] Abbildung 4: Verschleierter C++ Code. Alle Symbole wurden durch MD5 Hashes ersetzt; Kommentare, Zeilenumbrüche und Einrückungen wurden entfernt; Literale wurden kodiert [24] Es gibt jährlich den sogenannten „International Obfuscated C Contest“, bei dem die besten von Hand kodierten, verschleierten C Programme gesucht werden. Die überaus interessanten Programme können in [25] bewundert werden. Binary Obfuscation after Compilation – Verschleiern der Programmfunktion nachdem das Programm kompiliert wurde. Diese Technik hat den Vorteil, dass man direkt mit dem Binary arbeiten kann und sich alle Änderungen direkt auswirken. Der Compiler kann also nicht zusätzlich (redundant) eingefügte oder veränderte Codeteile wieder entfernen. Im Gegensatz zur Source Code Obfuscation wird bei dieser Technik versucht den Maschinencode zu verschleiern. Der Nachteil dabei ist, dass dazu meist Tools von anderen Herstellern verwendet werden müssen, da in-house das Know-How dazu fehlt. Dabei ist dann jedoch wiederum unbekannt, wie diese zugekauften Obfuscatoren genau funktionieren und ob diese nicht durch Fehler zu ungewünschten Nebenwirkungen führen. Bei frei verfügbaren Obfuscatoren besteht zusätzlich die Gefahr, dass nicht nur Verschleierung des eigenen Codes betrieben wird, sondern zusätzlich auch noch gleich ein Trojaner in die eigene Software mitreingepackt wird. 21 Beispiele für einen „Obfuscator after Compilation“ ist das Open Source Programm Obfuscator-LLVM (https://github.com/obfuscator-llvm/obfuscator/wiki), welcher auf der LLVM Compiler Suite aufsetzt. Andere Beispiele sind sogenannte Runtime Packer, auf die in diesem Kapitel noch näher eingegangen wird. Binary Obfuscation from the Top Down – Dieser Ansatz verfolgt schon bei der Programmierung das Ziel den Hochsprachencode so zu schreiben, dass der Compiler beinahe unlesbaren Code erzeugt. Der Vorteil dabei ist, dass es für den Programmierer leichter nachvollziehbar wird, wie der Code verschleiert wird und dass immer andere Methoden verwendet werden können. Das Problem dabei ist, dass es passieren kann, dass der Compiler den extra eingefügten Verschleierungscode einfach wegoptimiert. Denn standardmäßig wird vom Compiler zum Beispiel Code optimiert, der o nicht durchlaufen wird (z.B. Verzweigungen), MOV XOR CMP JNE EAX,949 EAX,310 EAX,0 z0r z0r: XOR EAX,310 PUSH EAX o MOV EAX,949 XOR EAX,310 XOR EAX,310 PUSH EAX XOR EAX,949 LEAVE RETN MOV EAX,949 PUSH EAX der sich gegenseitig aufhebt XOR EAX,310 XOR EAX,310 o dessen Berechnungen nicht mehr weiter gebraucht werden MOV EAX,949 MOV EBX,310 MOV ECX,213 XOR EAX,EBX ADD EBX,EAX SUB EAX,EAX PUSH EBX PUSH EAX MOV EAX,949 MOV EBX,310 XOR EAX,EBX ADD EBX,EAX SUB EAX,EAX PUSH EBX PUSH EAX 22 o welcher aus mehrere Berechnungen hintereinander mit derselben Variable besteht int x; x = 7; x <<= 2; x *= 2; x -= 12; x +=(x*x)<< 2; printf("%d\n",x); PUSH 1E6C PUSH “%d\n” CALL $PRINTFSUB Umgangen kann die Wegoptimierung des Compilers zum Beispiel im C, C++ und C# mithilfe des Schlüsselwortes volatile. Wird dieses Schlüsselwort vor Variablen verwendet, so darf der Compiler Berechnungen mit dieser Variable nicht optimieren. Hier also noch einmal das Beispiel von oberhalb: volatile int x; x = 7; x <<= 2; x *= 2; x -= 12; x +=(x*x)<< 2; printf("%d\n",x); MOV [ESP],7 SHL [ESP],2 MOV EAX,[ESP] ADD EAX,EAX MOV [ESP],EAX ADD [ESP],-0C MOV ECX,[ESP] MOV EDX,[ESP] MOV EAX,[ESP] IMUL ECX,EDX ... Die Berechnungen der volatile Variable x werden also nicht optimiert, was zu redundanten Code im Assembly führt. Ein ähnliches Ergebnis liefert der Compiler bei der Verwendung von Zufallszahlen. Da er diese zur Compile-Time nicht vorhersagen kann, ist es dem Compiler auch nicht möglich Code-Abschnitte, die mit Zufallszahlen zu tun haben, zu vereinfachen. Dazu folgendes Beispiel: int a=7, b=2, c=8, d=9; if(a+b+c*d > 0) { puts(“yes”); exit(0); } puts(“no”); PUSH CALL PUSH CALL “yes” $PUTS 0 $EXIT 23 int a,b,c,d; srand(time(0)); a=rand()+1;b=rand()+1; c=rand()+1;d=rand()+1; if(a+b+c*d > 0) { puts(“yes”); exit(0); } puts(“no”); ... TEST EAX,EAX JLE SHORT :NO PUSH “yes” CALL $PUTS PUSH 0 CALL $EXIT NO: PUSH “no” CALL $PUTS Auch durch diese Technik kann das Assembly mit vielen zusätzlichen Berechnungen erweitert und unnötig kompliziert gemacht werden. Eine weitere gute Methode es dem Reverse Engineer schwer zu machen ist das absichtliche Triggern einer Exception und anschließend mit der Programmausführung in der abgefangenen Exception weiterzumachen: try{ volatile int trigger = 20; doThisAndThat(); /* trigger divide-by-zero exception */ trigger=trigger/(trigger-trigger); neverExecutes(); } catch(...) { proceedWithExecution(); } Eine weitere Technik namens „Control Flow Flattening“ bezieht sich auf die grafische Repräsentation eines Programmablaufs in einem Programmgraphen (wie es zum Beispiel der Disassembler IDAPro bietet). Normalerweise ist in so einem Graphen ein Top-Down-Ablauf, mit der Main-Funktion int x=2; als Einstiegspunkt, zu erkennen. Das sw: „Flattening“ zielt jedoch darauf ab, die switch(x) { einzelnen Funktionen bzw. Codecase 0: doThat(); Abschnitte „auszuwalzen“ und die x = 1; gesamte Funktionalität von zentraler goto sw; Stelle aus zu steuern anstelle eines Topcase 1: doMore(); Down-Ablaufs. Dazu kann unter break; anderem die Switch-Case-Anweisung case 2: doThis(); verwendet werden um die x = 0; goto sw; } 24 verschiedenen Funktionen aufzurufen (siehe rechts). Das Ergebnis des Flattenings zeigen die nächsten beiden Abbildungen: Abbildung 5: Control Flow Flattening Schema (übernommen aus [26]) Abbildung 6: Control Flow Flattening in Aktion (übernommen aus [26]) Die hier vorgestellten Methoden: volatile Variablen, Zufallszahlen, Programmausführung in Exceptions und Flattening sind alles Methoden um den 25 Programmablauf zu verändern, mit dem Ziel diesen vor dem Reverse Engineer zu verschleiern (Control Flow Obfuscation). Doch nicht nur der Ablauf selbst, sondern auch die Programmdaten können vor dem Kompilieren der Anwendung verschleiert werden (Data Obfuscation). Um die Daten (wie Strings volatile int x; und Literale) dann zur Laufzeit verwenden zu können, x = 7; müssen diese auch zur Laufzeit wieder „entschleiert“ x <<= 2; werden. Eine der beliebtesten Data Obfuscation x *= 2; Techniken ist die Verschlüsselung, aber es gibt x -= 12; natürlich auch noch andere Möglichkeiten. Eine davon x +=(x*x)<< 2; ist das schon gezeigte volatile Beispiel (siehe rechts), printf("%d\n",x); bei dem der Wert der Variable x verschleiert wird. Daten können in weiterer Folge auch aggregiert werden. Hier ein Beispiel: char aggr[7] = “fboaor”; char foo[3], bar[3]; int i; for (i=0; i<3; ++i) { foo[i] = aggr[i*2]; bar[i] = aggr[i*2+1]; } /* foo = “foo” / bar = “bar” */ Externe Bibliotheksaufrufe für API-Funktionen wie printf() oder execv() werden in einem Assembly in einer speziell dafür vorgesehenen Tabelle gespeichert (Windows: Import Address Table (IAT), Linux: Procedure Linkage Table (PLT)). Diese externen Bibliotheksaufrufe verraten einiges über den Funktionsumfang eines Programmes und werden daher bei einer sogenannten „Dead Code Analysis“, also einer Analyse des Programms ohne das dieses ausgeführt wird, meist automatisch analysiert und ausgewertet (Beispiel: VirusTotal.com). Um eine solche Analyse der Bibliotheksaufrufe zu verhindern, kann der Programmierer dafür sorgen, dass diese nicht in der PLT/IAT eingetragen werden, sondern erst zur Laufzeit dynamisch geladen werden. Dafür gibt es die System Calls LoadLibrary() & GetProcAddress() unter Windows und dlopen() & dlsym() unter Linux. Nachfolgend der Beispielcode für Windows: 26 #include #include #include #include <stdio.h> <stdlib.h> <string.h> <windows.h> typedef int(*PUTS_T)(const char *); int main (int argc, char *argv[]){ /* MSVCR90 will already be loaded, so this is simply for example */ PUTS_T putsFunc = (PUTS_T)GetProcAddress(LoadLibrary(L"MSVCR90.DLL"),"puts"); putsFunc("mysterious!"); return 0; } Mit Hilfe von LoadLibrary() wird die MSVCR90.DLL in den Adressbereich des aktuellen Prozesses geladen und der Handle auf das Modul als Rückgabewert geliefert. Das Handle auf die DLL und der Funktionsname werden im nächsten Schritt der GetProcAddress() Funktion übergeben, die dann die Adresse der angegebenen Funktion (oder Variablen) zurückliefert. Diese Adresse wird im Funktionszeiger mit dem Namen putsFunc gespeichert und kann nun in weiterer Folge für Aufrufe der Funktion puts verwendet werden. Aus den gezeigten Beispielen geht hervor, dass Data Obfuscation zwar eine wirksame Maßnahme gegen eine „Dead Code Analysis“ darstellt, jedoch die LiveCode-Analyse nur begrenzt erschwert. Das liegt daran, dass zur Laufzeit ja zu einem gewissen Zeitpunkt mit den richtigen Werten gerechnet werden muss bzw. die Strings im Klartext vorliegen müssen. Die meisten hier gezeigten Methoden zur „Binary Obfuscation before Compilation“ wurden von Taylor Sean auf der Defcon 17 im Jahre 2009 gezeigt [26]. Bytecode Compiled Languages (.NET, Java) Java und .NET Programme sind verglichen mit kompilierten Sprachen sehr einfach zu disassemblen beziehungsweise Reverse Engineering von den ausführbaren (exe, dll, jar, class) Dateien ist sehr einfach. Denn im Gegensatz zu nativen Maschinencode, wie er zum Beispiel beim C-Compiler rausfällt, enthält der Intermediate Bytecode alle ursprünglich verwendeten Bezeichner (zB. Variablen- & Funktionsnamen), sodass ein Decompiler beinahe den exakten Source Code wiederherstellen kann. Das einzige was der Decompiler nicht wiederherstellen kann sind Kommentare. Die Konsequenz davon ist, dass bei kommerziellen Programmen, die in .NET oder Java erstellt wurden, die Gefahr besteht, dass Programmteile und Algorithmen abgeschaut und nachgebaut werden können oder der Programmcode erweitert und angepasst werden kann. 27 Selbst bei unternehmensinternen Programmen entstehen dadurch Gefahren. So könnten zum Beispiel Datenbankpasswörter herausgefunden oder SQL-Abfragen manipuliert werden. Auch das Ausfindig machen von Schwachstellen ist sehr viel einfacher, da der Angreifer mit Quellcode arbeiten kann, anstatt sich mühsam mit Assembler-Code herumzuschlagen. Hinzu kommt, dass Disassembler für .NET und Java für jedermann frei und zum Teil als Freeware oder Open Source verfügbar sind: .NET Java Microsoft MSIL disassembler (ILDASM) .NET Reflector ILSpy The Java Class File Disassembler (javap) Java Decompiler (JD) DJ Java Decompiler Tabelle 1: Beispiele für .NET und Java Disassembler/Decompiler Die nachfolgende Abbildung zeigt das mit .NET geschriebene Programm Fiddler2 im dekompilierten Zustand. Es ist schön zu sehen, dass alle Bezeichner (Namespaces, Klassennamen, Funktionsnamen und Variablennamen) noch erhalten sind. Abbildung 7: .NET Programm Fiddler2 dekompiliert mittels ILSpy Code Obfuscation Tools Um nun das Reverse Engineering und die daraus resultierenden Gefahren zu verhindern, werden bei Programmiersprachen, in denen zu Bytecode kompiliert wird, sehr häufig Code Obfuscation Tools verwendet. Diese versprechen meist, dass durch die Anwendung der Obfuscation das Reverse Engineering der Programme mindestens genauso schwer wird, wie es bei nativen Applikationen, wie C oder Cobal der Fall ist. Als Ergebnis auf die starke Nachfrage gibt es natürlich für beide Sprachen ausreichend Obfuscatoren. Beispiele für .NET sind die Tools Agile.NET, Dotfuscator, ConfuserEx und 28 Obfuscar, wobei es sich bei den ersten beiden um kommerzielle Produkte handelt, während ConfuserEx und Obfuscar Open-Source Tools sind. Beim Dotfuscator ist erwähnenswert, dass dieser bereits als Lite-Edition in Visual Studio integriert ist. Eine ausführliche Übersicht mit Vergleich der angebotenen Obfuscation-Techniken von mehr als 10 .NET Obfuscatoren ist auf Wikipedia unter folgendem Link zu finden: https://en.wikipedia.org/wiki/List_of_obfuscators_for_.NET Auch für die Programmiersprache Java gibt es eine Vielzahl an Obfuscatoren, zum Beispiel ProGuard (Open Source), DexGuard (Android, kommerziell), Allatori Java Obfuscator (kommerziell), JODE (Open Source), Excelsior JET Evaluation (kommerziell) und Klassmaster (kommerziell). Eine Übersicht über die verschiedenen Java Obfuscatoren ist unter folgendem Link einsehbar: http://proguard.sourceforge.net/alternatives.html In Android Studio ist ProGuard sogar standardmäßig in die Build-Umgebung integriert und wird nach vorheriger Aktivierung automatisch gestartet sobald eine Applikation im „Release Mode“ erstellt wird. .NET Obfuscation Beispiele Eine von Preemptive Solutions (dem Hersteller von DotFuscator) patentierte Technik ist die sogenannte „Overload Induction“. Diese Technik macht nichts anderes als Variablen- und Funktionsnamen zu verändern. Dabei macht sie sich aber zu Nutze, dass derselbe Identifier für Klassen und Methoden verwendet werden kann, solange diese verschiedene Signaturen haben. Weiters können auch Variablen denselben Namen haben, sofern diese sich in verschiedenen Namespaces befinden. DotFuscator nutzt diese beiden Features um so viele Funktions-, Klassen- und Variablennamen wie möglich in den Buchstaben ‚a‘ bzw. ‚b‘ zu ändern. Dadurch können bis zu 33% aller im Code enthaltenen Bezeichner zu ‚a‘ und weitere 10% zu ‚b‘ umbenannt werden, was das Reverse Engineering des verschleierten Bytecodes extrem schwer macht. Hier ein Beispiel: private void CalcPayroll(SpecialList employeeGroup) { while (employeeGroup.HasMore()) { employee = employeeGroup.GetNext(true); employee.updateSalary(); DistributeCheck(employee); } } private void a(a b) { while (b.a()) { a = b.a(true); a.a(); a(a); } } Beim Vergleich der beiden Codesnippets geht zwar klar hervor, dass beide dieselbe Logik implementiert haben, jedoch ist es ungeheuer schwer nachzuvollziehen was genau der rechte Codeteil macht beziehungsweise welche Objekte, Eigenschaften und Methoden 29 verwendet und aufgerufen werden. Als zusätzliches Feature wird dadurch auch noch die Codegröße signifikant geschrumpft. Ähnlich wie bei kompilierten Sprachen wird auch bei Sprachen, die in Bytecode kompiliert werden, Control-flow Obfuscation angewandt um Disassembler (in diesem Fall den Menschen) zu täuschen. Dabei werden beispielsweise goto Statements in den Bytecode eingebaut, sodass die ursprüngliche Instruktionssequenz zwar in performanter Art ausführgeführt wird, dies aber mit einem hin und her Springen gemacht wird, dass es sehr schwer wird dem Logikfluss zu folgen: // Code Snippet copyright 2000, Microsoft Corp, from WordCount.cs public int CompareTo(Object o) { int n = occurrences - ((WordOccurrence)o).occurrences; if (n == 0) { n = String.Compare(word, ((WordOccurrence)o).word; } return (n); } Disassemblierter Bytecode ohne Code Obfuscation public virtual int a(object A_0) { int local0; int local1; local0 = this.a - (c) A_0.a; if (local0 != 0) goto i0; goto i1; while (true) { return local1; i0: local1 = local0; } i1: local0 = System.String.Compare(this.b, (c) A_0.b); goto i0; } Derselbe disassemblierte Bytecode mit Control-Flow Obfuscation Die Funktion macht zwar noch exakt dasselbe wie die Funktion oberhalb, jedoch durch die beiden Sprungbefehle, der zusätzlichen lokalen Variable und der falschen Endlosschleife wird selbst die Funktionalität dieser sehr kleinen Funktion, die im Endeffekt nur aus einer Subtraktion, einer Abfrage und einem Vergleich besteht, sehr schwer lesbar. Hat man nun 30 eine große Routine und keinen Vergleichscode zur Verfügung, so wird das Verstehen des Codes zu einer sehr zeitaufwändigen Aufgabe. Natürlich generiert diese Technik ein wenig Overhead und aufgrund der Komplexität kann es schon bei der Programmierung selbst viel einfacher zu Fehlern kommen. Bei zeitkritischen Funktionen sollte man deshalb dieses Feature eventuell deaktivieren oder entsprechende Tests durchführen. Weiters werden natürlich auch Data Obfuscation Techniken wie „String Encryption“ verwendet, um das Auslesen von String Literalen, wie Bibliothekaufrufen, SQL-Befehlen und Passwörtern zu verhindern. [27], [28] Java Obfuscation Beispiel Abbildung 8: links: Java Quellcode | rechts: Dekompilierter Java Quellcode Wie in der Abbildung oberhalb zu sehen ist, können auch in Java bloß die Kommentare vom Decompiler nicht zurückgewonnen werden, der Rest kann rekonstruiert werden. Das heißt auch hier kommen die Entwickler eines kommerziellen Programms um einen Obfuscator, wie zum Beispiel ProGuard, nicht herum. Das mit dem ProGuard verschleierte (aber nicht geschrumpfte oder optimierte) und mit Java Decompiler dekompilierte Programm sieht dann folgendermaßen aus: 31 Abbildung 9: Dekompilierter Java Quellcode, der mit ProGuard obfuscated wurde Auch Android Apps sind in Java geschrieben und werden in Bytecode übersetzt. Und auch bei Android werden die einzelnen Quellcode-Dateien (.java) in .class-Datei übersetzt. Doch anderes als gewöhnlich werden die .class-Dateien nicht in einem .jar-Archiv zusammengefasst und bei der Ausführung zur Laufzeit von der Java Virtual Machine (JVM) kompiliert, sondern sie werden in sogenannte .dex (Dalvik Executable) Bytecodedateien übersetzt, welche speziell für mobile Geräte optimiert sind. Die Dalvik Executables werden dann in einer .apk-Archivdatei zusammengefasst und können anschließend auf ein Android Gerät übertragen werden. [29] Bis zur Android Version 5.0 „Lollipop“ wurden am mobilen Endgerät die .apk-Dateien bzw. .dex-Dateien bei der Installation der App in .odex-Dateien (Optimized Dalvik Executable) umgewandelt, um dann bei der Ausführung der App von einer Process Virtual Machine namens Dalvik mittels Just-in-Time (JIT) Kompilierung in Maschinencode übersetzt zu werden. [30] Mit der Version 5.0 wurde nun ein Application Runtime Environment mit den Namen „Android Runtime“ eingeführt, welches die .dex-Dateien nicht in .odex Dateien umwandelt und dann Just-in-Time kompiliert, sondern eine Ahead-of-time (AOT) Kompilierung bei der Installation der App durchführt und eine ELF-Datei erstellt. [31] Doch egal ob nun JIT oder AOT bei Android verwendet wird, am mobilen Endgerät landet in beiden Fällen der Java Bytecode in Form der apk-Datei. Das heißt, dass auch bei Android Apps in jedem Fall Obfuscation eingesetzt werden muss, wenn man Funktionalität und Algorithmen vor neugierigen Dritten schützen möchte. 32 Interpreted Languages / Skriptsprachen (JavaScript, Python, Perl) Bei interpretierten Sprachen kann direkt die Quellcode-Datei ausgeführt werden. Das ist natürlich sehr bequem, führt im Gegenzug aber auch zu Performance-Einbußen und bedeutet, dass bei der Weitergabe von Programmen immer der gesamte Quelltext weitergegeben werden muss. Aus diesem Grund gilt für Skriptsprachen prinzipiell dasselbe wie bei der Weitergabe von C-Sourcecode oder bei der Weitergabe von Bytecodedateien: Ohne zusätzliche Obfuscation können Dritte Einblick in die Algorithmen haben. Aus diesem Grund gibt es für Sprachen wie JavaScript, Python und Perl eine ganze Menge an Obfuscatoren. Stellvertretend für Skriptsprachen wird in dieser Arbeit JavaScript behandelt, da sie als Programmiersprache des WWW sehr weit verbreitet ist. Anmerkung zu Python: Programmiersprachen wie Python, bei denen auf Klammern und Semikolon verzichtet wird und stattdessen die Programmstruktur mit Hilfe von Einrückungen bewerkstelligt wird, sind nur sehr schwer gut zu verschleiern, da die Struktur und Einrückungen ja auch im verschleierten Code noch beibehalten werden müssen! Javascript Javascript wurde ursprünglich entwickelt um Webseiten dynamisch zu manipulieren (Inhalte verändern, nachladen oder generieren) und ist als ECMAScript im ECMA-262 Standard spezifiziert. Heutzutage wird JavaScript zwar auch außerhalb des Browsers verwendet (Server, Apps, Spiele), jedoch liegt der Hauptanwendungsbereich noch immer bei Webseiten. [32] Minification und Kompression Auch für JavaScript-Programme besteht häufig die Anforderung die Funktionalität und die Algorithmen des Codes vor unbefugten Zugriffen zu schützen. Noch häufiger steht bei JavaScript jedoch die Anforderung im Vordergrund, möglichst wenige Ressourcen in Form von Speicherbedarf zu verbrauchen, da die Webseite mit dem zugehörigen Skript ja über das Internet übertragen wird und sich die Ladezeit proportional zur Downloadmenge erhöht. Aus diesem Grund gibt es die sogenannte „Minification“, bei der unnötige Zeichen wie Leerzeichen, Zeilenumbrüche, Kommentare und lange Bezeichner entfernt beziehungsweise ersetzt werden, ohne die Funktionalität des Programms zu beeinflussen. Minification ist prinzipiell zwar bei so ziemlich jeder Programmiersprache anwendbar, jedoch ist sie vor allem bei interpretierten Sprachen und bei im Internet übertragenen Quelldateien sehr hilfreich. Im Gegensatz zu einem komprimierten Programm kann ein minimiertes Programm direkt interpretiert werden und muss nicht vorher noch zur Laufzeit dekomprimiert werden. Tools, die fertigen bzw. kompilierten Programmcode komprimieren und anschließend vorne beim Programm eine Routine anfügen, die das Programm zur Laufzeit dekomprimiert, nennt man Runtime Packer. Sowohl Minification als auch Komprimierung haben das Ziel den (JavaScript) Code zu optimieren. Aus diesem Grund gibt es in der Praxis natürlich auch 33 Tools die den Quellcode zuerst mittels Minification minimieren, um ihn anschließend mittels eines Packers zu komprimieren. Obwohl einige JavaScript-Optimierungstools im Namen die Wörter Packer oder Compressor tragen, führen diese Tools meist keine wirkliche Kompression durch, sondern nur einfache Minification. [33] Nachfolgend einige Beispiele für gängige JavaScript Minification Tools: JSMin Packer Closure Compiler Microsoft Ajax Minifier YUI Compressor UglifyJS http://crockford.com/javascript/jsmin http://dean.edwards.name/packer/ http://closure-compiler.appspot.com/home http://ajaxmin.codeplex.com/ http://yui.github.io/yuicompressor/ http://marijnhaverbeke.nl/uglifyjs Obfuscation Minification kann zwar als eine Art der Obfuscation angesehen werden, jedoch meint man mit Obfuscation meist zusätzliche Funktionalitäten, wie Kompression und Verschlüsselung. Weiters ist es bei der Verschleierung von Code durchaus auch möglich, dass zusätzlicher (sinnloser) Code in die Anwendung eingefügt wird und diese dadurch zum Original wächst. Bei der Minification ist natürlich das Ziel die Anwendung so klein wie möglich zu machen. Nachfolgend einige Beispiele für gängige JavaScript Obfuscation Tools: JScrambler JavaScript Obfuscator JS Packer https://jscrambler.com/en/ http://javascriptobfuscator.com/ http://packer.50x.eu/ 2.2.3 Packer Der Begriff Packer bzw. Runtime Packer wurde in dieser Arbeit bis jetzt schon einige Male erwähnt. In diesem Abschnitt wird nun genauer erläutert wie diese funktionieren und was mit ihnen erreicht werden soll. Ganz allgemein ist ein Packer ein Programm mit dem Software/Programme komprimiert und/oder verschlüsselt werden können. Dabei kommen häufig gängige Kompressionsverfahren wie ZIP, CAB und RAR aber auch selbst geschriebene Verfahren zum Einsatz und ohne dass man den verwendeten Algorithmus kennt, kann man die Daten nicht wieder entpacken. Auf den ersten Blick sieht es also so aus als würden sich Runtime Packer nicht von „normalen“ Kompressionstools wie WinZip, WinRar, 7-ZIP, gzip, usw. unterscheiden. Doch es gibt einen signifikanten Unterschied: Bei gewöhnlichen Kompressionstools müssen eine oder mehrere Dateien im komprimierten Zustand zuerst wieder mit Hilfe desselben oder einem ähnlichen Tool dekomprimiert werden um die Dateien verwenden zu können. Bei „gepackten“ Programmen können die Programme jedoch direkt 34 ausgeführt werden, ohne dass ein externes Tool fürs Dekomprimieren verwendet werden muss. Das funktioniert deshalb weil Packer-Programme, nachdem sie ein Programm komprimiert haben, die Dekomprimierungsroutine direkt vorne in das Programm einfügen. Beim Programmstart wird dann diese Routine als erstes ausgeführt. Sie entpackt das komprimierte Programm zur Laufzeit und springt dann zum ersten Befehl des ursprünglichen Programms. Somit kann das Programm ganz normal ausgeführt werden. Lediglich beim Programmstart ist mit einer leichten Verzögerung gegenüber dem Original zu rechnen, da zuerst die Dekomprimierung stattfindet. Statt oder zusätzlich zur Komprimierung kann natürlich auch Verschlüsselung eingesetzt werden. Das Schema ist dasselbe. Ein Packer kann bei interpretierten, kompilierten als auch semi-kompilierten (Bytecode) Sprachen angewandt werden. Wichtig ist dabei nur, dass die Routine zum Dekomprimieren in der entsprechenden Sprache vorliegt (Maschinencode, Bytecode oder in der Skriptsprache, z.B. in JavaScript). Meist werden Packer als externe Tools verwendet um ein Programm nach der Fertigstellung zu komprimieren, dies ist aber nicht zwingend. Die Dekomprimierungsroutine kann auch schon bei der Programmierung des Programms in dieses als fester Bestandteil integriert werden. So können zum Beispiel ganz bestimmte Codeteile komprimiert werden, während der Rest dekomprimiert bleibt. [34], Schwächen und Gegenmaßnahmen Runtime Packer bieten zwar prinzipiell eine gute Möglichkeit für Deobfuscation, weisen aber eine entscheidende Schwäche auf: Selbst wenn ein Packer eine Software mit dem robustesten kryptographischen Algorithmen verschlüsselt, früher oder später muss die komprimierte und/oder verschlüsselte Applikation entpackt/entschlüsselt werden, damit die CPU das Programm ausführen kann. Und genau das ist der Zeitpunkt bei dem das Reverse Engineering normalerweise startet. Der Analyst macht einfach einen Speicher-Dump der dekomprimierten/entschlüsselten Anwendung und speichert diesen auf der Festplatte. Somit kann er die Originalsoftware analysieren und muss sich nicht mit den Schutzmechanismen befassen. [34] Vor der Dekomprimierung kann der Algorithmus als mögliche Gegenmaßnahme zusätzlich prüfen ob er in einer virtuellen Maschine oder einem Debugger läuft bzw. ob am System ein Disassembler läuft. Wird er fündig so bricht er die Dekomprimierung ab oder dekomprimiert einen harmlosen Codeteil um den Reverse Engineer zu täuschen. Weiters ist es natürlich möglich mehrere Komprimierungen bzw. Verschlüsselungsvorgänge hintereinander zu vollziehen. Diese Technik wird häufig von Malware verwendet um die Detektion und das Reverse Engineering möglichst schwierig zu machen. Während im Jahre 2006 über 92% der gesamten Malware mittels eines Packers komprimiert war [35], sind es 2014 nur mehr um die 60% [36]. 35 Beispiele für Packer Es gibt eine Vielzahl an verschiedenen Runtime Packern. Unter shadowserver.org ist eine Statistik verfügbar, die die beliebtesten bzw. meist gebräuchlichen Packer zeigt: https://www.shadowserver.org/wiki/pmwiki.php/Stats/PackerStatistics Der bekannteste und am häufigsten verwendete Packer ist UPX (ultimate packer for executables). UPX eignet sich besonders zur Komprimierung von Linux-ELF (32- und 64Bit), DOS-EXE (16- und 32-Bit), Windows-PE (EXE und DLL) oder auch TOS-Dateien. Er unterstützt aber auch eine ganze Reihe von weiteren Formaten. UPX (unverändert) bietet jedoch keinen guten Schutz gegen Reverse-Engineering, da sich die UPX-gepackten Programme durch UPX selbst wieder entpacken lassen. Unveränderte UPX-gepackte Programme werden auch häufig von Antivirenprogrammen als solche erkannt und dekomprimiert. [37] Weitere Beispiele für Packer sind ASProtect, PECompact oder Morphine. Eine ausführliche Liste von Runtime Packers kann auf Wikipedia eingesehen werden: https://en.wikipedia.org/wiki/Executable_compression 2.2.4 Virtualisierung Auch virtuelle Maschinen können zum Schutz von Software vor Reverse Engineering eingesetzt werden. Im Bereich Software-Schutz und Obfuscation ist eine virtuelle Maschine eine Softwarekomponente, die einen Prozessor emuliert. Aus diesem Grund wird auch manchmal der Begriff virtueller Prozessor verwendet. Dieser virtuelle Prozessor besitzt seinen eigenen Instruktionssatz und kann Programme ausführen, welche in einem speziellen Bytecode kompiliert wurden. Der Prozessor muss dazu in das Programm integriert werden, damit dieses dann auch ausgeführt werden kann. Um einen möglichst guten SoftwareSchutz zu erzielen, ist die virtuelle Maschine folglich möglichst komplex aufgebaut, zum Beispiel kann sie auf einer exotischen Architektur basieren. Um die Komplexität weiter zu erhöhen, können für ein Programm auch mehrere virtuelle Prozessoren verwendet werden. Das kann entweder horizontal, also verschiedene Teile der ausführbaren Datei werden auf verschiedenen virtuellen Prozessoren ausgeführt, oder auch vertikal, also indem eine virtuelle Maschine in einer anderen virtuellen Maschine läuft, implementiert werden. [38] [39] Diese Art von Obfuscation wird unter anderem von kommerziellen Tools wie VMProtect, Themida, StarForce und SecureROM eingesetzt. Darüber hinaus gibt es auch mehrere Malware-Programme, die ihre eigene virtuelle Maschine verwenden um ihren Schadcode vor Antivirensoftware zu schützen. 36 2.2.5 Deobfuscation Als logische Konsequenz auf Obfuscation Tools, sind natürlich Deobfuscation Tools entstanden, die versuchen verschleierten Code wiederum zu entschleiern. Viele dieser Tools sind vor allem auch für Malware-Analysen von großer Bedeutung. Die vielen verschiedenen Deobfuscation Tools und Unpacker verdeutlichen noch einmal, dass wir es bei Obfuscation und Software Protection mit Security by Obscurity zu tun haben und die Verschleierung zwar eine zusätzliche Hürde beim Reverse Engineering darstellt und dieses aufwändig und zeitintensiv macht, jedoch kann früher oder später jede noch so ausgeklügelte Methode umgangen bzw. rückgängig gemacht werden. Auf die genauen Techniken, die die Deobfuscatoren verwenden wird in dieser Arbeit nicht eingegangen. Dennoch sind hier einige .NET de4dot iMPROVE .NET Deobfuscator Javascript JSUnpack JavaScript Deobfuscator JSDetox Binary Unpacking & Packer Erkennung PEiD ExeScan RDG Packer Detector PE.Explorer Devirtualization VMProtect Ultra Unpacker Themida - Winlicense Ultra Unpacker 2.3 Malware vs. Antivirus Malware ist die Kurzform für „malicious software“ (deutsch: Schadprogramm) und bezeichnet Software, die mit dem Ziel programmiert wurde, um auf dem installierten Hostsystem vom Benutzer unerwünschte und/oder schädliche Funktionen durchzuführen. Dazu gehört zum Beispiel das Manipulieren, Löschen oder Übermitteln von Daten, wie Dokumente, Passwörter und elektronische Nachrichten, sowie das außer Gefecht setzen eines Systems (Denial of Service). Diese Schadfunktionen werden dabei gewöhnlich im Hintergrund 37 ausgeführt und sollen vorm Benutzer bzw. Systembetreiber verborgen bleiben. Zusätzlich lässt sich Malware meist auch nicht mit gebräuchlichen Mitteln deinstallieren, da sich diese an verschiedenen Stellen und so tief im System verankert, dass meist voll funktionsfähige Schadcodeteile auch nach einer vermeintlichen Installation noch ihre Funktionen ausführen. [40] Malware Typen Wie aus dieser Definition hervorgeht ist Malware ein Oberbegriff und kann in folgende Typen unterteilt werden: Malwaretype Beschreibung Virus Ein Virus benötigt ein Wirtprogramm zur Ausführung seiner Befehle. Er kann sich reproduzieren & mit Hilfe des Benutzers verbreiten. Dazu legt der Virus Kopien von sich selbst in einem Speicherbereich (Programme, Datenträger und Dokumente) der seine Befehlssequenz noch nicht enthält (Infektion). Werden diese Daten von einem System auf ein anderes gesendet bzw. kopiert, so wird dadurch auch der Virus übertragen. Aus der Definition geht hervor, dass ein Virus sich nicht selbständig ausführen kann. Er wird ausgeführt, sobald die infizierte Datei vom Benutzer geöffnet wird. Nachdem der Virus seinen schadhafte Code ausgeführt hat, führt er meist noch die Funktion aus, die der Benutzer eigentlich getriggert hat, indem er an die Stelle der Datei springt, die ursprünglich der Startpunkt der Ausführung war. Dadurch bleibt er vom Benutzer unerkannt. Beispiel: Sobig Virus Worm Ein Computerwurm ist ein eigenständiges Programm welches sich reproduzieren und über Computernetzwerke verbreiten kann. Durch die Unabhängigkeit von einem Wirt, kann sich ein Wurm wesentlich schneller verbreiten als ein Virus. Beispiele: Internet-Wurm, ILOVEYOU-Wurm, Lovesan-Wurm Trojan Horse Ein Programm, welches sich wie ein trojanisches Pferd verhält, bietet dem Benutzer Funktionalitäten die dieser benötigt bzw. Vertrauen erwecken, ergänzt diese jedoch durch versteckte Schad-Funktionen. Der Benutzer wird also getäuscht. Häufig entfalten Trojaner ihren Schadfunktionen erst nach Verstreichen eines gewissen Zeitraums oder bei Eintreten eines gewissen Ereignisses. Beispiele: Häufig verstecken sich hinter Freeware, Raubkopien, Keygens und Anhängen in Emails Trojaner. Ransomware Setz sich aus den Begriffen Malware und Ransom (Lösegeld) zusammen und beschreibt Software, die nach dem Eindringen auf einem fremden Rechner, dessen Daten auf der Festplatte zu verschlüsselt bzw. den 38 Zugriff auf den Rechner verhindert. Für die Entschlüsselung wird dann in weiterer Folge ein Lösegeld eingefordert, das über OnlineZahlungssysteme eingezahlt werden muss. Spyware Ist ein Programm, welches Informationen über die Benutzer eines Systems sammelt (Passwörter, Email, Dokumente, Tastatureingaben, …) und diese über das Internet an Dritte weiterleitet. Diese Daten werden dann entweder verkauft oder für weitere Angriffe verwendet. Spyware wird häufig als Trojaner mit einem anderen nützlichen Programm mitinstalliert und bleibt auch nach der Deinstallation des nützlichen Programms noch auf dem Rechner. Adware Adware ist im Prinzip dasselbe wie Spyware, nur das die Schadfunktionen nicht Passwörter oder Dokumente stehlen, sondern Funktionen ausführen, die entweder Werbung zeigen oder das Nutzerverhalten in Bezug auf Werbung oder Marktforschung ausspionieren. Scareware Scareware versucht den System-Benutzer zu verunsichern und ihn dazu zu verleiten entweder ein schädliches Programm zu installieren oder Geld für ein eigentlich unnützes Programm zu bezahlen. Beispiel: Falsche Warnmeldung über einen Virenbefall, der nur mittels eines kostenpflichtigen Programms entfernt werden kann. Rogueware Bezeichnet falsche Sicherheitssoftware, die dem Benutzer nur vorgaukelt vermeintliche Schadprogramme zu deinstallieren. Die Rogueware ist dabei entweder kostenpflichtig oder installiert ein Schadprogramm während es die Entfernung von Schadsoftware vortäuscht. Tabelle 2: Malware Typen In der Praxis verschwimmen die oben angeführten Ausprägungen von Malware immer häufiger, da die Entwickler natürlich versuchen so viele Funktionen wie möglich in ihre Schadprogramme zu packen. So gibt es zum Beispiel Würmer, die als Ransomware fungieren oder Viren, die Spyware-Funktionalitäten aufweisen. Meist lässt sich grob unterscheiden ob es sich um ein Virus, einen Wurm oder einen Trojaner handelt, da diese 3 Arten unterschiedliche Verbreitungsstrategien vorweisen. Natürlich können aber auch diese kombiniert werden. [40], [41], [42] Malware vs. Antivirus – Das „Katz und Maus“ Spiel Es gibt verschiedene Wege sich vor den diversen Malware-Arten zu schützen, wie zum Beispiel Rechtebeschränkung, Deaktivierung von Autostartfunktionalitäten, Quarantäne und Isolierung, die allesamt präventive Maßnahmen darstellen. Am häufigsten werden jedoch Virenscanner bzw. Antivirus Programme eingesetzt um sich vor Malware zu schützen (der 39 Name „Antivirus“ ist ein wenig irreführend). Diese verwenden unter anderem eine Musterbzw. Signaturerkennung um eine bereits bekannte Malware zu erkennen und dessen Ausführung zu verhindern. Dazu muss die entsprechende Malware zuerst einmalig von den Analysten eingefangen und auf Schadfunktionen analysiert werden. Werden diese gefunden, so wird ein charakteristischer Teil des Schadprogramms hergenommen und in einer Signaturdatenbank gespeichert. Diese Datenbank wird an die einzelnen AntivirusProgramme regelmäßig als Update versendet. Die sogenannte Scanengine des Antivirus führt dann bei den am System vorhandenen Dateien bzw. bei Programmen die gestartet werden einen Bitmustervergleich mit der Signaturdatenbank durch und kann somit Kopien der Malware ausfindig machen. Diese einfache Erklärung für Signaturerkennung von Malware ist natürlich nicht mehr ganz 100% „State of the Art“ und wurde bereits Anfang der 90er Jahre verwendet. Die Entwickler von Malware versuchen natürlich diese Art der Signaturerkennung zu umgehen und reagieren darauf mit Verschleierungstechniken, so wie sie im vorherigen Abschnitt vorgestellt wurden. Ziel ist es den Schadcode so zu konstruieren, dass er möglichst schwer von einem Antivirusprogramm erkannt werden kann. Dadurch wird die Wahrscheinlichkeit höher, dass möglichst viele Systeme von der Malware befallen werden können und diese möglichst lange unentdeckt bleibt. Zur besseren Verständnis folgt ein einfaches Beispiel wie Signaturerkennung bei JavaScript funktioniert. Der nachfolgende Code ist nur ein kleiner Teil eines Exploits mit dem die „execCommand Use After Free Vulnerability - CVE-2012-4969“ ausgenutzt werden kann und wurde aus [43] übernommen. Diese 3 Zeilen (5 – 7) JavaScript werden von den Antivirus-Programmen GData, Ad-Aware, BitDefender, Emsisoft, F-Secure, MicroWorld-eScan und nProtect verwendet um den Exploit als Malware zu identifizieren. Aus diesem Grund wird die HTML-Datei von diesen Scannern als bösartig eingestuft, obwohl sie eigentlich gar nichts macht. 40 Abbildung 10: VirusTotal.com Scanergebnis des JavaScript-Codes von oberhalb Wie können die 3 Zeilen nun abgeändert werden, sodass diese nicht mehr als bösartig erkannt werden? Ganz einfach: Anstatt das window-Objekt in Zeile 6 direkt zu verwenden, wird dieses zuerst auf eine neu angelegte Variable w gespeichert: Nun folgt wieder der Test auf virusTotal.com: Kein Virenscanner erkennt den Code mehr als bösartig. Abbildung 11: VirusTotal.com Scanergebnis des abgeänderten JavaScript-Codes von oberhalb 41 Nachfolgend werden verschiedene Techniken und Vorgehensweisen von Malware aufgelistet, die dabei helfen sollen unentdeckt zu bleiben. Weiters wird auf die jeweiligen Gegenmittel der Antivirus – Hersteller eingegangen: Self-Encryption and Self-Decryption. Viren verschlüsseln und entschlüsseln bzw. komprimieren und dekomprimieren ihren Code um diesen vor einer direkten Prüfung des Codes zu verbergen. Dabei werden entweder mehrere Verschlüsselungsvorgänge verwendet oder zufällig erstellte Schlüssel, damit jede neue Kopie des Virus anders aussieht obwohl derselbe Code als Klartext-Basis verwendet wird und auf der CPU auch weiterhin derselbe Code ausgeführt wird. Im Kapitel Code Obfuscation wurden schon Programme vorgestellt, die eine solche Funktionalität implementiert haben: Runtime Packer. Laut einer Untersuchung von mehr als 6 Millionen Malware-Samples [36] ist UPX nach wie vor der beliebteste Packer für Malware (~20%). Die meisten Packer sind jedoch malwarespezifisch und können keinem verfügbaren Packer zugeordnet werden (~60%) Diese Technik erschwert nicht nur die Signaturerkennung (diese ändert sich ja zum größten Teil bei jeder Kopie), sondern vor allem auch das Reverse Engineering bei der Analyse der Malware. Da sowohl Entschlüsselungsfunktion (Decryptor Stub) als auch Entschlüsselungsschlüssel (Secret Key) in der Malware enthalten sein müssen ist es jedoch dennoch möglich durch eine statische Codeanalyse (also ohne Ausführung des Programms) den eigentlichen Code zu extrahieren um diesen analysieren zu können. Weiters kann die Funktion zum Entschlüsseln selbst nicht verschlüsselt werden. Das ermöglicht wiederum den AV-Herstellern charakteristische Signaturen für den Decryptor Stub zu erstellen und nach diesem in den Dateien zu suchen. Oligomorphism. Der nächste logische Schritt der Virenhersteller ist daher zu versuchen den Decryptor Stub so zu verändern, dass dieser per Signatur-Check nicht erkannt wird. Daher wird bei jeder Kopie der Malware nicht nur der Verschlüsselungsschlüssel geändert, sondern zusätzlich auch der Entschlüsselungsvorgang. Das kann im einfachsten Fall das zufällige Auswählen von mehreren (hunderten) vorgefertigten Decryptor Stubs sein. Da diese Anzahl nicht allzu groß ist, ist es jedoch meist immer noch möglich die Malware mittels Signaturerkennung zu identifizieren. Dazu müssen die Analysten nur von allen möglichen Stubs eine Signatur entnehmen und all diese in die AV-Datenbank einpflegen. Eine weitere Methode zur Erkennung eines Oligomorphen Dekryptors wäre es eine Signatur für jede mögliche Codezeile zu erstellen und diese Signaturen in allen möglichen Kombinationen aneinanderzureihen. [44] 42 Polymorphism. Eine polymorphe Malware verändert bei jeder Kopie von sich selbst ihre gesamten zu Grunde liegenden Befehle, ohne die Funktionalität der Software zu verändern. Dies wird mit Hilfe einer sogenannten „Polymorphic Engine“ gemacht und dabei ist Verschlüsselung wiederum die herkömmlichste Art um Polymorphie zu implementieren. Im Gegensatz zur oligomorphen Malware heißt dass, das der Decryptior Stub nicht aus einer Vorauswahl von möglichen Stubs ausgewählt wird, sondern dass fast keine Kopie der anderen gleicht. Das nachfolgende Beispiel wurde direkt vom unterhalb zitierten Wikipedia-Artikel übernommen. Dabei handelt es sich zwar nicht um einen wirklichen polymorphen Code, jedoch gibt es eine Vorstellung davon, wie man es bewerkstelligt den Decryptor Stub bei jeder Kopie der Malware zu mutieren. In diesem Beispiel wird die Mutation über die Variable C bewerkstelligt. Da diese Variable in die Entschlüsselung nicht miteingeht, ist ihr Wert im gesamten Entschlüsselungscode eigentlich egal. Das heißt die Zeilen 4, 8, 11,12 und 15 können fast nach Belieben geändert werden, solange der L-Operant das C bleibt. Ja noch mehr sogar: Es können auf den Basiscode für die Entschlüsselung (Zeilen: 3, 5, 6, 7, 9, 10, 13, 14, 16, 17, 18) so ziemlich alle schon in dieser Arbeit erläuterten Obfuscation Methoden angewandt werden um den Decryption Stub bei jeder Malware-Kopie aufs Neue abzuändern. In der Zeile 0 – 2 befindet sich in diesem Beispiel der verschlüsselte Payload. In diesem sind die eigentlichen Schadfunktionen, der Code zum Verbreiten der Malware, sowie der Code zum Kopieren und Verschlüsseln der Malware und zum Mutieren des Decryption Stubs enthalten. Im verschleierten Decryption Stub (Zeile 3 – 18) wird nichts anderes gemacht als auf der Variable A die Startadresse der verschlüsselten Payload zu speichern und danach mittels einer Schleife über alle Speicheradressen zu iterieren und für jede Adresse eine XOR-Operation mit dem symmetrischen Schlüssel durchzuführen bis das Ende des verschlüsselten Codes erreicht wurde. Sobald dies der Fall ist wird die Schleife verlassen und mittels eines Sprungbefehls an den Beginn des nun entschlüsselten Code verzweigt. 43 0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: ... lots of encrypted code ... Decryption_Code: C = C + 1 A = Encrypted Loop: B = *A C = 3214 * A B = B XOR CryptoKey *A = B C = 1 C = A + B A = A + 1 GOTO Loop IF NOT A = Decryption_Code C = C^2 GOTO Start_of_Encrypted_Code CryptoKey: some_random_number Eine vergleichsweise einfache Methode um Polymorphie bei den Malware-Instanzen sicherzustellen ist die sogenannte serverseitige Polymorphie. Dabei wird die Malware über einen Webserver verbreitet, der neben der Infektion von Rechnern auch gleich die Malware automatisiert abändert (durch Packer, andere Verschlüsselungsparameter, Obfuscation), sodass jede Malware-Instanz wirkt als wäre sie einzigartig. In diesem Fall muss sich die Malware-Instanz selbst nicht reproduzieren und benötigt selbst keinen Code zum Verschleiern der Kopien. Dadurch wird die Malware schlanker und muss weniger verdächtige Funktionen durchführen, die sie als Schadprogramm identifizieren könnten. Eine polymorphe Malware zu erkennen ist aus oben genannten Gründen daher schon nicht mehr ganz so einfach mittels Signaturerkennung zu bewerkstelligen. Der Grund dafür ist einfach, dass sich die gesamte Befehlssequenz der Malware bei jeder Kopie verändert und somit keine Instanz der anderen gleicht. Es müssen also andere Ansätze gefunden werden: Statische Analyse durch “Unpacking” Die zu überprüfende Datei wird analysiert und bei Feststellung von Komprimierung bzw. Verschlüsselung (zb. durch erhöhte Entropie) wird analysiert ob ein dem AV-Programm bekannter Packer verwendet wurde. Ist dies der Fall, so wird versucht die Malware zu dekomprimieren / entschlüsseln um anschließend eine statische Analyse, zum Beispiel mit Hilfe von Signaturen, durchführen zu können. 44 Laufzeit-komprimierte Dateien als gefährlich einstufen Funktioniert das Entpacken einer laufzeitgepackten Anwendung nicht, so verwenden einige Antivirus die Strategie diese Datei einfach als gefährlich einzustufen und diese vorerst an der Ausführung zu hindern. Der Benutzer erhält eine Warnung und kann entscheiden ob er das Programm ausführen möchte oder nicht. Der Nachteil bei dieser Strategie ist, dass es durchaus auch legitime Verwendungszwecke für Packer gibt und der Benutzer öfters mit False-Negative Meldungen konfrontiert wird. Dynamische Analyse durch Emulation und Signaturen Die zu überprüfende Datei wird in einer sicheren, virtuellen Umgebung (Sandbox) ausgeführt und darauf gewartet, dass die Malware den Schadcode entpackt um diesen auszuführen. Nun kann wiederum mit Hilfe von Signaturen geprüft werden ob es sich um eine bekannte Malware handelt. Das Problem bei dieser Methode ist die Geschwindigkeit. Außerdem verwenden Malware-Hersteller Methoden um zu erkennen ob ihre Software in einer virtuellen Umgebung ausgeführt wird. Dynamische Analyse wird auch als dynamische Heuristik bezeichnet, da das Verhalten der Malware auf verdächtige Funktionen hin untersucht wird. [45] Metamorphism. Auf Grund des Blockierens von komprimierten/verschlüsselten Anwendungen und der dynamischen Analyse von Anwendungen in einer virtuellen Umgebung geht das Spiel in die nächste Runde. Polymorphe Techniken sind zwar nach wie vor State of the Art und weit verbreitet, jedoch gibt es eine weitere Variante jede Malware-Instanz anders aussehen zu lassen, und das ganz ohne Komprimierung oder Verschlüsselung zu verwenden. Dazu wird Metamorphie verwendet. Ganz allgemein fertigt ein metamorpher Code ein logisches Äquivalent von sich selbst an (wie eine Quine), jedoch mit modifizierten Source- bzw. Maschinencode. Eine Malware, die sich diese Technik zu Nutze macht, verwendet also die schon bereits in dieser Arbeit behandelten Methoden der (Code) Obfuscation um jede Instanz anders aussehen zu lassen. Ein sehr einfaches Beispiel wurde dafür schon beim Decryptor Stub bei polymorpher Malware gezeigt. Wird „Code Obfuscation bevor Compilation“ verwendet, so muss das logische Äquivalent auch noch neu übersetzt werden. Durch diese Methode können meist bessere Ergebnisse erzielt werden als beim verschleiern des Maschinencodes. Da bei polymorphen Code die polymorphe Engine verschlüsselt wird, bleibt diese immer gleich bei jeder Malware-Instanz. Bei metamorpher Malware muss sich wirklich der gesamte ausführbare Code der Malware ändern und daher wird auch das Aussehen der metamorphen Engine immer wieder abgeändert. 45 Zu den Mutationsmethoden zählen folgende Techniken: Austauschen der verwendeten Register Ändern des "Control Flow" und Umordnen von Anweisungen Austauschen der Maschinen Befehle in äquivalente andere Verwenden von äquivalenten Formeln und konstante Transformationen Einfügen von Leercode (Dead Code Insertion) Aufruf von Subroutinen Der Zperm Virus verwendet zum Beispiel das „Umordnen von Anweisungen“ und „Einfügen von Sprungbefehlen“ um Metamophie zu gewährleisten: Abbildung 12: Zperm: Metamorphie mittels umordnen von Instruktionen und einfügen von Jump Statements [46] Eine weitere Form einer metamorphen Malware ist ein Executable, welches in der Lage ist auf zwei oder mehreren Betriebssystemen (zB. Windows und GNU/Linux) ausgeführt zu werden und Schaden anzurichten. Bewerkstelligt wird dies, indem die Datei einfach mehrere Malware-Varianten in sich trägt. Wichtig ist dabei, dass der Startcode der Malware so programmiert wurde, dass dieser in korrekten Maschinencode, für alle ZielPlattformen auf denen er ausgeführt werden soll, kompiliert werden kann. Gegen eine Metamorphe Malware kommt man weder mit Signaturprüfung noch mit Emulation und anschließender Signaturprüfung an. Jedoch kann das Antivirus mithilfe von statischen und dynamischen Heuristiken versuchen die Malware zu erkennen. Bei statischen Heuristiken wird zum Beispiel nach spezifischen API-Aufrufen und Entschlüsselungs-Funktionen gesucht. Bei dynamischen Heuristiken wird das Programm emuliert ausgeführt und verdächtiges Verhalten, wie zum Beispiel das Manipulieren von Systemdateien, detektiert. Durch Heuristiken kann prinzipiell auf gänzlich neue Malware gefunden werden. Das Problem dabei ist nur die relativ hohe false-positive und falsenegativ Rate. Eine weitere Methode ist die Detektion nach dem Hidden Markov Model (HMM), welches in dieser Arbeit nicht genauer erläutert wird. Einen Überblick kann man sich hier verschaffen: [47]. [48] 46 Da die vorgestellten Techniken Polymorphie und Metamorphie nicht ganz einfach zu implementieren sind, verwenden die meisten Malware-Autoren einfach existierende Lösungen um ihren Schadcode vor Entdeckung zu schützen. Häufig werden auch „Metamorphic Virus Generation Toolkits“ verwendet, mit denen sich metamorphe Viren per Mausklick erstellen lassen. Weitere Techniken um unerkannt zu bleiben Stealth. Schon die ersten Viren hatten Techniken implementiert um sich zu tarnen und eine Entdeckung zu vermeiden. Zu diesen Techniken gehören zum Beispiel: Änderungsdatum der infizierten Datei nicht verändern Sich selbst im Speicher verstecken Betriebssystemtabellen so verändern, dass die Dateigrößen der infizierten Dateien sich nicht verändern Kopien von infizierten Dateien anlegen, übernehmen von Systemfunktionen fürs lesen von Dateien und/oder Festplattensektoren um Virenscanner auf die Kopien der Dateien umzuleiten Um dennoch zu erkennen ob eine (Betriebssystem-) Datei geändert wurde werden Hashwerte und/oder kryptografische Signaturen verwendet. Armoring. Armoring bezeichnet Techniken, die dazu verwendet werden um die Analyse von Malware durch AV-Software oder Menschen, durch Debugging, Disassemblierung, Dekompilierung, De-Obfuscation, usw. zu verhindern (Anti-VM, Anti-Disassembly, AntiDebugging). Wird zum Beispiel eine virtuelle Umgebung oder ein Debugger erkannt, so wird ein anderer (harmloser) Teil der Malware extrahiert und nicht der Schadcode. Eine kleine Einführung in die verwendeten Techniken ist in [49] zu finden. [50] 47 3 Proof of Concept Basierend auf den eben theoretisch beschriebenen Techniken zur Verschleierung von Schadsoftware, werden diese in einem praktischen Versuchsaufbau auf Ihre Wirkungsweise und Funktionalität überprüft. Dabei werden die verwendeten Tools unter den Aspekten Detektionsrate, Zeitaufwand und Schwierigkeit untersucht. 3.1 Vorgehensweise Für die Umsetzung der Tests wurde eine virtuelle Maschine (VM) mit dem Betriebssystem Windows XP Professionell Service Pack3 aufgesetzt und sämtliche verfügbare Windows Updates installiert. Danach wurden mehrere freie Antiviren-Software-Produkte auf der VM, zur Überprüfung der Schadsoftware, installiert: Avast Free Antivirus, Version 2015.10.0.2208, Virendatenbankversion 150202-0 Avira Free Antivirus, Version 14.0.7.468, Virendefinitionsdatei 8.11.206.130 AVG AntiVirus Free, Version 2015.0.5645, Virendatenbankversion 4253/9042 Kaspersky Anti-Virus, Version 15.0.1.415 (b), Database release date: 2.2.2015 Anschließend wurden die bereits öffentlich bekannten Binaries des ZeuS Trojaners von https://zeustracker.abuse.ch/downloads/zeusbinaries.zip heruntergeladen. Diese werden zur Überprüfung der File-Scans der oben angegeben Antiviren-Produkte verwendet. Um nun die erwähnten Zeus-Executables vor den Viren-Scannern zu verschleiern, bedient man sich sogenannter Packer oder auch Crypter. Diese ermöglichen eine Verschlüsselung der Software, sodass diese nicht mehr disassembliert werden kann und somit auch von den Anti-Viren-Lösungen analysiert werden kann. Aus der zahllosen Menge wurde das Produkt „Yoda’s Crypter“ in der Version 1.03.3 ausgewählt, um die ZeuS-Binaries zu verschleiern und das Ergebnis mittels der Anti-Viren-File-Scans zu überprüfen. Eine andere Möglichkeit der Verschleierung stellt die Code Obfuscation bereits zum Zeitpunkt der Erstellung der Assemblys aus dem Source Code oder aus den fertigen Assemblys. Solche Code Obfuscation Tools sind meist auf eine bestimmte Umgebung zum Beispiel .Net Framework oder Java zugeschnitten und bieten den Vorteile, dass der Source Code selbst dermaßen verschleiert wird, sodass eine Code Analyse enorm erschwert bzw. sogar unmöglich gemacht wird. Eine solche Funktionalität bietet beispielsweise das Produkt „Smart Assembly“, welche .Net Applikationen verschleiern kann. Zu diesem Zweck wurde Microsoft Visual C# 2010 Express installiert und der Source Code bzw. das Assembly des Keyloggers „AvesoftKeylogger“ verwendet, um diesen mit „Smart Assembly 6“ zu verschleiern und erneut mittels der Anti-Viren-File-Scans zu überprüfen. 48 3.2 Durchführung Als erstes wurde die ZeuS-Bot-Binary mit Hilfe des Tools „Yoda’s Protector“ gepackt und mittels der installierten Anti-Virus Produkte überprüft. Abbildung 13: Obfuscation des ZeuS-Bot mittels yoda’s Protector v1.03.3 Aus dem Executable zeusbin.ex0 wurde also das komprimierte zeusbin_packed.ex0 erstellt. Zusätzlich wurden, wie auf der Abbildung oberhalb zu sehen ist, noch diverse weitere Schutzmechanismen angewandt: Schutz gegen Kernel Mode Debugging mittels SoftICE Schutz der Checksumme Schutz vor dem Umlenken der API Aufrufe zwecks Reverse Engineering Schutz vor Anti-Dumping Entfernen Import Informationen Entfernen der .reloc Sektion aus dem PE Header Entfernen der Debug Informationen Entfernen des MS-DOS Header Im zweiten Schritte werden nun die beiden ausführbaren Dateien jeweils nacheinander mittels verschiedener Virenscanner überprüft. Durch diese Vorgehensweise ist sichergestellt, dass beide Executables mit denselben Virendatenbanken verglichen werden. Die Die folgenden 4 Screenshots zeigen, dass alle 4 Antiviren-Produkte den originalen ZeusTrojaner erkennen: 49 Abbildung 14: avast! Prüfergebnis des originalen ZeuS-Bots Abbildung 15: AVG Prüfergebnis des originalen ZeuS-Bots Abbildung 16 & 17: Avira & Kaspersky Prüfergebnis des originalen ZeuS-Bots Eine Analyse des Zeus-Bots unter www.virustotal.com liefert ebenfalls ein eindeutiges Ergebnis. So gut wie alle Virenscanner erkennen die ausführbare Datei als Virues. 50 Abbildung 18: VirusTotal Prüfergebnis des originalen ZeuS-Bots Im Gegensatz dazu wird die mittels „Yoda’s Protector“ gepackte .exe nur von Avira Antivir als gepacktes Executable erkannt und als kritisch eingestuft. Die übrigen Virenscanner erkennen keine Bedrohung. Abbildung 19: avast! Prüfergebnis des verschleierten ZeuS-Bots Abbildung 20: AVG Prüfergebnis des verschleierten ZeuS-Bots Abbildung 21 & 22: Avira & Kaspersky Prüfergebnis des verschleierten ZeuS-Bots 51 Beim Virus-Scan unter virustotal.com erkennen nur 14 von 57 Scannern das Executable als Bedrohung und selbst diese können nur feststellen, dass es sich um eine gepackte Applikation handelt, aber nicht was diese beinhaltet. Abbildung 23: VirusTotal Prüfergebnis des verschleierten ZeuS-Bots Bytecode Obfuscation Beispiel (.NET) Mittels der Code Obfuscation auf Bytecode Ebene für .Net-Anwendungen lassen sich zahlreiche weitere Einstellungen treffen, als im Vergleich zur reinen Verschleierung mittels einer Packer-Software. Das Tool „Smart Assembly 6“ bietet beispielsweise Möglichkeiten zur Signierung, automatischen Fehlerberichterstattung, Berichterstattung der Funktionsnutzung, Migration von Abhängigkeiten, Pruning (Entfernung von nicht benötigten Information z.B: Metadaten, Namen von Events, Eigenschaften, …), dynamischen Umbenennung von Klassen- und Methodennamen, Änderung des Programmablaufes, externe Methodenaufrufe über einen Proxy, Verschlüsselung der Ressourcen und Strings, etc. 52 Abbildung 24: Smart Assembly GUI (.NET Obfuscator) Mit Hilfe des Tools „Smart Assembly“ wurde nun ein in .NET programmierter Keylogger verschleiert. Bei der Analyse des ursprünglichen und neu generierten Assemblies mittels des ILSpy .NetDisassemblers erkennt man (wie schon im Grundlagen Kapitel erläutert), dass sich die ursprüngliche Version vollständig analysieren und lesen lässt. Abbildung 25: Mit ILSpy disassembelter original Bytecode des Keyloggers 53 Im Vergleich dazu, ist aus der neu generierten Version des Keyloggers nur schwer Information herauszulesen. Außerdem erkennt man, dass der Programmablauf am Beispiel der appendLogFile – Funktion wesentlich verändert wurde. Abbildung 26: Mit ILSpy disassembelter verschleierter Bytecode des Keyloggers Als weitere Alternative wurde der Keylogger mittels des ConfuserEx v0.4.0 verschleiert. Abbildung 27: ConfuserEx v0.4.0 GUI Neben der Auswahl des zur verschleiernden Executables (siehe Abbildung 27) bietet der ConfuserEx nur die Möglichkeit der Auswahl eines Packers. Wie in Abbildung 28 dargestellt, lassen sich damit keine detaillierteren Einstellungen wählen. 54 Abbildung 28: Einstellungen des ConfuserEx Nachdem der Keylogger mit zwei verschiedenen Tools verschleiert wurde, wurden alle 3 ausführbaren Dateien durch die verschiedenen Virenscanner gejagt. Hier das Ergebnis: Avast erkennt bei der Überprüfung des ursprünglichen Keyloggers als auch bei der mittels „Smart Assembly 6“ durchgeführten Überprüfung eine Bedrohung. Abbildung 29: Avast-Virenscan des originalen Keyloggers Abbildung 30: Avast-Virenscan des mit Smart Assembly 6 verschleierten Keyloggers 55 Bei der Überprüfung des mit ConfuserEx-verschleierten Executables kann Avast jedoch keine Bedrohung feststellen. Abbildung 31: Avast-Virenscan des mit ConfuserEx verschleierten Keyloggers AVG AntiVirus hingegen stuft sowohl den die ursprüngliche als auch beide verschleierten Varianten als Bedrohung ein. Abbildung 32: AVG-Virenscan des originalen Keyloggers Abbildung 33: AVG-Virenscan des mit Smart Assembly 6 verschleierten Keyloggers 56 Abbildung 34: AVG-Virenscan des mit ConfuserEx verschleierten Keyloggers Im Gegensatz dazu erkennen weder die Anti-Viren-Lösungen von Avira noch Kaspersky eine Bedrohung hinter dem verschleierten Keylogger-Varianten. Nur die ursprüngliche Executable-Version wird als Bedrohung erkannt. Abbildung 35 & 36: Avira-Scan des originalen (li.) und des mit Smart Assembly 6 verschleierten (re.) Keyloggers Abbildung 37: Avira-Virenscan des mit ConfuserEx verschleierten Keyloggers 57 Abbildung 38: Kaspersky-Virenscan des originalen Keyloggers Abbildung 39: Kaspersky-Virenscan des Smart Assembly 6 Keyloggers Abbildung 40: Kaspersky-Virenscan des ConfuserEx Keyloggers Bei der Überprüfung mittels virustotal.com wird der originale Keylogger bei 29 von 56 Virenscannern zumindest als Bedrohung erkannt. Bei den meisten Scans wird auch richtig erkannt, um welche Art der Bedrohung es sich handelt. (siehe Abbildung 41) 58 Abbildung 41: Virustotal-Virenscan des originalen Keyloggers Nach der Verschleierung mittels „Smart Assembly 6“ wird der Keylogger nur noch von 9 Virenscannern als Bedrohung eingestuft. Allerdings wird auch nicht mehr erkannt, um welche Bedrohung es sich genau handelt. (siehe Abbildung 42) Abbildung 42: Virustotal-Virenscan des mit Smart Assembly 6 veschleierten Keyloggers 59 Ein ähnliches Bild erkennt man in der Abbildung 43 bei der Überprüfung der mittels ConfuserEx-verschleierten Variante des Keyloggers. Abbildung 43: Virustotal-Virenscan des mit ConfuserEx verschleierten Keyloggers 3.3 Ergebnisse Grundsätzlich ermöglichen sowohl die Verwendung von Cryptern/Packern als auch von Obfuscation Tools die Möglichkeit den Inhalt zu verbergen und eine Analyse zu erschweren. Die Detektionsrate beider Techniken ist dabei abhängig vom verwendeten Produkt als auch von der eingesetzten Anti-Viren-Software. Ob eine verschleierte Anwendung als Bedrohung eingestuft wird oder nicht hängt davon ab, wie die Anti-Viren-Software gepackte Anwendungen behandelt. Eine detailliertere Analyse welcher Typ oder noch genauer welche Anwendung gepackt wurde ist meist nicht umgesetzt. Der Zeitaufwand um solche Tools einzusetzen ist sehr gering. Den meisten Aufwand hat man mit der Suche nach einer entsprechenden Lösung und einer eventuellen Einrichtungszeit. Sobald man diese Initialarbeiten erledigt hat und weiß welche Tools sich für welche Anwendungsgebiete am besten eignen, beschränkt sich der Zeitaufwand auf einige wenige Mausklicks. Die Schwierigkeit bei der Verwendung der Tools hängt stark vom Umfang der mitgebrauchten Funktionen ab. Packer und Crypter lassen sich beispielsweise kinderleicht bedienen. Dabei müssen meist nur eine Eingabedatei, eine Ausgabedatei und einige wenige Parameter gewählt werden, um bereits ansehnliche Ergebnisse zu gewinnen. Will man spezielle Java oder .Net Funktionalitäten verschleiern oder zusätzliche Features nutzen, ist eine gewisse Basis nötig. 60 4 Gegenmaßnahmen Bevor auf die Verteidigungsmechanismen eingegangen wird, soll zuerst noch erläutert werden wie sich Malware heutzutage hauptsächlich verbreitet und wie gut neue Malware von Antivirus Programmen erkannt werden kann. 4.1 Verbreitung von Malware Basierend auf dem Paper „The modern Malware Review“ des Unternehmens Palo Alto Networks aus dem Jahre 2013 [51], bei dem 68.047 Malware Samples (die direkt von Firewalls von Unternehmen stammen) untersucht wurden, ging hervor, dass 68% der Malware über Web-Browsing und 25% der Malware über Email übertragen werden. Von allen Malware Samples, die bei den Unternehmensfirewalls aufschlugen, wurden rund 40% (26.363 Samples) nicht von den 6 führenden Antivirus erkannt. Auffallend dabei ist, dass 90% von diesen 26.363 nicht erkannten Malware Samples über Web-Browsing übertragen wurden, während jedoch nur 2% der unerkannten Samples von Emails stammen. Abbildung 44: Malware Verbreitungsmethoden und zugehörige Erkennungsraten von AVs [51] Und noch ein weiterer signifikanter Unterschied zwischen Web-Browsing und Email Infektionen wird in dem Paper dargelegt: Die, von den 6 führenden AVs unentdeckten Samples, wurden einen Monat lang täglich neu von den Scan Engines der AVs gescannt um festzustellen wie lange es dauert bis die Samples von der Antivirussoftware erkannt werden. Dabei wurde festgestellt, dass Malware, die sich per Email verbreitet im Durchschnitt innerhalb von 5 Tagen erkannt wird, während Malware, die sich anderweitig verbreitet (Web Browsing, Web Applikationen, File Sharing, …) im Durchschnitt 20 Tage lang unentdeckt bleibt. Dabei gab es aber auch etliche Samples die innerhalb des Testzeitraums, von einem Monat, gar nicht von den AVs erkannt wurde. Erklären lässt sich der Unterschied bei den Detektionsraten zwischen den beiden Infektionsmethoden Web-basiert und Email-basiert folgend: 61 1. Web-Browsing und Web-basierte Applikationen sind Echtzeit-Anwendungen, während es bei Emails meist keinen Unterschied macht ob die Mails innerhalb von einer Sekunde oder einer halben Minute vom Webserver zum Empfänger weitergeleitet werden. Das heißt also während bei Mails am Server dem AVProgrammen genügend Zeit bleibt um die einzelnen Dateien zu analysieren, müssen bei Web-basierden Anwendungen die Detektion und Entscheidungen innerhalb kürzester Zeit von statten gehen. 2. Der zweite und schwerwiegendere Grund ist, dass sich Malware, die über Webbasierte Anwendungen verteilt wird, die sich serverseitige Polymorphie zu Nutze machen kann. Das heißt einfach, dass der Server die Malware automatisiert abändert (durch Packer, andere Verschlüsselungsparameter, Obfuscation), sodass jede Malware-Instanz wirkt als wäre sie einzigartig. Dadurch werden viele verschiedenartige Malware-Samples erstellt, was die Wahrscheinlichkeit deutlich verringert, dass ein Sample von einem AV-Hersteller eingefangen wird und dieser eine Signatur vom dem Sample erstellen kann um seine Kunden zu schützen. Untersucht wurde weiters aus welchen Quellen die Malware stammt, die am längsten unbekannt bleibt und am zielgerichtetsten ist. Dabei vielen vor alle Filesharing Webseiten, wie 4shared, dropbox, netload, rapdishare, ... und Social Media, wie facebook, instagram, teachertube, … auf, aber auch das File Transfer Protocol ist in dieser Kategorie stark vertreten. So wurden 94% aller FTP-Samples nur ein einziges Mal eingefangen und 95% der FTP-Samples wurden nicht von den AV-Programmen erkannt. Es scheint also als würde FTP intensiv für sogenannte „high sophisticated attacks“, also hoch komplexe und zielgerichtete Angriffe auf Unternehmen (z.B. zur Industriespionage), verwendet werden. Abbildung 45: Zeitraum, wie lange Malware unentdeckt bleibt, aufgeschlüsselt auf die Infektionsquellen [51] 62 4.2 Verteidigungsmaßnahmen Die Verteidigungsmaßnahmen gegen herkömmliche Malware und zielgerichtete (Industrie-) Spionage (Advanced Persistent Threat, APT) können unterteilt in präventive Maßnahmen und solchen zur nachträglichen Detektion. Dabei wirken vor allem Anti-Exploit Techniken als präventive Maßnahmen als äußert interessant. Nachfolgende Sicherheitsmaßnahmen wurden durch ein Brain-Storming der Autoren erhoben und um die Vorschläge aus dem „The modern Malware Review“ [51] erweitert (diese sind gekennzeichnet). Präventiv Antivirus (AV) Obwohl in dieser Arbeit gezeigt wurde wie einfach es ist verschiedene AV-Scanner auszutricksen und erwähnt wurde, dass rund 40% der sich im Umlauf befindlichen (neuen) Malware nicht erkannt wird, stellt ein Antivirus einen Basisschutz dar und sollte auf jedem Rechner installiert sein. Mit der Auswahl des besten Antivirus beschäftigen sich mehrere Webseiten (zB. http://www.av-test.org/), wobei sehr oft ein Kompromiss aus Geschwindigkeit und Detektionsrate getroffen werden muss. Für Unternehmen ist es wiederum wichtig, dass die AV-Software von zentraler Stelle aus gesteuert und mit Updates der Virendatenbanken versorgt werden kann. Weiters soll es den Mitarbeitern nicht möglich sein können den Antivirus deaktivieren zu können. Firewalls und Intrusion Prevention Systeme (IPS) Auch eine Firewall gehört ähnlich wie das Antivirus zum präventiven Basisschutz eines Unternehmens. Welche Firewall(s) und Firewall-Architektur auch immer verwendet werden, wichtig ist, dass die Konfiguration von Experten vorgenommen und regelmäßig überprüft wird. Mit einem IPS kann zusätzlich der Netzwerk-Traffic auf verdächtiges Verhalten hin untersucht werden und kann bei einer Detektion den verdächtigen Datenstrom blockieren. Die Erkennung erfolgt dabei signaturbasiert, mittels Detektion von statistischen Anomalien (zB. wenn plötzlich ein neues Protokoll im Netzwerk verwendet wird) und mittels zustandsbehafteter Analyse von Protokollen. Die Autoren empfehlen auf jeden Fall auch eine Next Generation Firewall zu verwenden (Applikationsfilter mit Deep Packet Inspection und IPS integriert) um erkennen zu können ob ein Protokoll und freigegebener Port (zB. 80, 443, …) von einer Malware für bösartige Zwecke missbraucht wird. Anti-Exploit Techniken Wie schon behandelt geschehen die häufigsten Infektionen entweder über Emails oder über Web Browsing. Damit die Infektion jedoch wirklich von statten geht, muss 63 der Schadcode erst ausgeführt werden. Das heißt, dem Opfer einfach eine Exe- oder Jar-Datei zu senden reicht nicht aus um seinen Rechner schon zu infizieren. Der Empfänger muss erst die ausführbare starten damit der Schadcode seine Wirkung entfalten kann. Dasselbe gilt natürlich auch für ausführbare Dateien aus dem Internet. Als Gegenmaßnahmen werden ausführbare Dateien meist von einem Anhangfilter des Mailservers aus den Emails entfernt. Weiters wissen die meisten Mitarbeiter, dass sie eine Exe-Datei, die sie per Email erhalten oder die einfach beim Öffnen einer Seite heruntergeladen wird, nicht öffnen sondern löschen sollten. Natürlich sollten diese von der IT-Abteilung des Unternehmens auch entsprechend geschult werden. Eine Möglichkeit wäre nun zu versuchen den Benutzer zu täuschen. Das kann einerseits dadurch gemacht werden, dass der ausführbaren Datei besondere Namen gegeben werden, wie „Geheime Dokumente“ oder „AngryBirdsForPC“, die zur Ausführung verleiten sollen, oder andererseits durch Trojaner. Ein Mitarbeiter sucht zum Beispiel nach einem PDF-To-Word Konverter und wird im Internet auf einer vertrauenswürdig aussehenden Seite fündig. Er lädt sich diesen herunter, installiert diesen (dafür werden natürlich Admin-Rechte angefordert ) und verwendet ihn. Dieser funktioniert zwar einwandfrei, was er aber nicht mitbekommt ist, dass im Hintergrund sich schon eine Malware auf seinem PC eingenistet hat. Die dritte Möglichkeit sind Exploits. Diese wurden bereits ausführlich in diesem Dokument behandelt. Der Vorteil dabei ist, dass die Malware nicht in einer ausführbaren Datei implementiert ist, sondern sich in einer unscheinbaren Datei (PDF, Word, Excel, HTML, Flash, …) verstecken kann. Dabei ist es sehr oft nicht einmal notwendig, dass der Benutzer die Datei aktiv öffnet. Hat dieser zum Beispiel den Flash Player aktiviert und dieser hat eine ungepatchte Vulnerabilität und er surft eine präparierte Webseite an, so kann diese ein verstecktes Flash-Video abspielen und die Schwachstelle ausnutzen ohne dass der User überhaupt mitbekommt das die Webseite seinen Flash-Player verwendet hat. Und laut der bereits in Kapitel 2.1 erwähnten Studie von Malwarebytes [18], basieren heutzutage bereits 90% aller Angriffe auf Exploits. Das Problem dabei: Antivirus-Programme können meist erst dann eingreifen, wenn eine Schachstelle in einem Programm bereits ausgenutzt wurde und der Exploit Payload (also die Malware) auf den Computer übertragen wurde. Aus diesem Grund gibt es sogenannte Anti-Exploit Programme, die versprechen, dass Schwachstellen in Programmen (wie zB. ein Buffer-Overflow) von Exploits nicht mehr ausgenützt werden können. Dabei gibt es mehrere verschiedene Programme, die verschiedene Techniken verwenden: Microsoft’s Enhanced Mitigation Experience Toolkit (EMET) Verwendet verschiedene Techniken, wie DEP, ASLR, SEHOP, HeapSpray, Null page Allocations, EAF, Basic ROP mitigations um es Exploits schwerer zu machen stabil auf mehreren, verschiedenen System zu laufen. 64 Abbildung 46: GUI von MS EMET Die Features von EMET müssen explizit für jedes gewünschte Programm aktiviert werden. Dabei gestaltet sich die Verwendung des Tools als sehr einfach und intuitiv. Um einen Prozess zu schützen muss man einfach nur einen Rechtsklick auf diesen machen und auf „Configure Process“ klicken. Per Default werden dann gleich alle möglichen Schutzmechanismen für den Prozess aktiviert (nach Neustart des Systems): 65 Abbildung 47: App – Sicherheitsmechanismus – Matrix von EMET Obendrauf ist EMET auch noch kostenlos verfügbar. Doch EMET hat auch ein paar Schwachstellen: Kein Schutz mehr wenn diese Techniken umgangen werden können. Kein Schutz gegen Java Exploits (Sandbox Escape) Techniken sind zu generisch Bypass ist unter Umständen möglich Konflikte mit älteren Applikationen Invincea o Verwundbare und fehlanfällige Programme laufen in einer Sandbox Exploits können am Zielsystem keinen Schaden anrichten Bei einer Infektion wird einfach der Container beendet und damit auch der Exploit-Payload Benutzer müssen sich daran gewöhnen und geschult werden wie sie mit dem Browser umzugehen haben Teuer (mehr als 45$ pro Benutzer) Malwarebytes ANTI Exploit Verwendet eine 3-Schichten Architektur: Layer3: Applikationsverhalten & Applikationsüberwachung Layer2: Malicious Memory Blocker Verhindert Payload-Ausführung am Heap, Stack Layer1: OS Bypass Protection Ähnlich wie EMET + zusätzliche Techniken 66 Austausch zwischen den Layern Schutz gegen APTs Proaktive Techniken, kein Whitelisting, Sandboxing, Signaturen, VMs Nur 3MB groß und kompatibel mit alten Betriebssystemen Keine Benutzerinteraktion bzw. Management notwendig Kann alle möglichen Applikationen schützen Auch als Free-Edition für alle Browser + Add-ons und Java erhältlich In diesem Test [52] von PC Security Labs vom August 2014 kann verglichen werden wie MS EMET und Malwarebytes Anti Exploit in Vergleich zu den Top-Virenscannern bei der Erkennung und dem Schutz vor Exploit abgeschnitten haben. Dabei konnte das Tool Anti Exploit Premium als Testsieger beachtliche 93,1% aller Exploits erkennen und eine Infektion verhindern. Doch auch Norton Internet Security (81%), MS EMET (74,1%), Kaspersky Internet Security (72,4%), avast! Internet Security (72,4%) und ESET Smart Security (70,7%) erreichten noch gute Ergebnisse. Zusammengefasst kann gesagt werden, dass Anti-Exploit Tools eine sehr gute Gegenmaßnahme gegen Exploits und somit gegen eine Malware-Infektion darstellen. Auch die Antivirus-Hersteller wie Kaspersky und Norton haben in ihren Internet Security Produkten bereits Anti-Exploit Techniken integriert. Diese können zusammen mit dem Antivirus erworben werden und stellen somit einen guten Basisschutz dar. Nachteilig an dem Konzept ist, dass eine solche Software einen zusätzlichen Layer einführt, der in die Trusted Computing Base mitaufgenommen werden muss, die Komplexität des Systems weiter erhöht und eine weitere Angriffsmöglichkeit darstellt, falls sich Fehler bei der Erstellung des Anti-ExploitToolkits eingeschlichen haben. Zentrale Softwareverwaltung, Software Updates und deaktivieren/deinstallieren von fehlerbehafteter Software Mitarbeiter im Unternehmen sollten sich nicht nach Belieben Software herunterladen und installieren können. Die verwendeten Programme sollten zuerst von den ITExperten eingehend geprüft werden auf bekannte Schwachstellen oder zusätzliche Schädliche Funktionalitäten (Trojaner). Nach der Prüfung eines Programms wird dieses den Mitarbeitern über ein sogenanntes Software Deployment Tool zur Verfügung gestellt. Über dieses Tool kann die IT-Abteilung dann weiters regelmäßige Updates der verwendeten Software auf allen Rechnern einspielen und Software, die als unsicher gilt deaktivieren bzw. deinstallieren. So könnte zum Beispiel der Adobe Flash Player vorübergehend deaktiviert werden, wenn wieder einmal ein (oder mehrere) Zero Day Exploits für diesen gefunden werden. Eine besondere Gefahr stellt Software dar, die von Mitarbeitern des Unternehmens selbst programmiert wurde und den anderen Mitarbeitern auf Unternehmensservern 67 zur Verfügung gestellt wird. Diese umgeht damit die Software Deployment Lösung und die IT-Abteilung weiß oftmals nicht einmal, welches verschiedenen selbst geschriebenen Programme auf den Rechnern der Mitarbeiter installiert sind. Das Problem dabei ist, dass diese Software oft nicht mit Bedacht auf Sicherheitsaspekte programmiert und nur nebenbei und mit möglichst wenig Aufwand (als Prototyp) erstellt wurde. Auch Updates können keine erwartet werden. Dient die Software dazu um auf Datenbanken zuzugreifen, so müssen Mitarbeiter oft ihre Credentials dem Tool zur Verfügung stellen, wobei niemand Einblick hat was genau die Software mit den Passwörtern macht (zum Beispiel in Plaintext irgendwo ablegen). Weiters können Fehler in der Software zu schwerwiegenden Konsequenzen führen, wenn zum Beispiel wichtige Datensätze unbeabsichtigter Weise gelöscht werden. Aus diesen Gründen sollte unternehmensintern programmierte Software auch immer mit der IT Abteilung abgestimmt werden und ebenfalls über das zentrale Software Deployment Tool verteilt werden. Eine weitere gute Möglichkeit ist es den Mitarbeitern Zugriff auf virtuelle Maschinen zu geben, die auf Unternehmensservern gehostet werden (zB: Citrix XenDesktop) und alle benötigten Programme bereits installiert haben. Auf diese Art und Weise kann auch sichergestellt werden, dass geheime Dokumente nicht auf Laptops landen, sondern in den virtuellen Maschinen am Unternehmensserver. Auch der externe Zugriff über eine mobile Internetverbindung und ein VPN können somit perfomanter sein, da die Daten nicht auf den Laptop heruntergeladen werden müssen und der Laptop nur als graphische Oberfläche dient. Verwenden von VPNs Firmen-Notebooks sollten sich mit dem Internet nur über ein verschlüsseltes VPN verbinden können. Dadurch wird sichergestellt, dass der gesamte Internet-Traffic für Dritte nicht einsehbar über Unternehmens-Server läuft und der Traffic wiederum von IDS, IPS, Next-Generation Firewalls und weiterer Sicherheitssoftware geprüft werden kann. Rechte Einschränkungen Jeder Mitarbeiter sollte ein Benutzerkonto ohne Administrator-Rechte besitzen. Dadurch wird verhindert, dass Malware bei einer Infektion sofort Admin-Rechte hat. Wie schon im vorherigen Punkt erwähnt sollte Software automatisiert über eine Software Deployment Lösung (zB: WPKG) installiert und upgedatet werden, welches auf jeden Rechner Systemrechte besitzt. Es gibt auch die Möglichkeit bestimmten Benutzern temporär (zum Beispiel für eine Stunde) Administratorrechte zu gewährleisten. 68 Weiters sollte sich ein Mitarbeiter natürlich nicht nach Belieben im Unternehmensnetzwerk „bewegen“ können und auf jeden Server im Netzwerk Zugriff haben. Auch das Recht Dateien auf einem Computer im Netzwerk freizugeben sollte nicht erlaubt werden. Dies ist vor allem kritisch, wenn Mitarbeiter sich mit externe WLANs verbinden. Oft kommt es auch vor, dass bei Rechnern, die von mehreren Benutzern gemeinsam verwendet werden (zum Beispiel in einem Labor oder auf speziellen Testrechnern) von den Mitarbeitern ein „Gemeinschaftskonto“ angefordert wird, bei dem jeder Mitarbeiter die Credentials kennt und somit problemlos die Session eines anderen übernehmen kann. Hintergrund dafür ist oft einfach nur Bequemlichkeit, da es zum Beispiel vorkommt, dass mehrere Personen abwechselnd denselben Rechner verwenden müssen oder jemand sich schlichtweg vergisst aus zu loggen. Da dadurch jedoch jegliche Möglichkeit verloren geht nachzuvollziehen welcher Mitarbeiter was im Netzwerk gemacht hat sollte dies strikt untersagt werden. So könnten solche Benutzerkonten und Rechner zum Beispiel Ausgangspunkt für interne Angriffe sein oder dazu dienen per Key-Logger die Credentials anderer Mitarbeiter zu sammeln, wenn diese sich zum Beispiel auf Datenbanken oder auf Webseiten einloggen. URL und Content Blocking Wie schon im vorherigen Kapitel erläutert, ist die Nummer 1 Infektionsquelle das Web-Browsing. Blockieren von Webseiten, die bekannt dafür sind, dass Malware über diese verteilt wird, wie zum Beispiel File-Sharing Webseiten, Pornographische Webseiten, Hacking Webseiten, … Blockieren des Downloads von ausführbaren Dateien Blockieren des Senden und Empfangen von ausführbaren Dateien in Emails Zugriffsrechte auf unbekannte, neu registrierte und dynamische DNS Domänen einschränken [51] Laut [51] verbinden sich 33% der Malware Samples entweder zu einer neu registrierten Domäne oder verwenden dynamisches DNS oder Fast Flux. Aus diesem Grund sollte für solche Domänen härtere Sicherheitskontrollen und Zugriffsrechte gesetzt werden, wie zum Beispiel das Verbieten des Downloads von ausführbaren Dateien, blockieren von HTTP-Post-Requests oder das Entschlüsseln von SSL Traffic um diesen inspizieren zu können. 69 Email Traffic nur auf den Unternehmens Email-Server erlauben [51] Laut [51] verwenden 20% der Malware Samples direkte Email-Verbindungen über das Netzwerk ohne einen Mailserver zu verwenden (siehe zum Beispiel das Tool „sendMail“). Aus diesem Grund sollten die Firewall-Policies so eingestellt sein, dass die Email-Protokolle nur von und zum Email-Server übermittelt werden dürfen und der direkte Email-Verkehr mit dem Internet blockiert wird. Kontrollen für Web-Applikationen mit denen Dateien übertragen werden können [51] Unternehmen sollten die möglichen Angriffspunkte mit Hilfe von Benutzer- und Applikationskontrollen möglichst gering halten. So sind beispielsweise Http-Proxies gängige Quellen für Malware. Es sollte also sichergestellt werden, dass nur die Unternehmens-Proxy-Server von den Benutzern verwendet werden können und nicht eigene Web-Proxies mit denen die Sicherheitsrichtlinien des Unternehmens umgangen werden können. Bei Social Media können zum Beispiel die Dateiübertragungsmechanismen stark eingeschränkt werden, damit Malware über diese Quellen nicht so einfach ins Firmennetzwerk gelangen kann. Mitarbeiter sensibilisieren und Ausgabe von Security-Richtlinien Mitarbeiter, egal welcher Art (mit technischem Hintergrund, aus dem Management, IT Neuling, …) sind die Benutzer des Systems und damit meist auch der Grund, dass Malware überhaupt den Weg ins Unternehmensnetzwerk schafft. Aus diesem Grund gehören Mitarbeiter geschult und sensibilisiert auf die möglichen IT Bedrohungen inklusive Social Engineering. Den Autoren gefällt die Idee gut, einer zentralen, unternehmensinternen Webseite, auf der Security-Richtlinien und Verhaltensweisen in verdächtigen Situationen beschrieben werden und fürs Unternehmen wichtige Security-News von den Sicherheitsexperten im Unternehmen gepostet werden. Weiters sollte es die Möglichkeit eines öffentlichen Pinboards geben, auf der Mitarbeiter Fragen hinterlassen können und alle anderen Besucher der Seite die entsprechenden Antworten zu sehen bekommen. Zu den Sicherheitsrichtlinien können zum Beispiel folgende Punkte gehören: Kein verwenden von (unbekannten) USB-Geräten Sichere Passwörter (zB. Anfangsbuchstaben eines Satzes mit mehr als 10 Worten) verwenden und diese nirgendwo aufschreiben Kein Öffnen eines unbekannten Email-Anhangs Kein Surfen auf verdächtigen Webseiten – Aufklärung was verdächtige Webseiten sind Kein Download von ausführbaren Programmen (jar, exe, com, bat, …) Computer immer Sperren, wenn nicht am Platz Laptops am Abend versperren und nicht im Fahrzeug sichtbar liegen lassen 70 Detektion Verwenden von Anti-Malware-Technologien im Netzwerk [51] Bisher wurden Anti-Malware-Technologien vorwiegend am Desktop eingesetzt. Da durch die Verlagerung der Infektionsmethoden auf Web-basierte Anwendungen, Echtzeit-anforderungen an die Detektion von Malware hinzukommen, müssen neue Ansätze gefunden werden um Malware schneller zu erkennen und zu blockieren. Dies kann zentral auf Servern auf Netzwerk-Ebene gemacht werden. NextGeneration Firewalls und Intrusion Detection Systeme (IDS) gehören zu dieser Kategorie. Erstellen und ständiges überarbeiten einer soliden Ausgangsbasis (Referenz) [51] Sehr oft zeigt Malware ein anormales Verhalten. Dieses kann als Referenz verwendet werden um neuartige und unerkannte Malware im Netzwerk sehr schnell als solche zu identifizieren. Untersuchen und beseitigen von „unknown Traffic“ [51] Einer der größten Gemeinsamkeiten von verschiedener Malware ist die Verwendung von „customized“ oder „unknown“ Traffic. So werden sehr häufig „well-known“ Ports und Protokolle für die Schadprogramm-Zwecke angepasst (zB. http, DNS, Instant Messaging und Remote Desktop Protokolle, usw.). Mit Hilfe einer Next-Generation Firewall kann ein solcher angepasster oder unbekannter Traffic relativ einfach identifiziert werden. Schon beim Erstellen der Ausgangsbasis im Netzwerk, sollte jeglicher unbekannter oder angepasster Traffic identifiziert und analysiert werden. Auf diese Art und Weise kann neuer unbekannter Netzwerk-Traffic sehr schnell analysiert und neue Malware identifiziert werden. Für Antivirus unbekannte Malware erwarten und identifizieren [51] Durch Methoden wie serverseitige Polymorphie gibt es immer häufiger MalwareSamples die von Antivirus-Programmen nicht erkannt werden können. Um festzustellen ob unbekannte Dateien bösartiger Natur sind müssen diese in einer gesicherten Umgebung ausgeführt und die eventuell implementierte Wartezeit der Malware abgewartet werden. Es wird an dieser Stelle ein automatischer Mechanismus gebraucht, der in große Netzwerke implementiert werden kann um festzustellen ob sich die Datei schädlich verhält. 71 5 Zusammenfassung In dieser Arbeit wurden verschiedene Code Obfuscation Techniken wie Komprimierung, Verschlüsselung, Virtualisierung, Data Obfuscation und Control Flow Obfuscation gezeigt und erläutert. Basierend darauf wurde darauf eingegangen welche dieser Techniken sich moderne Malware zu Nutze macht und wie Antivirus-Programme versuchen trotz der Verschleierungstechniken Viren zu erkennen. Für die Autoren war dabei erschreckend, dass Techniken, wie Polymorphie und Metamorphie eigentlich schon in den frühen 90er Jahren von Malware eingesetzt wurden und aktuell (Jänner 2015) noch immer verwendet werden können um AV-Programme auszutricksen. Diese theoretische Recherche wurde im Proof of Concept überprüft, indem zwei verschiedene Malware-Programme mit Hilfe von frei verfügbaren Obfuscation Tools verschleiert und einer anschließenden Antivirus-Prüfung unterzogen wurden. Das Ergebnis war dabei, aus Sicht eines böswilligen Angreifers, gut. Denn die Verschleierungstechniken konnten einfach mittels weniger Mausklicks ausgeführt werden und zeigten eine gute Wirkung gegen die meisten AV-Programme. Bestätigt wird dies umso mehr durch diverse Studien (wie zum Beispiel in [51]), aus denen hervorgeht, dass 40% der sich im Umlauf befindlichen Malware Samples nicht von den 6 Top AV-Programmen erkannt werden (weder durch Signaturen noch durch Heuristiken) und es um die 20 Tage dauert bis diese Malware Samples dann endlich detektiert werden können (sofern die Anzahl der infizierten Hosts groß genug ist). Für die Autoren ist diese Tatsache vor allem in Bezug auf gezielte Angriffe auf einzelne Unternehmen (Industriespionage) kritisch. Denn da anscheinend die AV-Heuristiken Malware nicht sehr gut erkennen können und AV-Signaturen nur effektiv sind, wenn das spezifische Malware-Sample vom AV-Hersteller eingefangen wird, sind Antivirus-Programme gegen gezielte Angriffe machtlos. Der Angreifer muss nur eine bereits bekannte Malware bzw. ein Exploit Kit hernehmen, diese mit frei verfügbaren Tools verschleiern und die Malware entweder über einen Exploit, Email, USB-Stick oder sonstigen Weg auf einen Firmenrechner bringen. Da es sich bei der verschleierter Malware um ein Einzelstück handelt ist die Wahrscheinlichkeit einer Erkennung mittels einem AV-Programm gleich Null. Von dem infizierten Rechner aus, können dann weitere Angriffe gegen die unternehmensinterne Infrastruktur (z.B. Portscan) durchgeführt werden. Um zu zeigen, dass es durchaus möglich ist erfolgreich gezielte Angriffe abzuwehren, wurden abschließend mehrere präventive als auch erkennende Maßnahmen angeführt. Diese verdeutlichen, auf welche vielsichtige Art und Weise sich Unternehmen vor Angriffen schützen müssen um ein akzeptables Level an IT-Sicherheit gewährleisten zu können. Ob diese Maßnahmen wirksam vor Industriespionage schützen, hängt letztendlich von den ausführenden und kontrollierenden IT-Experten und den Mitarbeitern des Unternehmens ab. Denn der Mensch und sein Streben nach Einfachheit und Komfort ist und bleibt für die Autoren die größte Schwachstelle im Punkto IT-Sicherheit. 72 6 Future Work Während in dieser Arbeit stark der Fokus auf Code Obfuscation gelegt wurde, sollen in der nächsten Arbeit (im 2. Semester des Masterstudiengangs Informationsmanagement und Computersicherheit) Exploit Generatoren wie zum Beispiel Angler EK, Styx Ek, RIG Ek, Magnitude Ek, usw. in Vordergrund stehen. Diese könnten mit Bezug auf Funktionalität und Effektivität miteinander verglichen werden. Vorschlag der Autoren wäre es, als praktischen Teil eine Webseite zu hosten (eventuell offline ), die einen solchen Exploit Generator nutzt um in Rechner einzudringen und bösartige Software darauf zu installieren. Dabei soll die Malware zuvor mit Hilfe von serverseitiger Polymorphie oder serverseitiger Metamorphie verschleiert werden, sodass jeder Besucher der Webseite mit einer individuellen Instanz der Malware infiziert wird. 73 Literaturverzeichnis [1] „Wikipedia (Exploits),“ Wikimedia Foundation Inc, [Online]. Available: https://de.wikipedia.org/wiki/Exploit. [Zugriff am 20 12 2014]. [2] „people4.net,“ people4.net GmbH, [Online]. Available: http://www.people4.net/was-bedeutetder-begriff-exploit. [Zugriff am 20 12 2014]. [3] C. Evans, „Project Zero,“ Google, 15 07 2014. [Online]. Available: http://googleonlinesecurity.blogspot.co.at/2014/07/announcing-project-zero.html. [Zugriff am 20 12 2014]. [4] R. Eikenberg, „Heise Security,“ Heise Zeitschriften Verlag GmbH & Co. KG, 04 06 2013. [Online]. Available: http://www.heise.de/security/meldung/Google-Forscher-veroeffentlichtZero-Day-Exploit-fuer-Windows-1875749.html. [Zugriff am 27 12 2014]. [5] R. Eikenberg, „Heise Security,“ 13 5 2013. [Online]. Available: http://www.heise.de/security/meldung/Google-verkuerzt-Schonfrist-fuer-Herstellerverwundbarer-Software-1873727.html. [Zugriff am 15 12 2014]. [6] „Wikipedia (Responsible Disclosure),“ [Online]. Available: https://en.wikipedia.org/wiki/Responsible_disclosure. [Zugriff am 15 12 27]. [7] B. Fung, „The Washington Post,“ 31 August 2013. [Online]. Available: http://www.washingtonpost.com/blogs/the-switch/wp/2013/08/31/the-nsa-hacks-othercountries-by-buying-millions-of-dollars-worth-of-computer-vulnerabilities/. [Zugriff am 20 12 2014]. [8] A. Meister, „Netzpolitik,“ 15 Dezember 2014. [Online]. Available: https://netzpolitik.org/2014/vupen-threat-protection-wir-veroeffentlichen-den-vertrag-mit-demdas-bsi-sicherheitsluecken-und-exploits-kauft/. [Zugriff am 21 Dezember 2014]. [9] „Der Spiegel,“ 09 November 2014. [Online]. Available: http://www.spiegel.de/spiegel/vorab/bnd-will-informationen-ueber-softwaresicherheitsluecken-einkaufen-a-1001771.html. [Zugriff am 27 Dezember 2014]. [10] B. M. C. G. &. J. S.-R. Morgan Marquis-Boire, „CitizenLab,“ 30 April 2013. [Online]. Available: https://citizenlab.org/2013/04/for-their-eyes-only-2/. [Zugriff am 20 Dezember 2014]. [11] „Twitter,“ 08 August 2014. [Online]. Available: https://twitter.com/gammagrouppr. [Zugriff am 22 Dezember 2014]. 74 [12] „Wikileaks,“ 15 September 2014. [Online]. Available: https://wikileaks.org/spyfiles4/index.html. [Zugriff am 22 Dezember 2014]. [13] A. Meister, „Netzpolitik,“ 05 August 2014. [Online]. Available: https://netzpolitik.org/2014/gamma-finfisher-twitter-account-veroeffentlicht-interne-dokumenteueber-weltweit-eingesetzten-staatstrojaner/. [Zugriff am 22 Dezember 2014]. [14] A. Meister, „Netzpolitik,“ 06 August 2014. [Online]. Available: https://netzpolitik.org/2014/gamma-finfisher-gehackt-werbe-videos-von-exploits-und-quelltextvon-finfly-web-veroeffentlicht/. [Zugriff am 22 Dezember 2014]. [15] C. Team, „Corelan Team,“ 19 Juli 2009. [Online]. Available: https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-basedoverflows/. [Zugriff am 25 Dezember 2014]. [16] D. Hoelzer, „Cyber Defense,“ [Online]. Available: http://www.cyberdefense.org/Blog/files/e6fb7327cb615688f90fc07656a3880d-28.html. [Zugriff am 25 Dezember 2014]. [17] O. Security, „Offensive Security - Metasploid Unleashed,“ 2014. [Online]. Available: http://www.offensive-security.com/metasploit-unleashed/Main_Page. [Zugriff am 25 Dezember 2014]. [18] „Youtube (Malware Bytes Webinar),“ 4 August 2014. [Online]. Available: https://www.youtube.com/watch?v=fRxRp2x_jNU. [Zugriff am 30 Jänner 2015]. [19] „ssware,“ LogicNP Software, [Online]. Available: http://www.ssware.com/articles/protect-andobfuscate-your-dotnet-code-against-reverse-engineering-using-crypto-obfuscator.htm. [Zugriff am 02 Jänner 2015]. [20] „Wikipedia (Obfuscator),“ [Online]. Available: https://de.wikipedia.org/wiki/Obfuscator. [Zugriff am 02 Jänner 2015]. [21] „Wikipedia (Obfuscation),“ [Online]. Available: https://en.wikipedia.org/wiki/Obfuscation. [Zugriff am Jänner 02 2015]. [22] „Wikipedia (Interpreter),“ [Online]. Available: https://de.wikipedia.org/wiki/Interpreter. [Zugriff am 01 Jänner 2015]. [23] D. Bolton, „About Tech,“ [Online]. Available: http://cplus.about.com/od/introductiontoprogramming/a/compinterp.htm. [Zugriff am 01 Jänner 2015]. 75 [24] „Stunnix,“ [Online]. Available: http://www.stunnix.com/prod/cxxo/newsample.shtml. [Zugriff am 02 Jänner 2015]. [25] „University of Florida,“ [Online]. Available: https://www.cise.ufl.edu/~manuel/obfuscate/obfuscate.html. [Zugriff am 05 Jänner 2015]. [26] S. Taylor, „Defcon 17 (Binary Obfuscation),“ August 2009. [Online]. Available: https://www.defcon.org/images/defcon-17/dc-17-presentations/defcon-17-sean_taylorbinary_obfuscation.pdf. [Zugriff am 20 Jänner 2015]. [27] A. Binstock, „Destination.NET,“ 06 März 2003. [Online]. Available: http://web.archive.org/web/20080420165109/http://www.devx.com/microsoftISV/Article/11351. [Zugriff am 01 Jänner 2015]. [28] mdownen, „MSDN Blogs,“ Microsoft, 26 Mai 2005. [Online]. Available: http://blogs.msdn.com/b/clrsecurity/archive/2005/05/26/422440.aspx. [Zugriff am 02 Jänner 2015]. [29] „Wikipedia (Android Lollipop),“ [Online]. Available: https://en.wikipedia.org/wiki/Android_Lollipop. [Zugriff am 02 Februar 2015]. [30] „Wikipedia (Dalvik),“ [Online]. Available: https://en.wikipedia.org/wiki/Dalvik_%28software%29. [Zugriff am 02 Februar 2015]. [31] „Wikipedia (Android Runtime),“ [Online]. Available: https://en.wikipedia.org/wiki/Android_Runtime. [Zugriff am 02 Februar 2015]. [32] „Wikipedia (JavaScript),“ [Online]. Available: https://de.wikipedia.org/wiki/JavaScript. [Zugriff am 2015 Jänner 26]. [33] „Wikipedia (Minification),“ [Online]. Available: https://en.wikipedia.org/wiki/Minification_%28programming%29. [Zugriff am Jänner 28 2015]. [34] R. Abrams, „WeLiveSecurity (Packers),“ 27 October 2008. [Online]. Available: http://www.welivesecurity.com/2008/10/27/an-introduction-to-packers/. [Zugriff am 20 Jänner 2015]. [35] M. M. Tom Brosch, „Black Hat Briefings (Runtime Packers),“ AV-Test GmbH, 2006. [Online]. Available: https://www.blackhat.com/presentations/bh-usa-06/BH-US-06-Morgenstern.pdf. [Zugriff am 15 Jänner 2015]. [36] R. R. B. Gabriel Negreira Barbosa, „Black Hat USA 2014,“ 2014. [Online]. [Zugriff am 25 76 Jänner 2015]. [37] „Wikipedia (UPX),“ [Online]. Available: https://de.wikipedia.org/wiki/UPX. [Zugriff am 20 Jänner 2015]. [38] Y. G. &. A. Gazet, „metasm (08),“ 2008. [Online]. Available: http://metasm.cr0.org/docs/sstic08-metasm-jcv.pdf. [Zugriff am 20 Jänner 2015]. [39] Y. G. &. A. Gazet, „metasm (09),“ 2009. [Online]. Available: http://metasm.cr0.org/docs/sstic09-metasm-jcv.pdf. [Zugriff am 20 Jänner 2015]. [40] „Wikipedia (Schadprogramm),“ [Online]. Available: https://de.wikipedia.org/wiki/Schadprogramm. [Zugriff am 25 Jänner 2015]. [41] C. Eckert, Oldenbourg Wissenschaftsverlag GmbH, 2013. [Online]. [42] L. Böhne, 28 Jänner 2008. [Online]. Available: http://2012.hack.lu/archive/2009/PandorasBochs.pdf. [Zugriff am 01 Februar 2015]. [43] W. Chen, „Rapid 7,“ 05 Jänner 2014. [Online]. Available: https://community.rapid7.com/community/metasploit/blog/2014/01/05/a-cat-and-mouse-gamebetween-exploits-and-antivirus. [Zugriff am 30 Jänner 2015]. [44] „Wikipedia (Oligomorphic Code),“ [Online]. Available: https://en.wikipedia.org/wiki/Oligomorphic_code. [Zugriff am 30 Jänner 2015]. [45] „Wikipedia (Polymorphic Code),“ [Online]. Available: https://en.wikipedia.org/wiki/Polymorphic_code. [Zugriff am 25 Jänner 2015]. [46] P. Szor, The art of computer virus research and defence, Symantec Press, 2005. [47] „Wikipedia (Hidden Markov Model),“ [Online]. Available: https://de.wikipedia.org/wiki/Hidden_Markov_Model. [Zugriff am 15 Jänner 2015]. [48] „Wikipedia (Metamorphic Code),“ [Online]. Available: https://en.wikipedia.org/wiki/Metamorphic_code. [Zugriff am 15 Jänner 2015]. [49] D12d0x34X, „INFOSEC Institute,“ [Online]. Available: http://resources.infosecinstitute.com/anti-debugging-and-anti-vm-techniques-and-antiemulation/. [Zugriff am 06 Februar 2015]. [50] „ITLaw,“ [Online]. Available: http://itlaw.wikia.com/wiki/Virus_obfuscation_techniques. [Zugriff 77 am 01 Jänner 2015]. [51] „Palo Alto Networks,“ 2013. [Online]. Available: http://media.paloaltonetworks.com/documents/The-Modern-Malware-Review-March-2013.pdf. [Zugriff am 09 Jänner 2015]. [52] „Malwarebytes Anti Exploit,“ PC SECURITY LABS, August 2014. [Online]. Available: http://static-cdn.malwarebytes.org/assets/datasheets/2015-02-06/RCEMitigations.pdf. [Zugriff am 30 Jänner 2015]. [53] „Wikipedia (.NET Framework),“ [Online]. Available: https://en.wikipedia.org/wiki/.NET_Framework. [Zugriff am 2015 Jänner 01]. 78 Abbildungsverzeichnis Abbildung 1: Darstellung eines Buffer Overflow ..................................................................11 Abbildung 2: Common Language Infrastructure (CLI) [27] ..................................................19 Abbildung 3: Einfaches C++ Beispiel mit einer globalen Variable und zwei Funktionen, .....21 Abbildung 4: Verschleierter C++ Code. ..............................................................................21 Abbildung 5: Control Flow Flattening Schema (übernommen aus [26]) ..............................25 Abbildung 6: Control Flow Flattening in Aktion (übernommen aus [26]) ..............................25 Abbildung 7: .NET Programm Fiddler2 dekompiliert mittels ILSpy ......................................28 Abbildung 8: links: Java Quellcode | rechts: Dekompilierter Java Quellcode ......................31 Abbildung 9: Dekompilierter Java Quellcode, der mit ProGuard obfuscated wurde ............32 Abbildung 10: VirusTotal.com Scanergebnis des JavaScript-Codes von oberhalb .............41 Abbildung 11: VirusTotal.com Scanergebnis des abgeänderten JavaScript-Codes von oberhalb ...............................................................................................................................41 Abbildung 12: Zperm: Metamorphie mittels umordnen von Instruktionen und einfügen von Jump Statements [46] ..........................................................................................................46 Abbildung 13: Obfuscation des ZeuS-Bot mittels yoda’s Protector v1.03.3 .........................49 Abbildung 14: avast! Prüfergebnis des originalen ZeuS-Bots .............................................50 Abbildung 15: AVG Prüfergebnis des originalen ZeuS-Bots ...............................................50 Abbildung 16 & 17: Avira & Kaspersky Prüfergebnis des originalen ZeuS-Bots ..................50 Abbildung 18: VirusTotal Prüfergebnis des originalen ZeuS-Bots .......................................51 Abbildung 19: avast! Prüfergebnis des verschleierten ZeuS-Bots .......................................51 Abbildung 20: AVG Prüfergebnis des verschleierten ZeuS-Bots .........................................51 Abbildung 21 & 22: Avira & Kaspersky Prüfergebnis des verschleierten ZeuS-Bots ...........51 Abbildung 23: VirusTotal Prüfergebnis des verschleierten ZeuS-Bots ................................52 Abbildung 24: Smart Assembly GUI (.NET Obfuscator) ......................................................53 Abbildung 25: Mit ILSpy disassembelter original Bytecode des Keyloggers ........................53 Abbildung 26: Mit ILSpy disassembelter verschleierter Bytecode des Keyloggers ..............54 Abbildung 27: ConfuserEx v0.4.0 GUI ................................................................................54 Abbildung 28: Einstellungen des ConfuserEx .....................................................................55 Abbildung 29: Avast-Virenscan des originalen Keyloggers .................................................55 Abbildung 30: Avast-Virenscan des mit Smart Assembly 6 verschleierten Keyloggers .......55 Abbildung 31: Avast-Virenscan des mit ConfuserEx verschleierten Keyloggers..................56 Abbildung 32: AVG-Virenscan des originalen Keyloggers ..................................................56 Abbildung 33: AVG-Virenscan des mit Smart Assembly 6 verschleierten Keyloggers .........56 Abbildung 34: AVG-Virenscan des mit ConfuserEx verschleierten Keyloggers ...................57 Abbildung 35 & 36: Avira-Scan des originalen (li.) und des mit Smart Assembly 6 verschleierten (re.) Keyloggers .............................................................................................57 Abbildung 37: Avira-Virenscan des mit ConfuserEx verschleierten Keyloggers ..................57 Abbildung 38: Kaspersky-Virenscan des originalen Keyloggers .........................................58 79 Abbildung 39: Kaspersky-Virenscan des Smart Assembly 6 Keyloggers ............................58 Abbildung 40: Kaspersky-Virenscan des ConfuserEx Keyloggers ......................................58 Abbildung 41: Virustotal-Virenscan des originalen Keyloggers ...........................................59 Abbildung 42: Virustotal-Virenscan des mit Smart Assembly 6 veschleierten Keyloggers ..59 Abbildung 43: Virustotal-Virenscan des mit ConfuserEx verschleierten Keyloggers ...........60 Abbildung 44: Malware Verbreitungsmethoden und zugehörige Erkennungsraten von AVs [51] .......................................................................................................................................61 Abbildung 45: Zeitraum, wie lange Malware unentdeckt bleibt, aufgeschlüsselt auf die Infektionsquellen [51] ...........................................................................................................62 Abbildung 46: GUI von MS EMET ......................................................................................65 Abbildung 47: App – Sicherheitsmechanismus – Matrix von EMET ....................................66 Tabellenverzeichnis Tabelle 1: Beispiele für .NET und Java Disassembler/Decompiler .......................................28 Tabelle 2: Malware Typen ...................................................................................................39 80