.text:01004462 mov esi, ds:__imp__lstrcpyW@8 ; lstrcpyW(x,x)
TheHyper:0103A44D push ebx TheHyper:0103A44E mov ebx, [esp+8] TheHyper:0103A452 push esi TheHyper:0103A453 db 0,0,0,0,0,0 TheHyper:0103A459 push edi TheHyper:0103A45A push _szAnsiText TheHyper:0103A460 push ebx TheHyper:0103A461 call esi
.text:010023CE E9 00 00 00 00 jmp $+5
.text:01001C5B ; __stdcall SetTitle(x) .text:01001C5B 00 _SetTitle@4 db 0 .text:01001C5C 00 db 0 .text:01001C5D 00 db 0 .text:01001C5E 00 db 0
struct TH_registers { unsigned long rESP; unsigned long r1; unsigned long r2; unsigned long r3; unsigned long r4; unsigned long r5; unsigned long r6; unsigned long r7; unsigned long r8; unsigned long r9; unsigned long rA; unsigned long rB; unsigned long rC; unsigned long rD; unsigned long rE; unsigned long rF; }; struct TH_context { unsigned char *vm_data; unsigned long vm_data_len; unsigned char *EIP; unsigned long EFLAGS; TH_registers registers; TH_keyed_mem keyed_mem_array[502]; unsigned long stack[0x9000/4]; };
TheHyper:0104A159 VM_set_flags_dword: TheHyper:0104A159 cmp [edi], esi TheHyper:0104A15B pushf TheHyper:0104A15C pop [eax+VM_context_structure.EFLAGS] TheHyper:0104A316 VM_jz: TheHyper:0104A316 push [eax+VM_context_structure.EFLAGS] TheHyper:0104A319 popf TheHyper:0104A31A jnz short loc_104A31F TheHyper:0104A31C mov [eax+VM_context_structure.EIP], edi TheHyper:0104A31F loc_104A31F: TheHyper:0104A31F jmp short VM_dispatcher_13h_locret
TheHyper:0104A36A mov esi, esp TheHyper:0104A36C mov edx, [eax+VM_context_structure.VM_registers.rESP] TheHyper:0104A36F mov esp, edx TheHyper:0104A371 call edi TheHyper:0104A373 mov edx, [ebp+arg_0] TheHyper:0104A376 mov [edx+VM_context_structure.VM_registers.rA], eax TheHyper:0104A379 mov esp, esi
TheHyper:0104A69F cmp cl, 0FFh TheHyper:0104A6A2 jnz short go_on_parsing TheHyper:0104A6A4 popa TheHyper:0104A6A5 mov eax, [ebp+var_4_VM_context_structure] TheHyper:0104A6A8 mov eax, [eax+VM_context_structure.VM_registers.rA] TheHyper:0104A6AB mov [ebp+4], eax ; [ebp+4] = return address TheHyper:0104A6AE leave TheHyper:0104A6AF retn 8
struct TH_keyed_mem { unsigned char *ptr; unsigned long key; };
TheHyper:0104A3DC mov [esi], edx ; key TheHyper:0104A3DE mov [esi-4], eax ; ptr TheHyper:0104A3E1 add dword ptr [esi-4], 8 ; ptr
['$$$$'][4-byte key]^[arbitrary data] ^: pointer
.text:01001B9A ; __stdcall UpdateStatusBar(x) .text:01001B9A _UpdateStatusBar@4 db 0B7h dup(0) ROM:0103AFAA mov r0B, 1038A82h ; location of function in the VM section ROM:0103AFB2 mov r06, 0B7h ; notice this matches up with the ROM:0103AFBA push r06 ; size of the stolen function above ROM:0103AFBD push r0B ROM:0103AFC0 push r0F ; points to a block of allocated mem ROM:0103AFC3 x86call x86_memcpy ROM:0103AFC9 add rESP, 0Ch ROM:0103AFD1 mov r0B, 1001B9Ah ; address of UpdateStatusBar ROM:0103AFD9 mov r0E, r0F ROM:0103AFDD sub r0E, r0B ROM:0103AFE1 sub r0E, 5 ; r0E is the displacement of the jmp ROM:0103AFE9 add r0F, r06 ; point after the copied function ROM:0103AFED mov [r0Bb], 0E9h ; assemble a long jmp ROM:0103AFF2 inc r0B ROM:0103AFF5 mov [r0B], r0E ; write the displacement for the jmp
Displacement 0h into allocated memory -> 1001B9Ah Displacement B7h into allocated memory -> 1001EEFh Displacement 11Dh into allocated memory -> 100696Ah
ROM:01049920 getmem r0B, 10000h ROM:01049926 mov r0B, [r0B] ROM:0104992A add r0B, 639h ; where does this point?
.text:010019DF E9 00 00 00 00 jmp $+5
ROM:0104840F valloc 195h, 6 ; allocate 0x195 bytes of vmem under the ROM:01048418 getmem r0E, 6 ; tag 0x6 ROM:0104841E mov r0F, 10019DFh ; see above: same address ROM:01048426 mov r0D, r0F ROM:0104842A add r0D, 5 ; point after the jump ROM:01048432 mov r09, r0E ; point at the currently-assembling stub ROM:01048436 sub r09, r0D ; calculate the displacement for the jmp ROM:0104843A inc r0F ; point to the 0 dword in e9 00000000 ROM:0104843D mov [r0F], r09 ; insert reference to allocated memory ROM:01048441 mov r0B, 1001AE1h ; this is the target of the jmp ROM:01048449 mov r0C, r0E ROM:0104844D add r0C, 5 ; calculate address after allocated jmp ROM:01048455 sub r0B, r0C ; calculate displacement for jmp ROM:01048459 mov [r0Eb], 0E9h ; build jmp in VirtualAlloc'ed memory ROM:0104845E inc r0E ROM:01048461 mov [r0E], r0B ; insert address into jmp ROM:01048465 add r0E, 4
ROM:010498F3 getmem r0F, 10000h ROM:010498F9 mov r0F, [r0F] ROM:010498FD add r0F, 469h ROM:01049920 getmem r0B, 10000h ROM:01049926 mov r0B, [r0B] ROM:0104992A add r0B, 639h
.text:01001C51 6A 00 push 0 .text:01001C53 E8 00 00 00 00 call $+5 .text:01001C58 C2 1C 00 retn 1Ch ROM:0104419A valloc 3F2h, 5 ; allocate 0x3f2 bytes of memory under ROM:010441A3 getmem r0E, 5 ; the tag 0x5 ROM:010441A9 mov r0F, 1001C53h ; address of call to be fixed up (above) ROM:010441B1 mov r0D, r0F ROM:010441B5 add r0D, 5 ; point after the call ROM:010441BD mov r09, r0E ; r09 points to the allocated jmp stub ROM:010441C1 sub r09, r0D ROM:010441C5 inc r0F ROM:010441C8 mov [r0F], r09 ; insert the proper displacement ROM:010441CC mov r0B, 1001B9Ah ; we would be calling this address ROM:010441D4 mov r0C, r0E ROM:010441D8 add r0C, 5 ROM:010441E0 sub r0B, r0C ; calculate displacement ROM:010441E4 mov [r0Eb], 0E9h ; form the long jmp in allocated memory ROM:010441E9 inc r0E ROM:010441EC mov [r0E], r0B ROM:010441F0 add r0E, 4
ROM:010441F8 getmem r0F, 10000h ROM:010441FE mov r0F, [r0F] ROM:01044202 add r0F, 20Dh
TheHyper:01021524 pushf TheHyper:01021525 pusha TheHyper:01021526 call sub_1021548 TheHyper:01021548 pop eax TheHyper:01021549 add eax, 16h TheHyper:0102154C jmp eax
TheHyper:010215DE 61 popa TheHyper:010215DF 9D popf TheHyper:010215E0 E9 00 00 00 00 jmp $+5
ROM:01026058 mov r04, 1013000h ; point to beginning of packer section ROM:0102607B getmem r05, dword_101382D ROM:01026081 mov r0B, r09 ROM:01026085 mov r06, r04 ROM:01026089 add r06, 41Ch ROM:01026091 mov [r0Bb], [r06b] ; copy byte of DLL name from 0x101341c ROM:01026095 inc r0B ROM:01026098 mov r06, r04 ROM:0102609C add r06, 93h ROM:010260A4 mov [r0Bb], [r06b] ; copy byte of DLL name from 0x1013093 ; idiom repeats a variable number of times ROM:010260A8 inc r0B ROM:0102617C mov [r0Bb], 0 ROM:01026181 push r09 ROM:01026184 x86call r0C ; LoadLibraryA ROM:01026186 add rESP, 4
ROM:0102618E push r09 ROM:01026191 push r0B ROM:01026194 push r0D ROM:01026197 mov r09, r0A ROM:0102619B getmem r0A, g_Copy_Of_Kernel32_Address_Space ROM:010261A1 mov r0A, [r0A] ROM:010261A5 push kernel32_hashes_VirtualAlloc ROM:010261AB push r0A ROM:010261AE vmcall API__GetProcAddress ROM:010261B4 mov r0D, r0A ROM:010261B8 mov r0B, r09 ROM:010261BC add r0B, 3Ch ROM:010261C4 mov r0B, [r0B] ROM:010261C8 add r0B, r09 ROM:010261CC add r0B, 50h ROM:010261D4 mov r0B, [r0B] ; retrieve this DLL's SizeOfImage ROM:010261D8 push 40h ROM:010261DE push 1000h ROM:010261E4 push r0B ROM:010261E7 push 0 ROM:010261ED x86call r0D ; allocate that much memory ROM:010261EF add rESP, 10h ROM:010261F7 mov r03, r0A ROM:010261FB mov [r05], r0A ROM:010261FF push r0B ROM:01026202 push r09 ROM:01026205 push r0A ROM:01026208 x86call x86_memcpy ; copy DLL's address space ROM:0102620E add rESP, 0Ch ROM:01026216 pop r0D ROM:01026219 pop r0B ROM:0102621C pop r09
ROM:0102621F xor r07, r07 ; r07 = hash ROM:01026223 mov r06, r04 ROM:01026227 add r06, 12h ROM:0102622F mov r05, [r06] ROM:01026233 and r05, 0FFh ROM:0102623B or r07, r05 ; get a single byte of the hash ROM:0102623F ror r07, 8 ; idiom repeats three times ROM:010262B3 xor r08, r08 ; r08 = where to put the resolved import ROM:010262B7 mov r06, r04 ROM:010262BB add r06, 5C7h ROM:010262C3 mov r05, [r06] ROM:010262C7 and r05, 0FFh ROM:010262CF or r08, r05 ROM:010262D3 ror r08, 8 ; idiom repeats three times ROM:01026347 push r07 ROM:0102634A push r03 ; point at copied DLL ROM:0102634D vmcall API__GetProcAddress ROM:01026353 add r08, 1000000h ROM:0102635B mov [r08], r0A ; store resolved address back into IAT
.text:010012A0 __imp__PageSetupDlgW@4 dd 0 010012A0 -> [Address of new FirstThunk entry for PageSetupDlgW import]
.text:010012A0 ; BOOL __stdcall PageSetupDlgW(LPPAGESETUPDLGW) .text:010012A0 __imp__PageSetupDlgW@4 dd 0 TheHyper:01014126 pushf TheHyper:01014127 pusha TheHyper:01014128 call sub_1014150 ; eventually ends up at next snippet TheHyper:0101423A popa TheHyper:0101423B popf TheHyper:0101423C jmp near ptr 0B97002DDh ; patch here + 1 byte ROM:0103659A mov r0B, 10012A0h ; see above: IAT addr ROM:010365A2 mov r0E, 1014126h ; see above: beginning of import obfs ROM:010365AA mov r08, 101423Dh ; see above: end of import obfs ROM:010365B2 mov r06, [r0B] ROM:010365B6 mov [r0B], r0E ; replace IAT addr with obfuscated addr ROM:010365BA mov r03, r08 ROM:010365BE dec r03 ROM:010365C1 add r03, 5 ROM:010365C9 sub r06, r03 ROM:010365CD mov [r08], r06 ; form relative jump to real import
.text:010019D4 int 3 ; Trap to Debugger .text:010019D5 nop .text:010019D6 nop .text:010019D7 nop .text:010019D8 nop .text:010019D9 nop ROM:0103C747 mov r03, 10019D4h ; address of the snippet above ROM:0103C74F mov r06, r03 ROM:0103C753 add r06, 5 ; point after call ROM:0103C75B mov [r03b], 0E8h ; insert relative call ROM:0103C760 inc r03 ROM:0103C763 mov r04, 100121Ch ; where we call to ROM:0103C76B sub r04, r06 ; create relative displacement ROM:0103C76F mov [r03], r04 ; insert relative address ROM:0103C773 add r03, 4 ROM:0103C77B mov [r03b], 90h ; insert NOP in empty byte spot
ROM:0103C67E getmem r03, 10000h ROM:0103C684 mov r03, [r03] ROM:0103C688 add r03, 1318h
ROM:01049F05 mov r0A, 1006AE0h ROM:01049F0D stop
ROM:01035E90 cmp r07, 1 ROM:01035E98 jz 77026DDFh
case 0x20: printf("%lx: getefl %s\n", address, decode_register(next_byte & 0xf)); return 2; // size of instruction
case 0x20: cmd.itype = TH_getefl; // instruction code is TH_getefl; this comes // from an enumeration cmd.Op1.type = o_reg; // operand 1 is register cmd.Op1.reg = TH_Regnum(4, ua_next_byte() & 0xf); // get register num cmd.Op1.dtyp = dt_dword; // register is dword size cmd.Op2.type = o_void; // operands 2+ do not exist length = 2; // instruction size is 2 break;
case o_reg: OutReg( x.reg ); break;
" Usually I write a new processor module in the following way: - copy the sample module files to a new directory - first I edit INS.CPP and INS.HPP files - write the analyser ana.cpp - then outputter - and emulator (you can start with an almost empty emulator) - and describe the processor & assembler, write the notify() function"
enum nameNum { TH_null = 0, // Unknown Operation TH_mov, // Move [...,] // [more instructions here] TH_stop, // Stop execution, return to x86 TH_end // No more instructions };
instruc_t Instructions[] = { { "", 0 }, // Unknown Operation // GROUP 1: Two-Operand Arithmetic Instructions { "mov" , CF_USE2 | CF_USE1 | CF_CHG1 }, // Move [{...,...},] // [more instructions] { "stop" , CF_STOP } // Stop execution, return to x86 };
enum TH_regs { rESPb = 0, rESPw, rESP, [...,] r0F, rVcs, // fake registers for segmentation rVds, // fake rEND };
static char *TH_regnames[] = { "rESPb", "rESPw", "rESP", [...,] "r0F" };
case 0x1d: cmd.itype = TH_vfree; // virtualalloc'ed memory free cmd.Op1.type = o_imm; // type of operand 1 is immediate cmd.Op1.value = ua_next_long(); // value = memory key to free cmd.Op1.dtyp = dt_dword; // 4-byte memory key length = 5; // 5 bytes, 1 for opcode, 4 for operand break;
void out( void ) { char buf[MAXSTR]; init_output_buffer(buf, sizeof(buf)); OutMnem(); if( cmd.Op1.type != o_void ) out_one_operand( 0 ); // output first operand if( cmd.Op2.type != o_void ) // do we have a second operand? { out_symbol( ',' ); // put a ", " in the output OutChar( ' ' ); out_one_operand( 1 ); // output second operand } term_output_buffer(); // attach a possible user-defined comment to this instruction gl_comm = 1; MakeLine( buf ); }
case o_displ: out_symbol('['); OutReg( x.phrase ); out_symbol('+'); OutValue(x, OOF_ADDR ); out_symbol(']'); break;
int emu( void ) { ulong Feature = cmd.get_canon_feature(); if((Feature & CF_STOP) == 0) // does this instruction pass flow on? ua_add_cref( 0, cmd.ea+cmd.size, fl_F ); // yes -- add a regular flow if(Feature & CF_USE1) // does this instruction have a first operand? TouchArg(cmd.Op1, 0); // process it if(Feature & CF_USE2) TouchArg(cmd.Op2, 1); return 1; // return value seems to be unimportant } // "emulation" performed on a given op_t, see emu() static void TouchArg( op_t &x, bool bRead ) { switch( x.type ) { case o_vmmem: ua_add_cref( 0, get_keyed_address(x.addr), InstrIsSet(cmd.itype, CF_CALL) ? fl_CN : fl_JN); // add a code reference to the targeted address, either a call or a // jump depending on whether that instruc_t's flags has CF_CALL set. break; } }
There are 31,320 total registered users.
[+] expand