Tatort Internet: Zeig mir das Bild vom Tod

Seite 2: Premiere

Inhaltsverzeichnis

Sieh an, das Tool funktioniert wie geplant und zeigt mir insgesamt 5 Streams an, aus denen sich das Powerpoint-Dokument zusammensetzt:

Pictures   [TYPE: Stream - OFFSET: 0x200 - LEN: 857541] 
CurrentUser [TYPE: Stream - OFFSET: 0xe3600 - LEN: 47]
SummaryInformation [TYPE: Stream - OFFSET: 0xd7800 - LEN: 44484]
PowerPointDocument [TYPE: Stream - OFFSET: 0xd1800 - LEN: 46958]
DocumentSummaryInformation [TYPE: Stream - OFFSET: 0xd7800 - LEN: 912]

Allerdings sieht das bisher recht harmlos aus; insbesondere hat der Scanner kein VB-Makro gefunden. Dabei hatte ich extra eine spezielle Erkennungsroutine gebaut, die mir den Visual-Basic-Skriptcode sogar dekomprimiert in eine Datei geschrieben hätte. Na ja, dann eben beim nächsten Mal.

Anscheinend greift die Powerpoint-Datei etwas tiefer in die Trickkiste, um Code auszuführen. Wahrscheinlich nutzt sie eine der zahlreichen, bekannten – und eigentlich längst gepatchten – Sicherheitslücken in Powerpoint, über die man direkt eigenen Code einschleusen und ausführen kann. Trotzdem müsste der sich doch eigentlich in der Office-Datei aufspüren lassen, wenn man nach den richtigen Dingen sucht. Ich mach mich also erneut an die Arbeit, um mit einer neuen Scan-Routine ein wenig tiefer zu schürfen.

Ein paar Stunden später ist die neue Version fertig. Sie entdeckt in Office-Dateien versteckte, ausführbare Dateien an ihrem PE-Header; also dieses „MZ“ und so weiter, das man sieht, wenn man mal eine EXE-Datei in einem Editor öffnet. Eine eingebettete Windows-Objekt-Datei im OLE-Format erkenne ich an der typischen Office-Binärformat-Signatur \xD0\xCF\x11\xE0\xA1\xB1\x1a\xE1.

Außerdem habe ich gleich noch eine Reihe von Signaturen gebastelt, die typische Shellcode-Elemente aufspüren. Unter anderem springt das Tool auf die Kombination von Push- und Call-Befehlen an, wie sie für Funktionsaufrufe typisch sind. Aber auch einige komplexere und deshalb zuverlässigere Signaturen sind schon da. Das hier etwa ist ein Klassiker der Windows-Shellcode Programmierung, den immer noch viele Exploits genau so einsetzen:

mov eax, fs:[30h] 
mov eax, [eax+0Ch]
mov esi, [eax+1Ch]
lodsd
mov ebp, [eax+08h]

Wenn man Code einschleust, will man typischerweise Dateien aus dem Netz nachladen, auf Festplatte schreiben und starten. Dafür gibt es im System bereits Funktionen; um sie aufzurufen, muss man sie die allerdings erst mal finden. Bereits 2002 veröffentlichte die legendäre Hackergruppe "Last Stage of Delirium" dieses Verfahren, um zuverlässig die Basisadresse der zentralen Systembibliothek kernel32.dll im Speicher zu ermitteln. Sie stellt eine Reihe von nützlichen Systemfunktionen wie LoadLibraryA bereit, über die man dann weitere Bibliotheken nachladen kann.

Der Debug-Modus von OfficeMalScan gibt Zusatzinfos aus, mit denen man schnell entscheiden kann, ob der Scanner wirklich was sinnvolles gefunden hat.

Der Code selbst ist einfach gestrickt: An der Speicheradresse FS:0x30 eines aktiven Windows-Prozesses befindet sich immer ein Zeiger auf den genannten Process Environment Block (PEB), der unter anderem verkettete Listen über bereits geladene Module enthält. An denen hangelt sich der Code entlang, bis schließlich die gewünschte Basisadresse der kernel32.dll im Register ebp landet. Das wegweisende Paper Understanding Windows Shellcode (PDF) und ein paar andere Quellen lieferten die wichtigsten Maschinencode-Sequenzen für die Shellcode-Erkennung.

Doch weiter im Text – wir wollen ja schließlich eine Powerpoint-Datei auseinandernehmen. Ich teste also den OfficeMalScanner mit meinem neuen Scan-Modus und habe auch prompt Erfolg. Ein FS:30-Zugriff, um die Kernel32-Basis-Adresse zu finden, eine API-Hashing-Schleife zum Aufspüren bestimmter Funktionen und reihenweise Push/Call-Kombinationen:

FS:[30h] (Method 1) signature found at offset: 0x506e 
API-Hashing signature found at offset: 0x52fb
PUSH DWORD[]/CALL[] signature found at offset: 0x50ab
PUSH DWORD[]/CALL[] signature found at offset: 0x5137
...

Der Kontrollblick mit dem ebenfalls schnell zusammengebastelten Disassembler DisView.exe zeigt tatsächlich ab 0x506e eindeutig Shellcode. Aber so richtig zufrieden bin ich noch immer nicht.