{"id":38,"date":"2006-04-13T10:31:44","date_gmt":"2006-04-13T09:31:44","guid":{"rendered":"http:\/\/my.stargazer.at\/?p=38"},"modified":"2007-05-29T13:53:25","modified_gmt":"2007-05-29T11:53:25","slug":"analyse-eines-samples","status":"publish","type":"post","link":"https:\/\/my.stargazer.at\/de\/2006\/04\/13\/analyse-eines-samples\/","title":{"rendered":"Analyse eines Samples"},"content":{"rendered":"<p>Ein altes Sample lag schon seit Wochen in meinem Homedirectory, da ich es einmal analysieren wollte &#8211; der Hash F0B0224B75E899440C15EE05B59B6013. Obgleich es Virenscanner als Backdoor.Win32.Dumador.at erkennen gehe ich ans Werk um es einmal selbst zu zerlegen. Ein Sample mit 21536 Bytes Kampfgewicht und einer Behandlung mit dem FSG Packer sollten schon knackbar sein. Der defekte PE- und der fast winzige MZ-Header sind ein sicheres Zeichen daf\u00fcr dass jemand etwas verstecken m\u00f6chte.<!--more--><\/p>\n<p>Das Tolle an den Packern, wie im vorherigen Post schon beschrieben ist, dass sie den Entpackungsmechanismus und den Key gleich frei Haus mitliefern. FSG ist da keine Ausnahme und mit ein bisschen Trickserei gibt das Paket auch seinen Inhalt Preis.<\/p>\n<p>Beim Start kopiert sich das Sample als winldra.exe in den Ordner %windir%\\system32, wo es ein paar DLL Dateien ablegt und sich schliesslich in der Registry unter HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Run einnistet, was den Autostart sichert. Was die DLLs genau tun kann ich jedoch nur vermuten, scheint jedoch etwas mit einer Funktion namens Windows-Hook CBTProc zu tun zu haben, was eine Art Keylogger f\u00fcr das aktive Fenster zu sein scheint. Laut Microsoft ist es ein (dubioses) Windows-feature f\u00fcr Computer Based Training, \u00fcber das ein Prozess beobachten kann, was im aktiven Fenster vor sich geht:<\/p>\n<p><em>&#8222;Das System ruft diese Funktionen auf, bevor es ein Fenster aktiviert, erzeugt, vernichtet, minimiert, maximiert, bewegt oder seine Gr\u00f6\u00dfe ver\u00e4ndert; bevor es System-Kommandos beendet; bevor es Maus- oder Tastatureingaben aus der Message Queue entfernt; bevor es den Tastaturfokus setzt; oder bevor es die Message Queue des Systems synchronisiert. Ein computergest\u00fctztes Trainingsprogramm (CBT) benutzt diesen Hook, um vom System n\u00fctzliche Benachrichtigungen zu erhalten.&#8220;<\/em><\/p>\n<p>Das gef\u00e4hrliche an dieser Funktion ist, dass sie wie f\u00fcr diesen Virus geschaffen ist und die Vorg\u00e4nge im Browser bei einer enthaltenen Liste von Webseiten genauestens beobachten kann. Diese Liste beinhaltet Seiten wie cbonline.co.uk, volkswagenbank.de oder raiba-nu-wh.de&#8230; Nett oder? Was passiert weiter?<\/p>\n<p>Die gesammelten Daten werden per eMail, codiert versendet und ein Registry Key gesetzt: HKCU\\Software\\SARS\\mailsended = 1<\/p>\n<p>Altbekannte Maneuver des Samples sind dazu noch das nachtr\u00e4gliche Bearbeiten der Datei <em>%windir%\\system32\\drivers\\etc\\hosts<\/em>, mit welcher man die DNS Aufl\u00f6sung diverser Dateien effektiv unterbinden kann. Dass dies in erster Linie Seiten von Antivirus-Herstellern sind, wird wohl jedem klar sein.<\/p>\n<p>Nach diesem groben \u00dcberblick fand ich in dem File noch ein paar Ungereimtheiten, welche mich in die Tiefen des Codes zwangen, welcher sich nun im Debugger vor mir ausbreitete. Ich begann zu lesen&#8230;<\/p>\n<p>Bei der Adresse 004030B2 angelangt stiess ich auf InternetConnectA() und HttpSendRequestA() WinInet API, was eindeutig auf das Senden von Daten ausgelegt war, welche wiederum ihre Daten mit einer netten Routine bei 00403187 mit Hilfe der Funktion strcpy() und logdata= als Argument verschl\u00fcsselt. Meine Neugierde w\u00e4chst und ich grabe tiefer und folge den Spuren im Sample in der Hoffnung nichts zu \u00fcbersehen.<\/p>\n<p>Die der Verschl\u00fcsselung \u00fcbergebenen Argumente, namentlich EAX (ein unverschk\u00fcsselter String), EDX (das Ergebnis &#8211; String) und ECX, die L\u00e4nge von EAX. Jedes Byte von EAX wird in einer Schleife abgearbeitet, welche so lange l\u00e4uft bis alle Zeichen verschl\u00fcsselt sind.<\/p>\n<blockquote><p><code>00401935 ; ::::::::::::::: S U B R O U T I N E :::::::::::::::<br \/>\n00401935<br \/>\n00401935 EncryptLogs<br \/>\n00401935     push    ebx<br \/>\n00401936     push    esi<br \/>\n00401937     push    edi<br \/>\n00401938     push    ebp<br \/>\n00401939     mov     edi, offset aAbcdefghijklmn ;<br \/>\n0040193E     xor     esi, esi<br \/>\n00401940     test    ecx, ecx<br \/>\n00401942     jle     loc_4019D8<\/code><\/p><\/blockquote>\n<p>In diesem ersten Block passiert nichts Unheimliches: Register werden gespeichert und Variablen gesetzt. Desweiteren wird gepr\u00fcft ob der Wert von ECX gr\u00f6sser als Null ist. Die Variable EDI welche hier auftaucht zeigt auf einen alphanumerischen string mit den Zeichen A-Z, a-z, 0-9 und &#8222;+\/&#8220;) &#8211; sein Sinn scheint nur Verwirrung zu sein.<\/p>\n<blockquote><p><code>00401948 loc_401948:<br \/>\n00401948     cmp     esi, 20<br \/>\n0040194B     jbe     short loc_401957<br \/>\n0040194D     mov     byte ptr [edx], 0Dh<br \/>\n00401950     inc     edx<br \/>\n00401951     mov     byte ptr [edx], 0Ah<br \/>\n00401954     inc     edx<br \/>\n00401955     xor     esi, esi<\/code><\/p><\/blockquote>\n<p>Der zweite Block formatiert die Zeilen der Ausgabe, sodass das Ergebnis keine \u00fcberlangen Zeilen enth\u00e4lt &#8211; was sich durchaus als Vorteil erweisen sollte. ESI dabei stellt einen Z\u00e4hler dar, welcher nach 20 verschl\u00fcsselten Zeichen zur\u00fcckgesetzt wird, nachdem ein CRLF in die Verschl\u00fcsselung eingef\u00fcgt wurde.<\/p>\n<blockquote><p><code>00401957 loc_401957:<br \/>\n00401957     xor     ebx, ebx<br \/>\n00401959     mov     bl, [eax]<br \/>\n0040195B     sar     ebx, 2<br \/>\n0040195E     mov     bl, [edi+ebx]<br \/>\n00401961     mov     [edx], bl<\/code><\/p><\/blockquote>\n<p>Der dritte Teil hat auch nichts Magisches an sich: Bedenken wir, dass EAX auf den zu verschl\u00fcsselnden String zeigt. Daraufhin wird EBX gel\u00f6scht und das erste Zeichen nach BL geladen und EBX um 2 Bit verschoben. Das Ergebnis wird in ein Byte verwandelt und im Ergebnisstring EDX abgelegt. Klingt komplex, ist es aber nicht:<\/p>\n<p>Nehmen wir an, unser Zeichen lautet &#8218;I&#8216;, was nach der ASCII-Tabelle in Bin\u00e4r so aussieht: 01001001 (Sch\u00f6n, nicht?)<br \/>\nNun verschieben wir um 2 Bit und das Ergebnis lautet 00010010. Da wir jedoch nur 8 Bit zur Verf\u00fcgung haben, verlieren wir 2 Stellen und wir haben einen Wert den wir in der ASCII Tabelle ermitteln k\u00f6nnen&#8230;<\/p>\n<p>Wir schreiten zum n\u00e4chsten St\u00fcck:<\/p>\n<blockquote><p><code>00401963     xor     ebx, ebx<br \/>\n00401965     mov     bl, [eax]<br \/>\n00401967     inc     edx<br \/>\n00401968     and     ebx, 3<br \/>\n0040196B     shl     ebx, 4<br \/>\n0040196E     cmp     ecx, 1<br \/>\n00401971     jle     short loc_40197C<br \/>\n00401973     movzx   ebp, byte ptr [eax+1]<br \/>\n00401977     sar     ebp, 4<br \/>\n0040197A     jmp     short loc_40197E<br \/>\n0040197C ; ------------------------------------------------<br \/>\n0040197C loc_40197C:<br \/>\n0040197C     xor     ebp, ebp<br \/>\n0040197E<br \/>\n0040197E loc_40197E:<br \/>\n0040197E     or      ebx, ebp<br \/>\n00401980     mov     bl, [edi+ebx]<br \/>\n00401983     mov     [edx], bl<\/code><\/p><\/blockquote>\n<p>Huh? Das kennen wir doch schon? Exakt: Als erstes wird wie auch im vorherigen Abschnitt EBX gel\u00f6scht und das erste zu verschl\u00fcsselnde Zeichen geladen. EDX wird daraufhin erh\u00f6ht und eine AND-Operation an EBX mit dem Wert 3 ausgef\u00fchrt. Um uns nun richtig zu verwirren wird dann das Zeichen wieder verschoben, diesmal um 4. Danach passiert ein Check ob wir nicht schon beim letzten Byte angelangt sind.<\/p>\n<p>Sehen wir uns das Ganze wieder an unserem Beispiel von vorhin an. 3 entspricht dem ASCII Wert 00000011 und &#8218;I&#8216; kennen wir bereits als 01001001. Die logische AND Operation  sieht wie folgt aus: <em>01001001 AND 00000011 = 00000001<\/em>. Mit diesem Ergebnis und der Verschiebung landen wir schliesslich bei 00010000&#8230; Was ist hier passiert? &#8211; Ganz langsam zum Mitschreiben: Die 2 LSB (Least Significant Bits) des ersten Bytes wurden gespeichert und um 4 nach rechts verschoben. Der aufmerksame Leser wird sich die Zeichen ansehen und bemerken, dass dies die Zeichen sind, welche uns bei der ersten Operation verloren gingen.<\/p>\n<p>Was den Check des letzten Bytes im String betrifft ignoriere ich ihn f\u00fcr&#8217;s erste einmal, da die Stelle 00401973 meine Aufmerksamkeit auf sich zieht. Was hier passiert ist, dass das n\u00e4chste Byte genommen wird, es um 4 Stellen nach Rechts verschoben wird um schliesslich mit 2 in der logischen Operation OR zu landen.<\/p>\n<p>Um es zu veranschaulichen sei unser n\u00e4chstes Byte der Buchstabe &#8218;D&#8216;, welcher in der ASCII Tabelle unter dem Bin\u00e4rwert 01000100 zu finden ist. Verschieben wir einmal und wir erhalten 00000100. Die OR-Operation gegen die Bitfolge 00010000 f\u00fchrt uns zum Ergebnis 00010100. Hier halten wir die ersten 2 Bits des ersten Byte und die letzten 4 des zweiten Bytes in den H\u00e4nden. Wie auch vorhin verlieren wir ein paar Bits bei den Operatonen, hier die MSB (Most Significant Bits)&#8230;<\/p>\n<p>Wie dem auch sei, wir wissen wie die fehlenden Bits der ersten Manipulation aussehen, was uns erm\u00f6gicht, das erste Byte zu decoden:<br \/>\nWir suchen uns den Index der ersten beiden Bytes im verschl\u00fcsselten String und verschieben. Unser Beispiel mit dem Zeichen &#8218;I&#8216; sollte uns dabei gute Dienste leisten. Das Ergebnis dabei ist 01001000, was uns das Zeichen bis auf die LSB liefert. Um diese zu bekommen verschieben wir den zweiten Index um 4 nach Rechts und bekommen 01001000. Diese zwei Ergebnisse addieren wir in einer AND Operation und erhalten &#8211; Oh Wunder &#8211; 01001001 was dem Zeichen &#8218;I&#8216; entspricht.<\/p>\n<p>Das erste Zeichen in der Theorie zu entschl\u00fcsseln war ja nicht mal so hart, oder? Lesen wir weiter und sehen wir uns an, wie es weitergeht:<\/p>\n<blockquote><p><code>0040198D     mov     bl, [eax+1]<br \/>\n00401990     shl     ebx, 2<br \/>\n00401993     and     ebx, 3Ch<br \/>\n00401996     cmp     ecx, 2<br \/>\n00401999     jle     short loc_4019A4<br \/>\n0040199B     movzx   ebp, byte ptr [eax+2]<br \/>\n0040199F     sar     ebp, 6<br \/>\n004019A2     jmp     short loc_4019A6<br \/>\n004019A4 ; ------------------------------------------------<br \/>\n004019A4 loc_4019A4:<br \/>\n004019A4     xor     ebp, ebp<\/code><\/p><\/blockquote>\n<p>Mal sehen&#8230; In diesem Block sieht es \u00e4hnlich aus wie zuvor und wir haben gute Chancen mit den aktuellen \u00dcberlegungen durchzukommen. Das 2. Byte wird um 2 Verschoben und in einer AND Operation gegen 0x3c gerechnet. Das heisst f\u00fcr unser Beispiel:<\/p>\n<blockquote><p><code>'D' = 01000100 < < 2 = 00010000,\n0x3c = 00111100\n00010000 &#038; 00111100 = 00010000.<\/code><\/code><\/p><\/blockquote>\n<p>Dann wird das 3. Byte angegriffen und um 6 Stellen verschoben. Das 3. Byte nehmen wir als &#8218;:&#8216; an, was 00111010 entspricht. Nach dem verschieben der Stellen haben wir 00000000. Die im Code vorgeschriebene OR Operation gegen dieses Ergebnis ergibt 00010000 und einen Heisshunger auf eine Tasse Kaffee.<\/p>\n<p>Nun wissen wir die ersten 4 Bit des zweiten Bytes, haben aber die ersten 6 Bit des dritten Zeichens verloren. \u00c3\u201ehnlich wie wir dem ersten Byte zu Leibe gegangen sind decoden wir das Zweite indem wir das Bitmuster des Zweiten und Dritten Bytes in unserem String suchen um ersteres um 4 Bit nach links und zweiteres um 2 Bit nach rechts zu versetzen. Die Ergebnisse vereinen wir mit einer AND Operation und &#8211; Heureka, das 2. Byte ist leserlich.<\/p>\n<p>Die Decodierung des 3. Bytes sollte erratbar sein, aber um sicher zu gehen &#8211; wir sind ja paranoid &#8211; pr\u00fcfen wir es in den n\u00e4chsten Zeilen des Codes nach:<\/p>\n<blockquote><p><code>004019B9     mov     bl, [eax+2]<br \/>\n004019BC     and     ebx, 3Fh<br \/>\n004019BF     mov     bl, [edi+ebx]<\/code><\/p><\/blockquote>\n<p>Was hier passiert ist wirklich simpel und Debuggerfreundlich: Das 3. Byte wird in BL geladen und in einer AND Operation mit 0x3f vereint.<br \/>\nKurz und schmerzlos testen wir das an unserem Beispiel aus:<\/p>\n<p>Unser 3. Byte 00111010 und 0x3F ergibt 00111111.<br \/>\n00111010 &#038; 00111111 = 00111010.<\/p>\n<p>Das w\u00e4re ja im Grunde genommen unser Byte in Klartext, aber die letzten 2 Bits gingen durch das Shiften verloren. Analog zum vorigen Codeblock shiften wir das 3. Byte um 6 Stellen nach links und vereinen es mit einer OR Operation mit dem 4. Wir wissen nun, wie wir den String decrypten, aber es fehlt noch eine Kleinigkeit. Diese cmp ECX welche in unseren Bl\u00f6cken herumgeistern zeigen die Stringl\u00e4nge, damit wir nicht ins Leere greifen. Doch was tun wenn keine Bytes mehr da sind? Der Code zeigt dassentweder 0x0 oder 0x3D verwendet wird, was dem Zeichen &#8218;=&#8216; entspricht&#8230;<\/p>\n<p>Wir wissen nun die h\u00e4ndische Methode um die verschl\u00fcsselten Daten zu bekommen, doch ist dies nicht rentabel wenn es darum geht, etwas zu decoden, da die gew\u00fcnschte Information selten kleiner als 3 Bytes sein wird &#8211; daher eine Funktion welche uns die Arbeit abnehmen wird:<\/p>\n<blockquote><p><code>void decrypt (char *in)<br \/>\n{<br \/>\n    char first, second, third, fourth;<br \/>\n    int lf_count = 0,<br \/>\n        i        = 0;<br \/>\n    int byte_count = strlen(in);<\/p>\n<p>    while (byte_count > 0)<br \/>\n    {<br \/>\n        first  = index(&in[i]);<br \/>\n        second = index(&in[i + 1]);<br \/>\n        third  = index(&in[i + 2]);<br \/>\n        fourth = index(&in[i + 3]);<\/p>\n<p>        if (byte_count > 2)<br \/>\n            first = (first < < 2) | (second >> 4);<br \/>\n        else<br \/>\n            first = (first < < 2);\n\n        printf(\"%c\", first);\n\n        if (byte_count > 2)<br \/>\n        {<br \/>\n            if (byte_count > 3)<br \/>\n                second = (second < < 4) | (third >> 2);<br \/>\n            else<br \/>\n                second = (second < < 4);\n        }\n\n        printf(\"%c\", second);\n\n        if (byte_count > 3)<br \/>\n        {<br \/>\n            third = (third < < 6) | fourth;\n            printf(\"%c\", third);\n        }\n\n        i += 4;\n        byte_count -= 4;\n        lf_count++;\n    }\n}\n<\/code><\/code><\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>Ein altes Sample lag schon seit Wochen in meinem Homedirectory, da ich es einmal analysieren wollte &#8211; der Hash F0B0224B75E899440C15EE05B59B6013. Obgleich es Virenscanner als Backdoor.Win32.Dumador.at erkennen gehe ich ans Werk um es einmal selbst zu zerlegen. Ein Sample mit 21536 Bytes Kampfgewicht und einer Behandlung mit dem FSG Packer sollten schon knackbar sein. Der defekte PE- und der [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[230,229],"class_list":["post-38","post","type-post","status-publish","format-standard","hentry","category-security","tag-analysis","tag-sample"],"_links":{"self":[{"href":"https:\/\/my.stargazer.at\/de\/wp-json\/wp\/v2\/posts\/38","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/my.stargazer.at\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/my.stargazer.at\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/my.stargazer.at\/de\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/my.stargazer.at\/de\/wp-json\/wp\/v2\/comments?post=38"}],"version-history":[{"count":0,"href":"https:\/\/my.stargazer.at\/de\/wp-json\/wp\/v2\/posts\/38\/revisions"}],"wp:attachment":[{"href":"https:\/\/my.stargazer.at\/de\/wp-json\/wp\/v2\/media?parent=38"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/my.stargazer.at\/de\/wp-json\/wp\/v2\/categories?post=38"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/my.stargazer.at\/de\/wp-json\/wp\/v2\/tags?post=38"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}