;###############[ Cut Here ]############################################

; - Crackme.asm -
; 
; Zum kompilieren ( TASM 5.0 ) :
;
;  tasm crackme /n /p /t /w /z /m4
;  tlink crackme /d /x /t


.model tiny
.code
.486
org 100h                    ; COM Datei

Start:
call Crypt                  ; Call des Entcrypters

;---------------------------; Hier fngt der verschlsselte Teil an
CryptStart:
 mov ah, 3dh                ; eigene Datei zum schreiben ffnen
 mov al, 02h                ; denn diese wollen wir manipulieren
 lea dx, filename
 int 21h

 jc Ende
 
 xchg bx, ax                ; Dateihandle speichern

 pusha                      ; Register speichern
 call PolyEngine            ; Datei neu erstellen
 popa                       ; Register wieder laden

 mov ax, 4200h              ; gehe zum Anfang der Datei
 xor cx,cx
 xor dx,dx
 int 21h

 mov ah, 40h                ; schreibe etwas in die Datei
 lea dx, CryptedCom         ; und zwar den gesamten eigenen Code
 mov cx, word ptr [mySize]  ; der nun einen neuen Entcryptor trgt
 int 21h                    ; und verschlsselt ist

 mov ah, 3eh                ; Datei schlieen ( Handle ist in bx )
 int 21h 

 mov ah, 09h                ; <------------------------------------------>
 lea dx, MSG1               ; <<== make this point to MSG2
 int 21h

Ende:
 mov ax, 4c00h              ; Programm beenden
 int 21h

                            ; Die Daten
MSG1      db 'Crack me !',10,13,'$'       ; <- normale Ausgabe
MSG2      db 'You cracked me !',10,13,'$' ; <- Ausgabe der gecrackten Version

filename  db 'Crackme.com',0h  ; Der eigene Dateiname
mySize    dw 0h                ; hier speichern wir die Grsse der neuen Datei
CryptType db 0h                ; Die Art wie wir die Datei verschlsseln
LoadType  db 0h
CryptKey  db 0h


; diese Prozedur erstellt die neue COM Datei
; in dem Buffer ( CryptedCom ) am Ende der COM Datei
; ich habe hier fr jede Instruktion nur eine Alternative gewhlt,
; weil ich verdammt faul bin, und weil es so bersichtlich bleibt =)

PolyEngine:

 lea di, CryptedCom

; zuallererst erstellen wir den CALL neu
; dieser wird jedesmal ber eine andere Distanz gefhrt,
; so dass er nicht statisch bleibt

 mov al, 0E8h               ; "Call" - Opcode 
 stosb
 
 xor ax, ax
 in al, 40h                 ; Zufallszahl von 0 bis 255
 shr al, 3h                 ; teilen durch 8 ( Zahl von 0 bis 31 )

                            ; Lnge der Datei ( ohne Crypter & Co )
 mov bx, offset Crypt - offset CryptStart
 add bx, ax                 ; damit geht der Call immer ber eine andere
                            ; Distanz
 xchg ax, bx
 stosw
 add ax, 3
 mov word ptr [mySize], ax  ; Gesamtgroesse speichern
 
 push bx                    ; bx enthlt die "Trash" Bytes, die wir
                            ; spter noch anhngen mssen, damit der call
                            ; auch den decrypter trifft

; zuerst "verschluesseln" wir mal die Datei und schreiben sie
; in unseren Buffer, wir haben hier 2 konstante Arten der Verschlsselung
; man knnte der XOR Verschlsselung auch relativ einfach fr jedes
; Mal einen anderen Key verpassen.

 lea si, CryptStart        
 mov cx, offset Crypt - offset CryptStart

; durch in al, 40h ermitteln wir eine Zufallszahl, dies geht, da
; der Lautsprecher, wohl jedesmal einen anderen Wert liefert, durch
; normales Rauschen & Co..

 in al, 40h                 ; neue Zufallszahl
 shr al, 2h                 ; 1 oder 2
 jc NegCrypt
                            ; speichern wie wir verschluesseln
 mov byte ptr [CryptType], 0

 in al, 40h                 ; Schlssel ermitteln
 mov byte ptr [CryptKey], al
 mov dl, al

 CryptLoop1:
  lodsb
   xor al, dl              ; mit xor "verschlsseln"
  stosb                    ; Zuflliger Schlssel
 loop CryptLoop1

 jmp GoOn

NegCrypt:                   ; speichern wir wir verschluesseln
 mov byte ptr [CryptType], 1
 CryptLoop2:
  lodsb
   neg al                  ; mit einem einfachen neg "verschlsseln"
  stosb
 loop CryptLoop2

; Jetz fangen wir an den Decryptor zu erstellen
; zuerst einige sinnlose Bytes, damit die Groesse nicht immer gleich 
; ist.

GoOn: 

 pop cx                     ; cx sind die Trashbytes zum anhngen
  
 Trash1:
  in al, 40h                ; Zufllige Bytes
  stosb                     ; in den Buffer schreiben
 loop Trash1

 mov ax, word ptr [mySize]  ; Groesse des verschluesselten Teiles
 push ax                    ; im Stack speichern

; Nun erstellen wir den Teil des Decryptors, der den Anfangscode
; ermittelt, ab dem er entschlsseln muss. Da dieser nach dem
; Call auf dem Stack liegt, mssen wir nur den Wert auf den
; sp / esp zeigt in si laden.

 in al, 40h                 ; wir poppen si vom stack, um den Start
 shr al, 1                  ; des verschlsselten codes zu bekommen
 jc GetOffset2

 mov ax, 0565Eh
 stosw
 add word ptr [mySize], 2h
 jmp GoOn2

GetOffset2:                 ; mov si, word ptr [esp]
 mov ax, 08b67h 
 stosw
 mov ax, 02434h
 stosw
 add word ptr [mySize], 4h
GoOn2:   

; Nun laden wir in cx die Groesse des verschlsselten Codes
; entweder indem wir ein mov cx, size machen oder
; indem wir den Wert pushen und dann nach cx poppen

 pop cx                     ; groesse des verschluesselten teiles
 in al, 40h
 shr al, 1
 jc GetSize2
 
 mov al, 068h               ; push Size
 stosb
 mov ax, cx
 stosw
 mov al, 059h               ; pop cx
 stosb
 add word ptr [mySize], 4h
 jmp GoOn3

GetSize2:                   ; mov cx, Size
 mov al, 0B9h
 stosb
 mov ax, cx
 stosw
 add word ptr [mySize], 3h

GoOn3:

; Nun mssen wir die Entschlsselungsschleife generieren
; zuallererst laden wir einen Wert in al
;
; entweder per : mov di, si - lodsb
; oder         : mov al, byte ptr [si]


 push word ptr [mySize]    ; groesse speichern

 in al, 40h
 shr al, 1
 jc LoadByte2 

 mov ax, 0FE8Bh            ; mov di, si
 stosw
 mov al, 0ACh              ; lodsb
 stosb
 add word ptr [mySize], 3h
 mov LoadType, 0
 jmp GoOn4

LoadByte2:
 mov ax, 0048Ah            ; mov al, byte ptr [si]
 stosw
 add word ptr [mySize], 2h
 mov LoadType, 1

GoOn4:                      ; nun wird das Byte in al entsprechen
                            ; der Verschlsselungsart "entschlsselt"
 cmp byte ptr [CryptType],0
 jne Crypt_2

 mov al, 034h               ; xor al, 
 mov ah, byte ptr CryptKey  ; CryptKey
 jmp GoOn5

Crypt_2:
 mov ax, 0D8F6h             ; neg al

GoOn5:
 stosw
 add word ptr [mySize], 2h

; Jetzt mssen wir das Byte in al wieder
; an seinen alten Platz speichern
; entweder per stosb
; oder per mov byte ptr [si], al - inc si

 cmp LoadType, 0
 jne Store2

 mov al, 0AAh               ; stosb
 stosb
 inc word ptr [mySize]
 jmp GoOn6

Store2:
 mov ax, 00488h             ; mov byte ptr [si], al
 stosw
 mov al, 046h               ; inc si
 stosb
 add word ptr [mySize], 3h

GoOn6:

; Jetzt fehlt nur der Loop um das Ganze zu wiederholen
; Zuerst ermitteln wir die Groesse ueber die der Loop gehen muss


 mov bx, word ptr [mySize] ; momentane Grsse
 pop ax                    ; Groesse vor dem Loop-Teil
 sub bx, ax                ; Groesse des Loops
 mov ax, 0FFh              ; wir loopen "rckwrts"
 sub ax, bx                ; der Wert is in al
 dec ax
 mov ah, al

 push ax
 in al, 40h
 shr al, 1
 jc DoLoop2

 pop ax
 mov al, 0E2h              ; loop
 stosw
 add word ptr [mySize], 2
 jmp GoOn7

DoLoop2:                   ; dec cx
 mov al, 049h
 stosb
 pop ax
 dec ah                    ; der Sprung geht ber 1 Byte mehr
 mov al, 075h              ; jnz <CryptStart>
 stosw
 add word ptr [mySize], 3

GoOn7:

; Nun koennen wir den entschluesselten Teil starten,
; wir kehren immer mit einem einfachen "ret" zurck

 mov al, 0C3h               ; Das 'ret' am Ende des Decryptors anhngen
 stosb 
 inc word ptr [mySize]      ; Groesse um eins erhhen, wegen dem Ret
ret


Trash:
 in al, 40h
 

ret


;---------------------------; bis hier ist alles verschlsselt

Crypt:                      ; in der ersten Generation wird
ret                         ; hier noch nichts entschlsselt
                            ; deshalb steht hier nur das ret

CryptedCom:                 ; hierhin speichern wir die verschlsselte
                            ; Datei ( unser Buffer halt *g* )
db 90h dup (0h)

END Start


;###############[ Cut Here ]############################################