-
-
[原创] 2019看雪CTF 晋级赛Q1第3题
-
发表于: 2019-3-25 10:38 7637
-
一、初探
CODE:00493628 db 'function sptWBCallback(spt_wb_id,spt_wb_name,optionstr){url=',27h; Text CODE:00493628 db '#sptWBCallback:id=',27h,';url=url+spt_wb_id+',27h,';eventName=',27h; Text CODE:00493628 db '+spt_wb_name;if(optionstr) url=url+',27h,';params=optionstr',27h,';'; Text CODE:00493628 db 'location=url;}',0 ; Text CODE:00493868 db '<center><br><br><br><input value="" id="pswd" size=39></input><br'; Text CODE:00493868 db '><br><br><input type=button value="checkMyFlag" onclick="ckpswd()'; Text CODE:00493868 db ';"></center>',0 ; Text CODE:004938FF align 10h
从字符串上看,存在一个html,里面有个onclick的处理函数 ckpswd函数,首先需要找到ckpswd函数体。不想一步一步分析,启动程序,用ce在内存总搜索,很快可以发现如下脚本函数:
function ckpswd() { key="simpower91"; a = document.all.pswd.value; if(a.indexOf(key) ==0) { l=a.length; i=key.length; sptWBCallback(a.substring(i,l)); } else { alert("wrong!<" + a + "> is not my GUID;-)"); return "1234"; } }
可以看出要求输入的sn开头部分必须是 "simpower91",否则会提示 'worng!',测试一下确实如此,如果输入simpower91111,没有任何提示,看起来仍然有进一步的判断。从上面的脚本可知为sptWBCallback函数,看起来像个回调函数。先找到sptWBCallback函数体。从前面的字符串中可以看到其影子,在内存中搜索下,发现如下:
function sptWBCallback(spt_wb_id,spt_wb_name,optionstr) { url='#sptWBCallback:id='; url=url+spt_wb_id+'; eventName='+spt_wb_name; if(optionstr) url=url+'; params=optionstr'; location=url; }
上面代码应该是WebBrowser JS回调delphi的方法。因此真正的检测应该仍然在dephi主程序中。需要找到注册时间的回调函数。分析IDA反汇编代码发下如下:
CODE:00491DCC sub_491DCC proc near ; CODE XREF: _Tfrmcrackme_FormCreate+81↓p CODE:00491DCC push ebx CODE:00491DCD mov ebx, eax CODE:00491DCF mov eax, ebx CODE:00491DD1 call sub_491B78 ; call function CODE:00491DD6 mov eax, [ebx+40h] CODE:00491DD9 mov [eax+2A4h], ebx CODE:00491DDF mov dword ptr [eax+2A0h], offset sub_492088 CODE:00491DE9 pop ebx CODE:00491DEA retn CODE:00491DEA sub_491DCC endp
其中sub_492088函数比较可疑。设置个断点,输入 “
simpower91111
”果然断了下了。
二、回调
sub_492088
int __userpurge sub_492088@<eax>(int a1@<eax>, int a2@<edx>, int a3@<ecx>, int a4@<ebx>, int a5@<esi>, int edi0@<edi>, _WORD *a6, int a7, int a8, int a9, int a10, int a11) { int v12; // ebx int v13; // esi int v14; // eax int v15; // eax Classes::TStrings *v16; // esi int v17; // ST14_4 int v18; // ST10_4 unsigned int v20; // [esp-14h] [ebp-34h] void *v21; // [esp-10h] [ebp-30h] int *v22; // [esp-Ch] [ebp-2Ch] int v23; // [esp-8h] [ebp-28h] int v24; // [esp-4h] [ebp-24h] int v25; // [esp+0h] [ebp-20h] int v26; // [esp+4h] [ebp-1Ch] int v27; // [esp+8h] [ebp-18h] char v28[4]; // [esp+Ch] [ebp-14h] int v29; // [esp+10h] [ebp-10h] int System::AnsiString; // [esp+14h] [ebp-Ch] int v31; // [esp+18h] [ebp-8h] int v32; // [esp+1Ch] [ebp-4h] int savedregs; // [esp+20h] [ebp+0h] System::AnsiString = 0; v29 = 0; *(_DWORD *)v28 = 0; v27 = 0; v26 = 0; v25 = 0; v24 = a4; v23 = a5; v31 = a3; v32 = a2; v12 = a1; v22 = &savedregs; v21 = &loc_4921D1; v20 = __readfsdword(0); __writefsdword(0, (unsigned int)&v20); Variants::__linkproc__ VarToLStr(&v29, a11); v13 = sub_465C88((int)&str__sptWBCallback_[1], v29); if ( v13 > 0 ) { *a6 = -1; Variants::__linkproc__ VarToLStr(&System::AnsiString, a11); v14 = GetJSLen(System::AnsiString); v15 = System::__linkproc__ LStrCopy(System::AnsiString, v13 + 15, v14 - v13 - 14, (int)&System::AnsiString); LOBYTE(v15) = 1; unknown_libname_161(System::AnsiString, (int)&str___41[1], (int)&str____19[1], v12, edi0, v13, (int)v28, v15); System::__linkproc__ LStrLAsg(&System::AnsiString, *(signed __int32 *)v28); v16 = (Classes::TStrings *)TStreamCreate((int)cls_Classes_TStringList, 1); (*(void (__fastcall **)(Classes::TStrings *, int))(*(_DWORD *)v16 + 44))(v16, System::AnsiString); if ( *(_WORD *)(v12 + 50) ) { Classes::TStrings::GetValue(v16, (const int)&str_params[1], (int)&v27); v17 = v27; Classes::TStrings::GetValue(v16, (const int)&str_eventName[1], (int)&v26); v18 = v26; Classes::TStrings::GetValue(v16, (const int)&str_id[1], (int)&v25); (*(void (__fastcall **)(_DWORD, int, int, int))(v12 + 48))(*(_DWORD *)(v12 + 52), v25, v18, v17); } } if ( *(_WORD *)(v12 + 58) ) (*(void (__fastcall **)(_DWORD, int, int, int, int, int, int, int, _WORD *))(v12 + 0x38))( *(_DWORD *)(v12 + 60), v32, v31, a11, a10, a9, a8, a7, a6); __writefsdword(0, v20); v22 = (int *)&loc_4921D8; return System::__linkproc__ LStrArrayClr(&v25, 6); }
核心处理函数为 V12+0X38,地址为;493F70
三、 493F70函数
loc_493F70: ; DATA XREF: _Tfrmcrackme_FormCreate+87↑o CODE:00493F70 push ebp CODE:00493F71 mov ebp, esp CODE:00493F73 CODE:00493F73 loc_493F73: ; CODE XREF: CODE:00493FC5↓j CODE:00493F73 add esp, 0FFFFFBD8h CODE:00493F79 push ebx CODE:00493F7A push esi CODE:00493F7B xor ebx, ebx CODE:00493F7D mov [ebp-428h], ebx CODE:00493F83 mov [ebp-424h], ebx CODE:00493F89 mov [ebp-420h], ebx CODE:00493F8F mov [ebp-14h], edx CODE:00493F92 mov ebx, eax CODE:00493F94 mov eax, [ebp-14h] CODE:00493F97 call @System@@LStrAddRef$qqrpv ; System::__linkproc__ LStrAddRef(void *) CODE:00493F9C mov eax, [ebp+8] CODE:00493F9F call @System@@LStrAddRef$qqrpv ; System::__linkproc__ LStrAddRef(void *) CODE:00493FA4 xor eax, eax CODE:00493FA6 push ebp CODE:00493FA7 push offset loc_4941BA CODE:00493FAC push dword ptr fs:[eax] CODE:00493FAF mov fs:[eax], esp CODE:00493FB2 mov eax, [ebp-14h] CODE:00493FB5 call GetJSLen ; BDS 2005-2007 and Delphi6-7 Visual Component Library CODE:00493FBA cmp eax, 4 CODE:00493FBD jnz loc_494181 CODE:00493FC3 jmp short loc_493FE6 CODE:00493FC5 ; --------------------------------------------------------------------------- CODE:00493FC5 loopne near ptr loc_493F73+4 CODE:00493FC7 mov cl, 0B2h CODE:00493FC9 mov edx, offset byte_494045 CODE:00493FCE mov [ebp-4], edx CODE:00493FD1 mov edx, offset loc_4940D0 CODE:00493FD6 mov [ebp-8], edx CODE:00493FD9 mov edx, offset dword_494168 CODE:00493FDE mov [ebp-0Ch], edx CODE:00493FE1 jmp loc_4940DA CODE:00493FE6 ; --------------------------------------------------------------------------- CODE:00493FE6 CODE:00493FE6 loc_493FE6: ; CODE XREF: CODE:00493FC3↑j CODE:00493FE6 mov eax, offset _str_data_txt_1.Text CODE:00493FEB call @Sysutils@FileExists$qqrx17System@AnsiString ; Sysutils::FileExists(System::AnsiString) CODE:00493FF0 test al, al CODE:00493FF2 jz short loc_494010 CODE:00493FF4 mov dl, 1 CODE:00493FF6 mov eax, off_416648 CODE:00493FFB call TStreamCreate ; BDS 2005-2007 and Delphi6-7 Visual Component Library CODE:00494000 mov esi, eax CODE:00494002 mov edx, offset _str_data_txt_1.Text CODE:00494007 mov eax, esi CODE:00494009 call @Ibsql@TIBXSQLVAR@LoadFromFile$qqrx17System@AnsiString ; Ibsql::TIBXSQLVAR::LoadFromFile(System::AnsiString) CODE:0049400E jmp short loc_494025 CODE:00494010 ; --------------------------------------------------------------------------- CODE:00494010 CODE:00494010 loc_494010: ; CODE XREF: CODE:00493FF2↑j CODE:00494010 or ecx, 0FFFFFFFFh CODE:00494013 mov edx, offset _str_data_txt_1.Text CODE:00494018 mov eax, [ebx+330h] CODE:0049401E call GetVmpCode CODE:00494023 mov esi, eax CODE:00494025 CODE:00494025 loc_494025: ; CODE XREF: CODE:0049400E↑j CODE:00494025 mov edx, offset byte_494045 CODE:0049402A mov [ebp-4], edx CODE:0049402D mov eax, [ebp-4] CODE:00494030 push eax CODE:00494031 mov eax, [esi+4] CODE:00494034 push eax CODE:00494035 mov eax, ds:dword_498F3C CODE:0049403A push eax CODE:0049403B call sub_473A04 CODE:0049403B ; --------------------------------------------------------------------------- CODE:00494040 dd 0 CODE:00494044 db 0 CODE:00494045 byte_494045 db 0 ; DATA XREF: CODE:00493FC9↑o CODE:00494045 ; CODE:loc_494025↑o CODE:00494046 dd 0 CODE:0049404A align 4 CODE:0049404C dd 1Ah dup(0) CODE:004940B4 db 2 dup(0) CODE:004940B6 dd 0 CODE:004940BA align 4 CODE:004940BC dd 5 dup(0)
这个函数与去年的类似,程序对 地址 494045代码进行解密,里面存在一个反汇编引擎,对代码进行重定位,并一条一条执行,同时存在一个简单的VMP。
73 69 6D 76 6D 01 00 05 00 .......simvm.... 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 C5 3F 49 00 05 .............I.. 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 02 01 01 02 00 00 F0 00 00 00 00 F3 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 01 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F2 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 02 00 00 00 00 ................ 00 00 00 03 01 01 02 00 00 F0 00 00 00 00 F1 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 03 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F0 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 ................ 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF FF 00 ................ 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 00 00 ................ 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 6F 72 69 67 6E 83 C0 7F ........orign兝 . 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 00 00 3襰 imvm......... 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 00 00 ................ 00 00 F3 FF FF FF 00 00 00 00 03 6F 72 69 67 6E ...........orign 3B C2 75 52 73 69 6D 76 6D 01 00 07 00 00 F0 00 ;聈 Rsimvm....... 00 00 00 00 00 00 00 00 00 00 00 04 02 00 00 F0 ................ 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 01 ................ 07 00 00 F0 00 00 00 00 01 00 00 00 00 00 00 00 ................ 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D 76 6D .orign兝 .3襰 imvm 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 02 00 00 F0 00 00 00 00 F2 FF FF FF 00 ................ 00 00 00 03 6F 72 69 67 6E 3B C2 75 3F 73 69 6D ....orign;聈 ?sim 76 6D 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 00 00 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF ................ FF 00 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 ................ 00 00 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 ................ 00 02 00 00 00 00 00 00 00 04 6F 72 69 67 6E 83 ..........orign. C0 7F 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 ..3襰 imvm....... 00 00 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 ................ 00 00 00 00 F1 FF FF FF 00 00 00 00 03 6F 72 69 .............ori 67 6E 3B C2 75 2C 73 69 6D 76 6D 01 00 07 00 00 gn;聈 ,simvm..... F0 00 00 00 00 00 00 00 00 00 00 00 00 04 02 00 ................ 00 F0 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 ................ 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 ................ 00 01 07 00 00 F0 00 00 00 00 03 00 00 00 00 00 ................ 00 00 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D ...orign兝 .3襰 im 76 6D 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 01 00 00 00 01 02 00 00 F0 00 00 00 00 F0 FF FF ................ FF 00 00 00 00 03 6F 72 69 67 6E 3B C2 75 19 8D ......orign;聈 .. 85 E0 FB FF FF 50 33 C9 73 69 6D 76 6D 01 00 05 呧 ...P3蓅 imvm... 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 E8 41 49 00 ............鐰 I. 05 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 04 04 00 00 F0 00 00 00 00 34 03 00 00 ............4... 00 00 00 00 06 6F 72 69 67 6E E8 27 DD FF FF EB .....orign...... 09 73 69 6D 76 6D 65 6E 64 00 .simvmend
上面是指令码,其中带有 simvm 标识的为VMP代码,带有orgin的为原始代码,对于simvm的代码走虚拟机执行引擎,对于orgin标识通过反编译引擎,并重定位执行。
493F70 会调用473A04 上面的逻辑主要在本函数执行。
CODE:00473A04 sub_473A04 proc near ; CODE XREF: CODE:0049403B↓p CODE:00473A04 CODE:00473A04 var_2C = dword ptr -2Ch CODE:00473A04 var_8 = dword ptr -8 CODE:00473A04 var_4 = dword ptr -4 CODE:00473A04 var_s0 = dword ptr 0 CODE:00473A04 arg_4 = dword ptr 0Ch CODE:00473A04 arg_8 = dword ptr 10h CODE:00473A04 CODE:00473A04 push ebp CODE:00473A05 mov ebp, esp CODE:00473A07 leave CODE:00473A08 push dword ptr [esp+0] CODE:00473A0B push [esp+var_s0] CODE:00473A0E push [esp+4+var_4] CODE:00473A11 pusha CODE:00473A12 pushf CODE:00473A13 call sub_4723EC CODE:00473A18 mov ebx, eax CODE:00473A1A xor eax, eax CODE:00473A1C mov [ebx+1050h], eax CODE:00473A22 mov eax, 0FFFFFFFFh CODE:00473A27 mov [ebx+1054h], eax CODE:00473A2D mov [esp+2Ch+var_8], ebx CODE:00473A31 mov eax, [esp+2Ch+arg_8] ; eax = encryptCodeAddr CODE:00473A35 mov [esp+2Ch+var_4], eax CODE:00473A39 mov eax, [esp+2Ch+arg_4] CODE:00473A3D mov [esp+2Ch+var_s0], eax CODE:00473A41 mov eax, [ebx+1090h] CODE:00473A47 cmp eax, 0 CODE:00473A4A jnz short loc_473A57 CODE:00473A4C mov eax, offset codeCrypt CODE:00473A51 mov [ebx+1090h], eax CODE:00473A57 CODE:00473A57 loc_473A57: ; CODE XREF: sub_473A04+46↑j CODE:00473A57 popf CODE:00473A58 popa CODE:00473A59 call HandleCode CODE:00473A5E pushf CODE:00473A5F pushf CODE:00473A60 pushf CODE:00473A61 pusha CODE:00473A62 pushf CODE:00473A63 jmp short loc_473A89 CODE:00473A65 ; --------------------------------------------------------------------------- CODE:00473A65 CODE:00473A65 loc_473A65: ; CODE XREF: sub_473A04+98↓j CODE:00473A65 mov eax, [ebx+1058h] CODE:00473A6B mov [esp+2Ch+var_s0], eax CODE:00473A6F mov eax, [ebx+1050h] CODE:00473A75 mov [esp+2Ch+var_4], eax CODE:00473A79 mov [esp+2Ch+var_8], ebx CODE:00473A7D popf CODE:00473A7E popa CODE:00473A7F call HandleCode CODE:00473A84 pushf CODE:00473A85 pushf CODE:00473A86 pushf CODE:00473A87 pusha CODE:00473A88 pushf CODE:00473A89 CODE:00473A89 loc_473A89: ; CODE XREF: sub_473A04+5F↑j CODE:00473A89 call sub_4723EC CODE:00473A8E mov ebx, eax CODE:00473A90 mov eax, [ebx+1050h] CODE:00473A96 cmp eax, [ebx+1054h] CODE:00473A9C jb short loc_473A65 CODE:00473A9E mov eax, [ebx+1050h] CODE:00473AA4 mov [esp+30h], eax CODE:00473AA8 mov eax, [esp+2Ch+var_2C] CODE:00473AAB mov [esp+2Ch+var_s0], eax CODE:00473AAF popf CODE:00473AB0 popa CODE:00473AB1 add esp, 8 CODE:00473AB4 popf CODE:00473AB5 retn 0Ch CODE:00473AB5 sub_473A04 endp CODE:00473AB5
而其核心函数为HandleCode(472EAC)
int __usercall HandleCode@<eax>(int a1@<ebx>, int a2@<edi>, int a3@<esi>, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15) { unsigned int v15; // et0 int (__fastcall *v16)(unsigned int *); // ST10_4 unsigned int v18; // [esp+10h] [ebp-30h] int v19; // [esp+30h] [ebp-10h] void **v20; // [esp+34h] [ebp-Ch] int *v21; // [esp+38h] [ebp-8h] int v22; // [esp+3Ch] [ebp-4h] unsigned int vars0; // [esp+40h] [ebp+0h] void *retaddr; // [esp+44h] [ebp+4h] vars0 = a3; v22 = a2; v21 = (int *)&vars0; v20 = &retaddr; v19 = a1; v15 = __readeflags(); *(_DWORD *)(a13 + 4188) = retaddr; DecryptData(a13, a14, a12, (char *)a15, &v21, (int *)&v20, &v19); vars0 = v18; __writeeflags(v18); __writeeflags(v18); return v16(&vars0); }
其中 "16(&vars0);"语句为执行重定位后的代码。而虚拟机以及原始代码重定位在DecryptData函数(472EAC)如下
DWORD *__stdcall DecryptData(int a1, int orgAddr, int a3, char *dataOfFile, _DWORD *a5, int *a6, _DWORD *a7) { _DWORD *global; // ebx int v8; // esi int v9; // edi int v10; // eax int v11; // ecx int v12; // esi int v13; // esi int v14; // eax int v15; // ST18_4 unsigned int v17; // [esp+1Ch] [ebp-77Ch] void *v18; // [esp+20h] [ebp-778h] int *v19; // [esp+24h] [ebp-774h] int v20; // [esp+34h] [ebp-764h] int v21; // [esp+38h] [ebp-760h] char data[1024]; // [esp+3Fh] [ebp-759h] int v23; // [esp+440h] [ebp-358h] char v24; // [esp+444h] [ebp-354h] char v25; // [esp+544h] [ebp-254h] unsigned __int8 orgCodeLen; // [esp+77Ah] [ebp-1Eh] char v27; // [esp+77Bh] [ebp-1Dh] char *nextData; // [esp+77Ch] [ebp-1Ch] char *data1; // [esp+780h] [ebp-18h] _BYTE *v30; // [esp+784h] [ebp-14h] int outDataLen; // [esp+788h] [ebp-10h] int v32; // [esp+78Ch] [ebp-Ch] int opCodeLen; // [esp+790h] [ebp-8h] _DWORD *v34; // [esp+794h] [ebp-4h] int vars0; // [esp+798h] [ebp+0h] v21 = 0; v20 = 0; v30 = 0; v19 = &vars0; v18 = &loc_4732B2; v17 = __readfsdword(0); __writefsdword(0, (unsigned int)&v17); global = sub_4723EC(); v34 = (_DWORD *)(vars0 + 8); data1 = data; v8 = *(_DWORD *)off_497644; *(_DWORD *)(*(_DWORD *)off_497644 + 52) = 0; v27 = 0; while ( 1 ) { callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); while ( 1 ) { while ( *(_DWORD *)(v8 + 52) == 1 ) { orgCodeLen = 0; nextData = callVmpHandle(v8, (_BYTE *)orgAddr, data, (int)&orgCodeLen); opCodeLen = nextData - data; GetNextValueByLen(&dataOfFile, nextData - data); GetNextValueByLen(&orgAddr, orgCodeLen); callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); } if ( ifCode_simvm_orign(v8, &data1) != 1 )// 不是 simvm break; data1 = data; v27 = 1; simvm_Handle(global, v34); } data1 = data; if ( !v27 ) break; v27 = 0; orgin_Handle(global, v34); } outDataLen = off_498CA0(data, outDataLen, 0x400000, &v23, 4, v17);// 执行原始code *a5 = outDataLen; v9 = unknown_libname_29(32 - outDataLen - 6); data1 = (char *)global + v9 + 4144; sub_464FA4(data1, data, outDataLen); *((_BYTE *)global + v9 + outDataLen + 4144) = 104; GetCharFormTstring((int)&v30, &v25); if ( (unsigned __int8)sub_472520(v30, global[1047]) ) { GetCharFormTstring((int)&v30, &v24); opCodeLen = sub_465C88((int)&str___29[1], (int)v30); v10 = GetJSLen(v30); System::__linkproc__ LStrCopy((int)v30, opCodeLen + 1, v10 - opCodeLen, (int)&v30); opCodeLen = sub_465CEC(v30); if ( outDataLen - 1 >= 0 ) { v11 = outDataLen; v32 = 0; do { *((_BYTE *)global + v9 + v32++ + 4144) = -112; --v11; } while ( v11 ); } opCodeLen += outDataLen; v12 = sub_471F04(v8, data, opCodeLen); } else if ( sub_465C88((int)&str_CALL_0[1], (int)v30) == 1 ) { GetCharFormTstring((int)&v30, &v24); if ( sub_465C88((int)&str_FF_0[1], (int)v30) != 1 ) { opCodeLen = sub_465C88((int)&str___29[1], (int)v30); v32 = opCodeLen - 1; v13 = (opCodeLen - 1) / 2; data1 = (char *)global + v9 + v13 + 4144; v14 = GetJSLen(v30); System::__linkproc__ LStrCopy((int)v30, opCodeLen + 1, v14 - opCodeLen, (int)&v30); opCodeLen = sub_465CEC(v30); v32 = opCodeLen + orgAddr - ((_DWORD)global + v9 + 4144); sub_464FA4(data1, &v32, outDataLen - v13); } opCodeLen = outDataLen; v12 = outDataLen; } else { opCodeLen = outDataLen; v12 = outDataLen; } *a7 = opCodeLen; opCodeLen = a3; data1 = (char *)global + v9 + outDataLen + 4145; sub_464FA4(data1, &opCodeLen, 4u); *((_BYTE *)global + v9 + outDataLen + 4149) = 0xC3u; *a6 = (int)global + v9 + 0x1030; global[1044] = orgAddr + *a7; global[1046] = &dataOfFile[v12]; GetCharFormTstring((int)&v21, &v25); v15 = v21; GetCharFormTstring((int)&v20, &v24); sub_4736D4((int)global, *a6, orgAddr, v15, v20, outDataLen); __writefsdword(0, v17); v19 = (int *)&loc_4732B9; System::__linkproc__ LStrArrayClr(&v20, 2); return System::__linkproc__ LStrClr(&v30); }
其中如下代码为执行VMP代码
while ( 1 ) { callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); while ( 1 ) { while ( *(_DWORD *)(v8 + 52) == 1 ) { orgCodeLen = 0; nextData = callVmpHandle(v8, (_BYTE *)orgAddr, data, (int)&orgCodeLen); opCodeLen = nextData - data; GetNextValueByLen(&dataOfFile, nextData - data); GetNextValueByLen(&orgAddr, orgCodeLen); callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); } if ( ifCode_simvm_orign(v8, &data1) != 1 )// 不是 simvm break; data1 = data; v27 = 1; simvm_Handle(global, v34); } data1 = data; if ( !v27 ) break; v27 = 0; orgin_Handle(global, v34); }
后半部分为执行原始代码,进行反编译从定位。
下面是虚拟程序相关函数:
char *__fastcall callVmpHandle(int unknowGlogal, _BYTE *orgAddr, _BYTE *data, int global) { int unknowGlogal_1; // ebx char *data_2; // [esp+4h] [ebp-8h] char *data_1; // [esp+8h] [ebp-4h] data_1 = data; unknowGlogal_1 = unknowGlogal; data_2 = data; if ( *(_DWORD *)(unknowGlogal + 52) == 1 ) { if ( ifCode_simvm_orign(unknowGlogal, &data_1) == 2 ) { data_2 = data_1; // orgin } else { data_2 = data_1; if ( *data_1 == byte_497214 ) data_2 = vmpHandle(unknowGlogal_1, data_1, (char *)global); else *(_DWORD *)(unknowGlogal_1 + 52) = 2; } } return data_2; } char *__fastcall vmpHandle(int unknowGlogal, char *data, char *a3) { char *v3; // ST1C_4 int unknowGlogal_1; // edi char num0Data; // bl int num6Data; // ebp char *dataEnd; // [esp+4h] [ebp-38h] char num5Data; // [esp+8h] [ebp-34h] int num7Data; // [esp+Ch] [ebp-30h] int num8Data; // [esp+10h] [ebp-2Ch] int num9Data; // [esp+14h] [ebp-28h] int num1Data; // [esp+18h] [ebp-24h] int num2Data; // [esp+1Ch] [ebp-20h] int num3Data; // [esp+20h] [ebp-1Ch] int num4Data; // [esp+24h] [ebp-18h] char *data_1; // [esp+28h] [ebp-14h] v3 = a3; unknowGlogal_1 = unknowGlogal; dataEnd = data + 0x24; data_1 = data; GetNextValueByLen(&data_1, 1); num0Data = *data_1; GetNextValueByLen(&data_1, 1); num1Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num2Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num3Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num4Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num5Data = *data_1; GetNextValueByLen(&data_1, 1); num6Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num7Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num8Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num9Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); *v3 = *data_1; if ( num0Data || num5Data ) { if ( num0Data && num5Data ) { sub_471CDC(num0Data, num9Data, num8Data, num7Data, num6Data, num4Data, num3Data); } else if ( !num0Data || num5Data ) { if ( !num0Data && num5Data ) call_vmp_add_reg_value( unknowGlogal_1, num1Data, num2Data, num3Data, num4Data, num6Data, num7Data, num8Data, num9Data, num5Data); } else { call_vmp_memcpy_regAndReg_num( unknowGlogal_1, num1Data, num2Data, num3Data, num4Data, num6Data, num7Data, num8Data, num9Data, num0Data); } } else { sub_471C08(unknowGlogal_1, num1Data, num2Data, num3Data, num4Data, num6Data, num7Data, num8Data, num9Data, 0); } return dataEnd; }
int __fastcall call_vmp_add_reg_value(int unknowGlogal, int num1Data, int num2Data, int num3Data, int num4Data, int num6Data, int num7Data, int num8Data, int num9Data, char num5Data) { if ( num1Data && num6Data ) return vmp_add_reg_value(unknowGlogal, num1Data, num3Data, num6Data, num8Data, num5Data); if ( num1Data && num7Data ) return vmp_add_reg_value(unknowGlogal, num1Data, num3Data, num7Data, num8Data, num5Data); if ( num1Data && num9Data ) return vmp_add_reg_value(unknowGlogal, num1Data, num3Data, num9Data, 0, 0); if ( num2Data && num6Data ) return vmp_add_reg_value(unknowGlogal, num2Data, num3Data, num6Data, num8Data, num5Data); if ( num2Data && num7Data ) return vmp_add_reg_value(unknowGlogal, num2Data, num3Data, num7Data, num8Data, num5Data); if ( num2Data ) { if ( num9Data ) unknowGlogal = vmp_add_reg_value(unknowGlogal, num2Data, num3Data, num9Data, 0, 0); } return unknowGlogal; }
就是一些简单的寄存器读取以及加减乘除运算。
下面的函数是针对代码解密的,就是异或0xFF.
DWORD *__fastcall codeCrypt(int a1, int dataOfFile, char *outData, _DWORD *a4) { int v4; // ecx char v5; // zf _DWORD *v6; // eax unsigned int v8; // [esp+8h] [ebp-20h] void *v9; // [esp+Ch] [ebp-1Ch] int *v10; // [esp+10h] [ebp-18h] int v11; // [esp+20h] [ebp-8h] char *outData1; // [esp+24h] [ebp-4h] int savedregs; // [esp+28h] [ebp+0h] v11 = 0; v10 = &savedregs; v9 = &loc_473839; v8 = __readfsdword(0); __writefsdword(0, (unsigned int)&v8); *a4 = 0x400; outData1 = outData; v4 = 0; do { outData1[v4] = ~*(_BYTE *)(dataOfFile + v4); ++v4; } while ( v4 != 0x400 ); GetCharFormTstring((int)&v11, outData1 + 2); System::__linkproc__ LStrCmp(v11, &str_simvmend[1]._top); if ( v5 ) // 判断代码是否结束 { v6 = sub_4723EC(); v6[0x415] = v6[0x414]; } __writefsdword(0, v8); v10 = (int *)&loc_473840; return System::__linkproc__ LStrClr(&v11); }
三、sn
如下vm指令的主要功能就是解密最后的字符串"a123"
73 69 6D 76 6D 01 00 05 00 .......simvm.... 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 C5 3F 49 00 05 .............I.. 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 02 01 01 02 00 00 F0 00 00 00 00 F3 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 01 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F2 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 02 00 00 00 00 ................ 00 00 00 03 01 01 02 00 00 F0 00 00 00 00 F1 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 03 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F0 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 ................ 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF FF 00 ................ 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 00 00 ................ 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 6F 72 69 67 6E 83 C0 7F ........orign兝 . 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 00 00 3襰 imvm......... 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 00 00 ................ 00 00 F3 FF FF FF 00 00 00 00 03 6F 72 69 67 6E ...........orign 3B C2 75 52 73 69 6D 76 6D 01 00 07 00 00 F0 00 ;聈 Rsimvm....... 00 00 00 00 00 00 00 00 00 00 00 04 02 00 00 F0 ................ 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 01 ................ 07 00 00 F0 00 00 00 00 01 00 00 00 00 00 00 00 ................ 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D 76 6D .orign兝 .3襰 imvm 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 02 00 00 F0 00 00 00 00 F2 FF FF FF 00 ................ 00 00 00 03 6F 72 69 67 6E 3B C2 75 3F 73 69 6D ....orign;聈 ?sim 76 6D 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 00 00 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF ................ FF 00 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 ................ 00 00 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 ................ 00 02 00 00 00 00 00 00 00 04 6F 72 69 67 6E 83 ..........orign. C0 7F 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 ..3襰 imvm....... 00 00 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 ................ 00 00 00 00 F1 FF FF FF 00 00 00 00 03 6F 72 69 .............ori 67 6E 3B C2 75 2C 73 69 6D 76 6D 01 00 07 00 00 gn;聈 ,simvm..... F0 00 00 00 00 00 00 00 00 00 00 00 00 04 02 00 ................ 00 F0 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 ................ 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 ................ 00 01 07 00 00 F0 00 00 00 00 03 00 00 00 00 00 ................ 00 00 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D ...orign兝 .3襰 im 76 6D 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 01 00 00 00 01 02 00 00 F0 00 00 00 00 F0 FF FF ................ FF 00 00 00 00 03 6F 72 69 67 6E 3B C2 75 19 8D ......orign;聈 .. 85 E0 FB FF FF 50 33 C9 73 69 6D 76 6D 01 00 05 呧 ...P3蓅 imvm... 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 E8 41 49 00 ............鐰 I. 05 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 04 04 00 00 F0 00 00 00 00 34 03 00 00 ............4... 00 00 00 00 06 6F 72 69 67 6E E8 27 DD FF FF EB .....orign...... 09 73 69 6D 76 6D 65 6E 64 00 .simvmend
sn为 :simpower91a123
CODE:00493628 db 'function sptWBCallback(spt_wb_id,spt_wb_name,optionstr){url=',27h; Text CODE:00493628 db '#sptWBCallback:id=',27h,';url=url+spt_wb_id+',27h,';eventName=',27h; Text CODE:00493628 db '+spt_wb_name;if(optionstr) url=url+',27h,';params=optionstr',27h,';'; Text CODE:00493628 db 'location=url;}',0 ; Text CODE:00493868 db '<center><br><br><br><input value="" id="pswd" size=39></input><br'; Text CODE:00493868 db '><br><br><input type=button value="checkMyFlag" onclick="ckpswd()'; Text CODE:00493868 db ';"></center>',0 ; Text CODE:004938FF align 10h
从字符串上看,存在一个html,里面有个onclick的处理函数 ckpswd函数,首先需要找到ckpswd函数体。不想一步一步分析,启动程序,用ce在内存总搜索,很快可以发现如下脚本函数:
CODE:00493628 db 'function sptWBCallback(spt_wb_id,spt_wb_name,optionstr){url=',27h; Text CODE:00493628 db '#sptWBCallback:id=',27h,';url=url+spt_wb_id+',27h,';eventName=',27h; Text CODE:00493628 db '+spt_wb_name;if(optionstr) url=url+',27h,';params=optionstr',27h,';'; Text CODE:00493628 db 'location=url;}',0 ; Text CODE:00493868 db '<center><br><br><br><input value="" id="pswd" size=39></input><br'; Text CODE:00493868 db '><br><br><input type=button value="checkMyFlag" onclick="ckpswd()'; Text CODE:00493868 db ';"></center>',0 ; Text CODE:004938FF align 10h
从字符串上看,存在一个html,里面有个onclick的处理函数 ckpswd函数,首先需要找到ckpswd函数体。不想一步一步分析,启动程序,用ce在内存总搜索,很快可以发现如下脚本函数:
function ckpswd() { key="simpower91"; a = document.all.pswd.value; if(a.indexOf(key) ==0) { l=a.length; i=key.length; sptWBCallback(a.substring(i,l)); } else { alert("wrong!<" + a + "> is not my GUID;-)"); return "1234"; } }
可以看出要求输入的sn开头部分必须是 "simpower91",否则会提示 'worng!',测试一下确实如此,如果输入simpower91111,没有任何提示,看起来仍然有进一步的判断。从上面的脚本可知为sptWBCallback函数,看起来像个回调函数。先找到sptWBCallback函数体。从前面的字符串中可以看到其影子,在内存中搜索下,发现如下:
function ckpswd() { key="simpower91"; a = document.all.pswd.value; if(a.indexOf(key) ==0) { l=a.length; i=key.length; sptWBCallback(a.substring(i,l)); } else { alert("wrong!<" + a + "> is not my GUID;-)"); return "1234"; } }
可以看出要求输入的sn开头部分必须是 "simpower91",否则会提示 'worng!',测试一下确实如此,如果输入simpower91111,没有任何提示,看起来仍然有进一步的判断。从上面的脚本可知为sptWBCallback函数,看起来像个回调函数。先找到sptWBCallback函数体。从前面的字符串中可以看到其影子,在内存中搜索下,发现如下:
function sptWBCallback(spt_wb_id,spt_wb_name,optionstr) { url='#sptWBCallback:id='; url=url+spt_wb_id+'; eventName='+spt_wb_name; if(optionstr) url=url+'; params=optionstr'; location=url; }
上面代码应该是WebBrowser JS回调delphi的方法。因此真正的检测应该仍然在dephi主程序中。需要找到注册时间的回调函数。分析IDA反汇编代码发下如下:
CODE:00491DCC sub_491DCC proc near ; CODE XREF: _Tfrmcrackme_FormCreate+81↓p CODE:00491DCC push ebx CODE:00491DCD mov ebx, eax CODE:00491DCF mov eax, ebx CODE:00491DD1 call sub_491B78 ; call function CODE:00491DD6 mov eax, [ebx+40h] CODE:00491DD9 mov [eax+2A4h], ebx CODE:00491DDF mov dword ptr [eax+2A0h], offset sub_492088 CODE:00491DE9 pop ebx CODE:00491DEA retn CODE:00491DEA sub_491DCC endp
其中sub_492088函数比较可疑。设置个断点,输入 “
simpower91111
”果然断了下了。
二、回调
sub_492088
int __userpurge sub_492088@<eax>(int a1@<eax>, int a2@<edx>, int a3@<ecx>, int a4@<ebx>, int a5@<esi>, int edi0@<edi>, _WORD *a6, int a7, int a8, int a9, int a10, int a11) { int v12; // ebx int v13; // esi int v14; // eax int v15; // eax Classes::TStrings *v16; // esi int v17; // ST14_4 int v18; // ST10_4 unsigned int v20; // [esp-14h] [ebp-34h] void *v21; // [esp-10h] [ebp-30h] int *v22; // [esp-Ch] [ebp-2Ch] int v23; // [esp-8h] [ebp-28h] int v24; // [esp-4h] [ebp-24h] int v25; // [esp+0h] [ebp-20h] int v26; // [esp+4h] [ebp-1Ch] int v27; // [esp+8h] [ebp-18h] char v28[4]; // [esp+Ch] [ebp-14h] int v29; // [esp+10h] [ebp-10h] int System::AnsiString; // [esp+14h] [ebp-Ch] int v31; // [esp+18h] [ebp-8h] int v32; // [esp+1Ch] [ebp-4h] int savedregs; // [esp+20h] [ebp+0h] System::AnsiString = 0; v29 = 0; *(_DWORD *)v28 = 0; v27 = 0; v26 = 0; v25 = 0; v24 = a4; v23 = a5; v31 = a3; v32 = a2; v12 = a1; v22 = &savedregs; v21 = &loc_4921D1; v20 = __readfsdword(0); __writefsdword(0, (unsigned int)&v20); Variants::__linkproc__ VarToLStr(&v29, a11); v13 = sub_465C88((int)&str__sptWBCallback_[1], v29); if ( v13 > 0 ) { *a6 = -1; Variants::__linkproc__ VarToLStr(&System::AnsiString, a11); v14 = GetJSLen(System::AnsiString); v15 = System::__linkproc__ LStrCopy(System::AnsiString, v13 + 15, v14 - v13 - 14, (int)&System::AnsiString); LOBYTE(v15) = 1; unknown_libname_161(System::AnsiString, (int)&str___41[1], (int)&str____19[1], v12, edi0, v13, (int)v28, v15); System::__linkproc__ LStrLAsg(&System::AnsiString, *(signed __int32 *)v28); v16 = (Classes::TStrings *)TStreamCreate((int)cls_Classes_TStringList, 1); (*(void (__fastcall **)(Classes::TStrings *, int))(*(_DWORD *)v16 + 44))(v16, System::AnsiString); if ( *(_WORD *)(v12 + 50) ) { Classes::TStrings::GetValue(v16, (const int)&str_params[1], (int)&v27); v17 = v27; Classes::TStrings::GetValue(v16, (const int)&str_eventName[1], (int)&v26); v18 = v26; Classes::TStrings::GetValue(v16, (const int)&str_id[1], (int)&v25); (*(void (__fastcall **)(_DWORD, int, int, int))(v12 + 48))(*(_DWORD *)(v12 + 52), v25, v18, v17); } } if ( *(_WORD *)(v12 + 58) ) (*(void (__fastcall **)(_DWORD, int, int, int, int, int, int, int, _WORD *))(v12 + 0x38))( *(_DWORD *)(v12 + 60), v32, v31, a11, a10, a9, a8, a7, a6); __writefsdword(0, v20); v22 = (int *)&loc_4921D8; return System::__linkproc__ LStrArrayClr(&v25, 6); }
核心处理函数为 V12+0X38,地址为;493F70
三、 493F70函数
loc_493F70: ; DATA XREF: _Tfrmcrackme_FormCreate+87↑o CODE:00493F70 push ebp CODE:00493F71 mov ebp, esp CODE:00493F73 CODE:00493F73 loc_493F73: ; CODE XREF: CODE:00493FC5↓j CODE:00493F73 add esp, 0FFFFFBD8h CODE:00493F79 push ebx CODE:00493F7A push esi CODE:00493F7B xor ebx, ebx CODE:00493F7D mov [ebp-428h], ebx CODE:00493F83 mov [ebp-424h], ebx CODE:00493F89 mov [ebp-420h], ebx CODE:00493F8F mov [ebp-14h], edx CODE:00493F92 mov ebx, eax CODE:00493F94 mov eax, [ebp-14h] CODE:00493F97 call @System@@LStrAddRef$qqrpv ; System::__linkproc__ LStrAddRef(void *) CODE:00493F9C mov eax, [ebp+8] CODE:00493F9F call @System@@LStrAddRef$qqrpv ; System::__linkproc__ LStrAddRef(void *) CODE:00493FA4 xor eax, eax CODE:00493FA6 push ebp CODE:00493FA7 push offset loc_4941BA CODE:00493FAC push dword ptr fs:[eax] CODE:00493FAF mov fs:[eax], esp CODE:00493FB2 mov eax, [ebp-14h] CODE:00493FB5 call GetJSLen ; BDS 2005-2007 and Delphi6-7 Visual Component Library CODE:00493FBA cmp eax, 4 CODE:00493FBD jnz loc_494181 CODE:00493FC3 jmp short loc_493FE6 CODE:00493FC5 ; --------------------------------------------------------------------------- CODE:00493FC5 loopne near ptr loc_493F73+4 CODE:00493FC7 mov cl, 0B2h CODE:00493FC9 mov edx, offset byte_494045 CODE:00493FCE mov [ebp-4], edx CODE:00493FD1 mov edx, offset loc_4940D0 CODE:00493FD6 mov [ebp-8], edx CODE:00493FD9 mov edx, offset dword_494168 CODE:00493FDE mov [ebp-0Ch], edx CODE:00493FE1 jmp loc_4940DA CODE:00493FE6 ; --------------------------------------------------------------------------- CODE:00493FE6 CODE:00493FE6 loc_493FE6: ; CODE XREF: CODE:00493FC3↑j CODE:00493FE6 mov eax, offset _str_data_txt_1.Text CODE:00493FEB call @Sysutils@FileExists$qqrx17System@AnsiString ; Sysutils::FileExists(System::AnsiString) CODE:00493FF0 test al, al CODE:00493FF2 jz short loc_494010 CODE:00493FF4 mov dl, 1 CODE:00493FF6 mov eax, off_416648 CODE:00493FFB call TStreamCreate ; BDS 2005-2007 and Delphi6-7 Visual Component Library CODE:00494000 mov esi, eax CODE:00494002 mov edx, offset _str_data_txt_1.Text CODE:00494007 mov eax, esi CODE:00494009 call @Ibsql@TIBXSQLVAR@LoadFromFile$qqrx17System@AnsiString ; Ibsql::TIBXSQLVAR::LoadFromFile(System::AnsiString) CODE:0049400E jmp short loc_494025 CODE:00494010 ; --------------------------------------------------------------------------- CODE:00494010 CODE:00494010 loc_494010: ; CODE XREF: CODE:00493FF2↑j CODE:00494010 or ecx, 0FFFFFFFFh CODE:00494013 mov edx, offset _str_data_txt_1.Text CODE:00494018 mov eax, [ebx+330h] CODE:0049401E call GetVmpCode CODE:00494023 mov esi, eax CODE:00494025 CODE:00494025 loc_494025: ; CODE XREF: CODE:0049400E↑j CODE:00494025 mov edx, offset byte_494045 CODE:0049402A mov [ebp-4], edx CODE:0049402D mov eax, [ebp-4] CODE:00494030 push eax CODE:00494031 mov eax, [esi+4] CODE:00494034 push eax CODE:00494035 mov eax, ds:dword_498F3C CODE:0049403A push eax CODE:0049403B call sub_473A04 CODE:0049403B ; --------------------------------------------------------------------------- CODE:00494040 dd 0 CODE:00494044 db 0 CODE:00494045 byte_494045 db 0 ; DATA XREF: CODE:00493FC9↑o CODE:00494045 ; CODE:loc_494025↑o CODE:00494046 dd 0 CODE:0049404A align 4 CODE:0049404C dd 1Ah dup(0) CODE:004940B4 db 2 dup(0) CODE:004940B6 dd 0 CODE:004940BA align 4 CODE:004940BC dd 5 dup(0)
这个函数与去年的类似,程序对 地址 494045代码进行解密,里面存在一个反汇编引擎,对代码进行重定位,并一条一条执行,同时存在一个简单的VMP。
73 69 6D 76 6D 01 00 05 00 .......simvm.... 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 C5 3F 49 00 05 .............I.. 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 02 01 01 02 00 00 F0 00 00 00 00 F3 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 01 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F2 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 02 00 00 00 00 ................ 00 00 00 03 01 01 02 00 00 F0 00 00 00 00 F1 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 03 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F0 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 ................ 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF FF 00 ................ 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 00 00 ................ 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 6F 72 69 67 6E 83 C0 7F ........orign兝 . 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 00 00 3襰 imvm......... 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 00 00 ................ 00 00 F3 FF FF FF 00 00 00 00 03 6F 72 69 67 6E ...........orign 3B C2 75 52 73 69 6D 76 6D 01 00 07 00 00 F0 00 ;聈 Rsimvm....... 00 00 00 00 00 00 00 00 00 00 00 04 02 00 00 F0 ................ 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 01 ................ 07 00 00 F0 00 00 00 00 01 00 00 00 00 00 00 00 ................ 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D 76 6D .orign兝 .3襰 imvm 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 02 00 00 F0 00 00 00 00 F2 FF FF FF 00 ................ 00 00 00 03 6F 72 69 67 6E 3B C2 75 3F 73 69 6D ....orign;聈 ?sim 76 6D 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 00 00 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF ................ FF 00 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 ................ 00 00 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 ................ 00 02 00 00 00 00 00 00 00 04 6F 72 69 67 6E 83 ..........orign. C0 7F 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 ..3襰 imvm....... 00 00 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 ................ 00 00 00 00 F1 FF FF FF 00 00 00 00 03 6F 72 69 .............ori 67 6E 3B C2 75 2C 73 69 6D 76 6D 01 00 07 00 00 gn;聈 ,simvm..... F0 00 00 00 00 00 00 00 00 00 00 00 00 04 02 00 ................ 00 F0 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 ................ 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 ................ 00 01 07 00 00 F0 00 00 00 00 03 00 00 00 00 00 ................ 00 00 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D ...orign兝 .3襰 im 76 6D 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 01 00 00 00 01 02 00 00 F0 00 00 00 00 F0 FF FF ................ FF 00 00 00 00 03 6F 72 69 67 6E 3B C2 75 19 8D ......orign;聈 .. 85 E0 FB FF FF 50 33 C9 73 69 6D 76 6D 01 00 05 呧 ...P3蓅 imvm... 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 E8 41 49 00 ............鐰 I. 05 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 04 04 00 00 F0 00 00 00 00 34 03 00 00 ............4... 00 00 00 00 06 6F 72 69 67 6E E8 27 DD FF FF EB .....orign...... 09 73 69 6D 76 6D 65 6E 64 00 .simvmend
上面是指令码,其中带有 simvm 标识的为VMP代码,带有orgin的为原始代码,对于simvm的代码走虚拟机执行引擎,对于orgin标识通过反编译引擎,并重定位执行。
493F70 会调用473A04 上面的逻辑主要在本函数执行。
CODE:00473A04 sub_473A04 proc near ; CODE XREF: CODE:0049403B↓p CODE:00473A04 CODE:00473A04 var_2C = dword ptr -2Ch CODE:00473A04 var_8 = dword ptr -8 CODE:00473A04 var_4 = dword ptr -4 CODE:00473A04 var_s0 = dword ptr 0 CODE:00473A04 arg_4 = dword ptr 0Ch CODE:00473A04 arg_8 = dword ptr 10h CODE:00473A04 CODE:00473A04 push ebp CODE:00473A05 mov ebp, esp CODE:00473A07 leave CODE:00473A08 push dword ptr [esp+0] CODE:00473A0B push [esp+var_s0] CODE:00473A0E push [esp+4+var_4] CODE:00473A11 pusha CODE:00473A12 pushf CODE:00473A13 call sub_4723EC CODE:00473A18 mov ebx, eax CODE:00473A1A xor eax, eax CODE:00473A1C mov [ebx+1050h], eax CODE:00473A22 mov eax, 0FFFFFFFFh CODE:00473A27 mov [ebx+1054h], eax CODE:00473A2D mov [esp+2Ch+var_8], ebx CODE:00473A31 mov eax, [esp+2Ch+arg_8] ; eax = encryptCodeAddr CODE:00473A35 mov [esp+2Ch+var_4], eax CODE:00473A39 mov eax, [esp+2Ch+arg_4] CODE:00473A3D mov [esp+2Ch+var_s0], eax CODE:00473A41 mov eax, [ebx+1090h] CODE:00473A47 cmp eax, 0 CODE:00473A4A jnz short loc_473A57 CODE:00473A4C mov eax, offset codeCrypt CODE:00473A51 mov [ebx+1090h], eax CODE:00473A57 CODE:00473A57 loc_473A57: ; CODE XREF: sub_473A04+46↑j CODE:00473A57 popf CODE:00473A58 popa CODE:00473A59 call HandleCode CODE:00473A5E pushf CODE:00473A5F pushf CODE:00473A60 pushf CODE:00473A61 pusha CODE:00473A62 pushf CODE:00473A63 jmp short loc_473A89 CODE:00473A65 ; --------------------------------------------------------------------------- CODE:00473A65 CODE:00473A65 loc_473A65: ; CODE XREF: sub_473A04+98↓j CODE:00473A65 mov eax, [ebx+1058h] CODE:00473A6B mov [esp+2Ch+var_s0], eax CODE:00473A6F mov eax, [ebx+1050h] CODE:00473A75 mov [esp+2Ch+var_4], eax CODE:00473A79 mov [esp+2Ch+var_8], ebx CODE:00473A7D popf CODE:00473A7E popa CODE:00473A7F call HandleCode CODE:00473A84 pushf CODE:00473A85 pushf CODE:00473A86 pushf CODE:00473A87 pusha CODE:00473A88 pushf CODE:00473A89 CODE:00473A89 loc_473A89: ; CODE XREF: sub_473A04+5F↑j CODE:00473A89 call sub_4723EC CODE:00473A8E mov ebx, eax CODE:00473A90 mov eax, [ebx+1050h] CODE:00473A96 cmp eax, [ebx+1054h] CODE:00473A9C jb short loc_473A65 CODE:00473A9E mov eax, [ebx+1050h] CODE:00473AA4 mov [esp+30h], eax CODE:00473AA8 mov eax, [esp+2Ch+var_2C] CODE:00473AAB mov [esp+2Ch+var_s0], eax CODE:00473AAF popf CODE:00473AB0 popa CODE:00473AB1 add esp, 8 CODE:00473AB4 popf CODE:00473AB5 retn 0Ch CODE:00473AB5 sub_473A04 endp CODE:00473AB5
而其核心函数为HandleCode(472EAC)
int __usercall HandleCode@<eax>(int a1@<ebx>, int a2@<edi>, int a3@<esi>, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15) { unsigned int v15; // et0 int (__fastcall *v16)(unsigned int *); // ST10_4 unsigned int v18; // [esp+10h] [ebp-30h] int v19; // [esp+30h] [ebp-10h] void **v20; // [esp+34h] [ebp-Ch] int *v21; // [esp+38h] [ebp-8h] int v22; // [esp+3Ch] [ebp-4h] unsigned int vars0; // [esp+40h] [ebp+0h] void *retaddr; // [esp+44h] [ebp+4h] vars0 = a3; v22 = a2; v21 = (int *)&vars0; v20 = &retaddr; v19 = a1; v15 = __readeflags(); *(_DWORD *)(a13 + 4188) = retaddr; DecryptData(a13, a14, a12, (char *)a15, &v21, (int *)&v20, &v19); vars0 = v18; __writeeflags(v18); __writeeflags(v18); return v16(&vars0); }
其中 "16(&vars0);"语句为执行重定位后的代码。而虚拟机以及原始代码重定位在DecryptData函数(472EAC)如下
DWORD *__stdcall DecryptData(int a1, int orgAddr, int a3, char *dataOfFile, _DWORD *a5, int *a6, _DWORD *a7) { _DWORD *global; // ebx int v8; // esi int v9; // edi int v10; // eax int v11; // ecx int v12; // esi int v13; // esi int v14; // eax int v15; // ST18_4 unsigned int v17; // [esp+1Ch] [ebp-77Ch] void *v18; // [esp+20h] [ebp-778h] int *v19; // [esp+24h] [ebp-774h] int v20; // [esp+34h] [ebp-764h] int v21; // [esp+38h] [ebp-760h] char data[1024]; // [esp+3Fh] [ebp-759h] int v23; // [esp+440h] [ebp-358h] char v24; // [esp+444h] [ebp-354h] char v25; // [esp+544h] [ebp-254h] unsigned __int8 orgCodeLen; // [esp+77Ah] [ebp-1Eh] char v27; // [esp+77Bh] [ebp-1Dh] char *nextData; // [esp+77Ch] [ebp-1Ch] char *data1; // [esp+780h] [ebp-18h] _BYTE *v30; // [esp+784h] [ebp-14h] int outDataLen; // [esp+788h] [ebp-10h] int v32; // [esp+78Ch] [ebp-Ch] int opCodeLen; // [esp+790h] [ebp-8h] _DWORD *v34; // [esp+794h] [ebp-4h] int vars0; // [esp+798h] [ebp+0h] v21 = 0; v20 = 0; v30 = 0; v19 = &vars0; v18 = &loc_4732B2; v17 = __readfsdword(0); __writefsdword(0, (unsigned int)&v17); global = sub_4723EC(); v34 = (_DWORD *)(vars0 + 8); data1 = data; v8 = *(_DWORD *)off_497644; *(_DWORD *)(*(_DWORD *)off_497644 + 52) = 0; v27 = 0; while ( 1 ) { callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); while ( 1 ) { while ( *(_DWORD *)(v8 + 52) == 1 ) { orgCodeLen = 0; nextData = callVmpHandle(v8, (_BYTE *)orgAddr, data, (int)&orgCodeLen); opCodeLen = nextData - data; GetNextValueByLen(&dataOfFile, nextData - data); GetNextValueByLen(&orgAddr, orgCodeLen); callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); } if ( ifCode_simvm_orign(v8, &data1) != 1 )// 不是 simvm break; data1 = data; v27 = 1; simvm_Handle(global, v34); } data1 = data; if ( !v27 ) break; v27 = 0; orgin_Handle(global, v34); } outDataLen = off_498CA0(data, outDataLen, 0x400000, &v23, 4, v17);// 执行原始code *a5 = outDataLen; v9 = unknown_libname_29(32 - outDataLen - 6); data1 = (char *)global + v9 + 4144; sub_464FA4(data1, data, outDataLen); *((_BYTE *)global + v9 + outDataLen + 4144) = 104; GetCharFormTstring((int)&v30, &v25); if ( (unsigned __int8)sub_472520(v30, global[1047]) ) { GetCharFormTstring((int)&v30, &v24); opCodeLen = sub_465C88((int)&str___29[1], (int)v30); v10 = GetJSLen(v30); System::__linkproc__ LStrCopy((int)v30, opCodeLen + 1, v10 - opCodeLen, (int)&v30); opCodeLen = sub_465CEC(v30); if ( outDataLen - 1 >= 0 ) { v11 = outDataLen; v32 = 0; do { *((_BYTE *)global + v9 + v32++ + 4144) = -112; --v11; } while ( v11 ); } opCodeLen += outDataLen; v12 = sub_471F04(v8, data, opCodeLen); } else if ( sub_465C88((int)&str_CALL_0[1], (int)v30) == 1 ) { GetCharFormTstring((int)&v30, &v24); if ( sub_465C88((int)&str_FF_0[1], (int)v30) != 1 ) { opCodeLen = sub_465C88((int)&str___29[1], (int)v30); v32 = opCodeLen - 1; v13 = (opCodeLen - 1) / 2; data1 = (char *)global + v9 + v13 + 4144; v14 = GetJSLen(v30); System::__linkproc__ LStrCopy((int)v30, opCodeLen + 1, v14 - opCodeLen, (int)&v30); opCodeLen = sub_465CEC(v30); v32 = opCodeLen + orgAddr - ((_DWORD)global + v9 + 4144); sub_464FA4(data1, &v32, outDataLen - v13); } opCodeLen = outDataLen; v12 = outDataLen; } else { opCodeLen = outDataLen; v12 = outDataLen; } *a7 = opCodeLen; opCodeLen = a3; data1 = (char *)global + v9 + outDataLen + 4145; sub_464FA4(data1, &opCodeLen, 4u); *((_BYTE *)global + v9 + outDataLen + 4149) = 0xC3u; *a6 = (int)global + v9 + 0x1030; global[1044] = orgAddr + *a7; global[1046] = &dataOfFile[v12]; GetCharFormTstring((int)&v21, &v25); v15 = v21; GetCharFormTstring((int)&v20, &v24); sub_4736D4((int)global, *a6, orgAddr, v15, v20, outDataLen); __writefsdword(0, v17); v19 = (int *)&loc_4732B9; System::__linkproc__ LStrArrayClr(&v20, 2); return System::__linkproc__ LStrClr(&v30); }
其中如下代码为执行VMP代码
while ( 1 ) { callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); while ( 1 ) { while ( *(_DWORD *)(v8 + 52) == 1 ) { orgCodeLen = 0; nextData = callVmpHandle(v8, (_BYTE *)orgAddr, data, (int)&orgCodeLen); opCodeLen = nextData - data; GetNextValueByLen(&dataOfFile, nextData - data); GetNextValueByLen(&orgAddr, orgCodeLen); callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); } if ( ifCode_simvm_orign(v8, &data1) != 1 )// 不是 simvm break; data1 = data; v27 = 1; simvm_Handle(global, v34); } data1 = data; if ( !v27 ) break; v27 = 0; orgin_Handle(global, v34); }
后半部分为执行原始代码,进行反编译从定位。
下面是虚拟程序相关函数:
char *__fastcall callVmpHandle(int unknowGlogal, _BYTE *orgAddr, _BYTE *data, int global) { int unknowGlogal_1; // ebx char *data_2; // [esp+4h] [ebp-8h] char *data_1; // [esp+8h] [ebp-4h] data_1 = data; unknowGlogal_1 = unknowGlogal; data_2 = data; if ( *(_DWORD *)(unknowGlogal + 52) == 1 ) { if ( ifCode_simvm_orign(unknowGlogal, &data_1) == 2 ) { data_2 = data_1; // orgin } else { data_2 = data_1; if ( *data_1 == byte_497214 ) data_2 = vmpHandle(unknowGlogal_1, data_1, (char *)global); else *(_DWORD *)(unknowGlogal_1 + 52) = 2; } } return data_2; } char *__fastcall vmpHandle(int unknowGlogal, char *data, char *a3) { char *v3; // ST1C_4 int unknowGlogal_1; // edi char num0Data; // bl int num6Data; // ebp char *dataEnd; // [esp+4h] [ebp-38h] char num5Data; // [esp+8h] [ebp-34h] int num7Data; // [esp+Ch] [ebp-30h] int num8Data; // [esp+10h] [ebp-2Ch] int num9Data; // [esp+14h] [ebp-28h] int num1Data; // [esp+18h] [ebp-24h] int num2Data; // [esp+1Ch] [ebp-20h] int num3Data; // [esp+20h] [ebp-1Ch] int num4Data; // [esp+24h] [ebp-18h] char *data_1; // [esp+28h] [ebp-14h] v3 = a3; unknowGlogal_1 = unknowGlogal; dataEnd = data + 0x24; data_1 = data; GetNextValueByLen(&data_1, 1); num0Data = *data_1; GetNextValueByLen(&data_1, 1); num1Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num2Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num3Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num4Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num5Data = *data_1; GetNextValueByLen(&data_1, 1); num6Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num7Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num8Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num9Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); *v3 = *data_1; if ( num0Data || num5Data ) { if ( num0Data && num5Data ) { sub_471CDC(num0Data, num9Data, num8Data, num7Data, num6Data, num4Data, num3Data); } else if ( !num0Data || num5Data ) { if ( !num0Data && num5Data ) call_vmp_add_reg_value( unknowGlogal_1, num1Data, num2Data, num3Data, num4Data, num6Data, num7Data, num8Data, num9Data, num5Data); } else { call_vmp_memcpy_regAndReg_num( unknowGlogal_1, num1Data, num2Data, num3Data, num4Data, num6Data, num7Data, num8Data, num9Data, num0Data); } } else { sub_471C08(unknowGlogal_1, num1Data, num2Data, num3Data, num4Data, num6Data, num7Data, num8Data, num9Data, 0); } return dataEnd; }
int __fastcall call_vmp_add_reg_value(int unknowGlogal, int num1Data, int num2Data, int num3Data, int num4Data, int num6Data, int num7Data, int num8Data, int num9Data, char num5Data) { if ( num1Data && num6Data ) return vmp_add_reg_value(unknowGlogal, num1Data, num3Data, num6Data, num8Data, num5Data); if ( num1Data && num7Data ) return vmp_add_reg_value(unknowGlogal, num1Data, num3Data, num7Data, num8Data, num5Data); if ( num1Data && num9Data ) return vmp_add_reg_value(unknowGlogal, num1Data, num3Data, num9Data, 0, 0); if ( num2Data && num6Data ) return vmp_add_reg_value(unknowGlogal, num2Data, num3Data, num6Data, num8Data, num5Data); if ( num2Data && num7Data ) return vmp_add_reg_value(unknowGlogal, num2Data, num3Data, num7Data, num8Data, num5Data); if ( num2Data ) { if ( num9Data ) unknowGlogal = vmp_add_reg_value(unknowGlogal, num2Data, num3Data, num9Data, 0, 0); } return unknowGlogal; }
就是一些简单的寄存器读取以及加减乘除运算。
下面的函数是针对代码解密的,就是异或0xFF.
DWORD *__fastcall codeCrypt(int a1, int dataOfFile, char *outData, _DWORD *a4) { int v4; // ecx char v5; // zf _DWORD *v6; // eax unsigned int v8; // [esp+8h] [ebp-20h] void *v9; // [esp+Ch] [ebp-1Ch] int *v10; // [esp+10h] [ebp-18h] int v11; // [esp+20h] [ebp-8h] char *outData1; // [esp+24h] [ebp-4h] int savedregs; // [esp+28h] [ebp+0h] v11 = 0; v10 = &savedregs; v9 = &loc_473839; v8 = __readfsdword(0); __writefsdword(0, (unsigned int)&v8); *a4 = 0x400; outData1 = outData; v4 = 0; do { outData1[v4] = ~*(_BYTE *)(dataOfFile + v4); ++v4; } while ( v4 != 0x400 ); GetCharFormTstring((int)&v11, outData1 + 2); System::__linkproc__ LStrCmp(v11, &str_simvmend[1]._top); if ( v5 ) // 判断代码是否结束 { v6 = sub_4723EC(); v6[0x415] = v6[0x414]; } __writefsdword(0, v8); v10 = (int *)&loc_473840; return System::__linkproc__ LStrClr(&v11); }
三、sn
如下vm指令的主要功能就是解密最后的字符串"a123"
73 69 6D 76 6D 01 00 05 00 .......simvm.... 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 C5 3F 49 00 05 .............I.. 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 02 01 01 02 00 00 F0 00 00 00 00 F3 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 01 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F2 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 02 00 00 00 00 ................ 00 00 00 03 01 01 02 00 00 F0 00 00 00 00 F1 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 03 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F0 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 ................ 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF FF 00 ................ 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 00 00 ................ 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 6F 72 69 67 6E 83 C0 7F ........orign兝 . 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 00 00 3襰 imvm......... 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 00 00 ................ 00 00 F3 FF FF FF 00 00 00 00 03 6F 72 69 67 6E ...........orign 3B C2 75 52 73 69 6D 76 6D 01 00 07 00 00 F0 00 ;聈 Rsimvm....... 00 00 00 00 00 00 00 00 00 00 00 04 02 00 00 F0 ................ 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 01 ................ 07 00 00 F0 00 00 00 00 01 00 00 00 00 00 00 00 ................ 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D 76 6D .orign兝 .3襰 imvm 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 02 00 00 F0 00 00 00 00 F2 FF FF FF 00 ................ 00 00 00 03 6F 72 69 67 6E 3B C2 75 3F 73 69 6D ....orign;聈 ?sim 76 6D 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 00 00 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF ................ FF 00 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 ................ 00 00 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 ................ 00 02 00 00 00 00 00 00 00 04 6F 72 69 67 6E 83 ..........orign. C0 7F 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 ..3襰 imvm....... 00 00 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 ................ 00 00 00 00 F1 FF FF FF 00 00 00 00 03 6F 72 69 .............ori 67 6E 3B C2 75 2C 73 69 6D 76 6D 01 00 07 00 00 gn;聈 ,simvm..... F0 00 00 00 00 00 00 00 00 00 00 00 00 04 02 00 ................ 00 F0 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 ................ 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 ................ 00 01 07 00 00 F0 00 00 00 00 03 00 00 00 00 00 ................ 00 00 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D ...orign兝 .3襰 im 76 6D 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 01 00 00 00 01 02 00 00 F0 00 00 00 00 F0 FF FF ................ FF 00 00 00 00 03 6F 72 69 67 6E 3B C2 75 19 8D ......orign;聈 .. 85 E0 FB FF FF 50 33 C9 73 69 6D 76 6D 01 00 05 呧 ...P3蓅 imvm... 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 E8 41 49 00 ............鐰 I. 05 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 04 04 00 00 F0 00 00 00 00 34 03 00 00 ............4... 00 00 00 00 06 6F 72 69 67 6E E8 27 DD FF FF EB .....orign...... 09 73 69 6D 76 6D 65 6E 64 00 .simvmend
sn为 :simpower91a123
function sptWBCallback(spt_wb_id,spt_wb_name,optionstr) { url='#sptWBCallback:id='; url=url+spt_wb_id+'; eventName='+spt_wb_name; if(optionstr) url=url+'; params=optionstr'; location=url; }
上面代码应该是WebBrowser JS回调delphi的方法。因此真正的检测应该仍然在dephi主程序中。需要找到注册时间的回调函数。分析IDA反汇编代码发下如下:
CODE:00491DCC sub_491DCC proc near ; CODE XREF: _Tfrmcrackme_FormCreate+81↓p CODE:00491DCC push ebx CODE:00491DCD mov ebx, eax CODE:00491DCF mov eax, ebx CODE:00491DD1 call sub_491B78 ; call function CODE:00491DD6 mov eax, [ebx+40h] CODE:00491DD9 mov [eax+2A4h], ebx CODE:00491DDF mov dword ptr [eax+2A0h], offset sub_492088 CODE:00491DE9 pop ebx CODE:00491DEA retn CODE:00491DEA sub_491DCC endp
其中sub_492088函数比较可疑。设置个断点,输入 “
simpower91111
”果然断了下了。
二、回调
sub_492088
int __userpurge sub_492088@<eax>(int a1@<eax>, int a2@<edx>, int a3@<ecx>, int a4@<ebx>, int a5@<esi>, int edi0@<edi>, _WORD *a6, int a7, int a8, int a9, int a10, int a11) { int v12; // ebx int v13; // esi int v14; // eax int v15; // eax Classes::TStrings *v16; // esi int v17; // ST14_4 int v18; // ST10_4 unsigned int v20; // [esp-14h] [ebp-34h] void *v21; // [esp-10h] [ebp-30h] int *v22; // [esp-Ch] [ebp-2Ch] int v23; // [esp-8h] [ebp-28h] int v24; // [esp-4h] [ebp-24h] int v25; // [esp+0h] [ebp-20h] int v26; // [esp+4h] [ebp-1Ch] int v27; // [esp+8h] [ebp-18h] char v28[4]; // [esp+Ch] [ebp-14h] int v29; // [esp+10h] [ebp-10h] int System::AnsiString; // [esp+14h] [ebp-Ch] int v31; // [esp+18h] [ebp-8h] int v32; // [esp+1Ch] [ebp-4h] int savedregs; // [esp+20h] [ebp+0h] System::AnsiString = 0; v29 = 0; *(_DWORD *)v28 = 0; v27 = 0; v26 = 0; v25 = 0; v24 = a4; v23 = a5; v31 = a3; v32 = a2; v12 = a1; v22 = &savedregs; v21 = &loc_4921D1; v20 = __readfsdword(0); __writefsdword(0, (unsigned int)&v20); Variants::__linkproc__ VarToLStr(&v29, a11); v13 = sub_465C88((int)&str__sptWBCallback_[1], v29); if ( v13 > 0 ) { *a6 = -1; Variants::__linkproc__ VarToLStr(&System::AnsiString, a11); v14 = GetJSLen(System::AnsiString); v15 = System::__linkproc__ LStrCopy(System::AnsiString, v13 + 15, v14 - v13 - 14, (int)&System::AnsiString); LOBYTE(v15) = 1; unknown_libname_161(System::AnsiString, (int)&str___41[1], (int)&str____19[1], v12, edi0, v13, (int)v28, v15); System::__linkproc__ LStrLAsg(&System::AnsiString, *(signed __int32 *)v28); v16 = (Classes::TStrings *)TStreamCreate((int)cls_Classes_TStringList, 1); (*(void (__fastcall **)(Classes::TStrings *, int))(*(_DWORD *)v16 + 44))(v16, System::AnsiString); if ( *(_WORD *)(v12 + 50) ) { Classes::TStrings::GetValue(v16, (const int)&str_params[1], (int)&v27); v17 = v27; Classes::TStrings::GetValue(v16, (const int)&str_eventName[1], (int)&v26); v18 = v26; Classes::TStrings::GetValue(v16, (const int)&str_id[1], (int)&v25); (*(void (__fastcall **)(_DWORD, int, int, int))(v12 + 48))(*(_DWORD *)(v12 + 52), v25, v18, v17); } } if ( *(_WORD *)(v12 + 58) ) (*(void (__fastcall **)(_DWORD, int, int, int, int, int, int, int, _WORD *))(v12 + 0x38))( *(_DWORD *)(v12 + 60), v32, v31, a11, a10, a9, a8, a7, a6); __writefsdword(0, v20); v22 = (int *)&loc_4921D8; return System::__linkproc__ LStrArrayClr(&v25, 6); }
核心处理函数为 V12+0X38,地址为;493F70
三、 493F70函数
loc_493F70: ; DATA XREF: _Tfrmcrackme_FormCreate+87↑o CODE:00493F70 push ebp CODE:00493F71 mov ebp, esp CODE:00493F73 CODE:00493F73 loc_493F73: ; CODE XREF: CODE:00493FC5↓j CODE:00493F73 add esp, 0FFFFFBD8h CODE:00493F79 push ebx CODE:00493F7A push esi CODE:00493F7B xor ebx, ebx CODE:00493F7D mov [ebp-428h], ebx CODE:00493F83 mov [ebp-424h], ebx CODE:00493F89 mov [ebp-420h], ebx CODE:00493F8F mov [ebp-14h], edx CODE:00493F92 mov ebx, eax CODE:00493F94 mov eax, [ebp-14h] CODE:00493F97 call @System@@LStrAddRef$qqrpv ; System::__linkproc__ LStrAddRef(void *) CODE:00493F9C mov eax, [ebp+8] CODE:00493F9F call @System@@LStrAddRef$qqrpv ; System::__linkproc__ LStrAddRef(void *) CODE:00493FA4 xor eax, eax CODE:00493FA6 push ebp CODE:00493FA7 push offset loc_4941BA CODE:00493FAC push dword ptr fs:[eax] CODE:00493FAF mov fs:[eax], esp CODE:00493FB2 mov eax, [ebp-14h] CODE:00493FB5 call GetJSLen ; BDS 2005-2007 and Delphi6-7 Visual Component Library CODE:00493FBA cmp eax, 4 CODE:00493FBD jnz loc_494181 CODE:00493FC3 jmp short loc_493FE6 CODE:00493FC5 ; --------------------------------------------------------------------------- CODE:00493FC5 loopne near ptr loc_493F73+4 CODE:00493FC7 mov cl, 0B2h CODE:00493FC9 mov edx, offset byte_494045 CODE:00493FCE mov [ebp-4], edx CODE:00493FD1 mov edx, offset loc_4940D0 CODE:00493FD6 mov [ebp-8], edx CODE:00493FD9 mov edx, offset dword_494168 CODE:00493FDE mov [ebp-0Ch], edx CODE:00493FE1 jmp loc_4940DA CODE:00493FE6 ; --------------------------------------------------------------------------- CODE:00493FE6 CODE:00493FE6 loc_493FE6: ; CODE XREF: CODE:00493FC3↑j CODE:00493FE6 mov eax, offset _str_data_txt_1.Text CODE:00493FEB call @Sysutils@FileExists$qqrx17System@AnsiString ; Sysutils::FileExists(System::AnsiString) CODE:00493FF0 test al, al CODE:00493FF2 jz short loc_494010 CODE:00493FF4 mov dl, 1 CODE:00493FF6 mov eax, off_416648 CODE:00493FFB call TStreamCreate ; BDS 2005-2007 and Delphi6-7 Visual Component Library CODE:00494000 mov esi, eax CODE:00494002 mov edx, offset _str_data_txt_1.Text CODE:00494007 mov eax, esi CODE:00494009 call @Ibsql@TIBXSQLVAR@LoadFromFile$qqrx17System@AnsiString ; Ibsql::TIBXSQLVAR::LoadFromFile(System::AnsiString) CODE:0049400E jmp short loc_494025 CODE:00494010 ; --------------------------------------------------------------------------- CODE:00494010 CODE:00494010 loc_494010: ; CODE XREF: CODE:00493FF2↑j CODE:00494010 or ecx, 0FFFFFFFFh CODE:00494013 mov edx, offset _str_data_txt_1.Text CODE:00494018 mov eax, [ebx+330h] CODE:0049401E call GetVmpCode CODE:00494023 mov esi, eax CODE:00494025 CODE:00494025 loc_494025: ; CODE XREF: CODE:0049400E↑j CODE:00494025 mov edx, offset byte_494045 CODE:0049402A mov [ebp-4], edx CODE:0049402D mov eax, [ebp-4] CODE:00494030 push eax CODE:00494031 mov eax, [esi+4] CODE:00494034 push eax CODE:00494035 mov eax, ds:dword_498F3C CODE:0049403A push eax CODE:0049403B call sub_473A04 CODE:0049403B ; --------------------------------------------------------------------------- CODE:00494040 dd 0 CODE:00494044 db 0 CODE:00494045 byte_494045 db 0 ; DATA XREF: CODE:00493FC9↑o CODE:00494045 ; CODE:loc_494025↑o CODE:00494046 dd 0 CODE:0049404A align 4 CODE:0049404C dd 1Ah dup(0) CODE:004940B4 db 2 dup(0) CODE:004940B6 dd 0 CODE:004940BA align 4 CODE:004940BC dd 5 dup(0)
这个函数与去年的类似,程序对 地址 494045代码进行解密,里面存在一个反汇编引擎,对代码进行重定位,并一条一条执行,同时存在一个简单的VMP。
73 69 6D 76 6D 01 00 05 00 .......simvm.... 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 C5 3F 49 00 05 .............I.. 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 02 01 01 02 00 00 F0 00 00 00 00 F3 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 01 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F2 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 02 00 00 00 00 ................ 00 00 00 03 01 01 02 00 00 F0 00 00 00 00 F1 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 03 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F0 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 ................ 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF FF 00 ................ 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 00 00 ................ 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 6F 72 69 67 6E 83 C0 7F ........orign兝 . 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 00 00 3襰 imvm......... 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 00 00 ................ 00 00 F3 FF FF FF 00 00 00 00 03 6F 72 69 67 6E ...........orign 3B C2 75 52 73 69 6D 76 6D 01 00 07 00 00 F0 00 ;聈 Rsimvm....... 00 00 00 00 00 00 00 00 00 00 00 04 02 00 00 F0 ................ 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 01 ................ 07 00 00 F0 00 00 00 00 01 00 00 00 00 00 00 00 ................ 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D 76 6D .orign兝 .3襰 imvm 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 02 00 00 F0 00 00 00 00 F2 FF FF FF 00 ................ 00 00 00 03 6F 72 69 67 6E 3B C2 75 3F 73 69 6D ....orign;聈 ?sim 76 6D 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 00 00 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF ................ FF 00 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 ................ 00 00 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 ................ 00 02 00 00 00 00 00 00 00 04 6F 72 69 67 6E 83 ..........orign. C0 7F 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 ..3襰 imvm....... 00 00 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 ................ 00 00 00 00 F1 FF FF FF 00 00 00 00 03 6F 72 69 .............ori 67 6E 3B C2 75 2C 73 69 6D 76 6D 01 00 07 00 00 gn;聈 ,simvm..... F0 00 00 00 00 00 00 00 00 00 00 00 00 04 02 00 ................ 00 F0 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 ................ 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 ................ 00 01 07 00 00 F0 00 00 00 00 03 00 00 00 00 00 ................ 00 00 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D ...orign兝 .3襰 im 76 6D 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 01 00 00 00 01 02 00 00 F0 00 00 00 00 F0 FF FF ................ FF 00 00 00 00 03 6F 72 69 67 6E 3B C2 75 19 8D ......orign;聈 .. 85 E0 FB FF FF 50 33 C9 73 69 6D 76 6D 01 00 05 呧 ...P3蓅 imvm... 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 E8 41 49 00 ............鐰 I. 05 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 04 04 00 00 F0 00 00 00 00 34 03 00 00 ............4... 00 00 00 00 06 6F 72 69 67 6E E8 27 DD FF FF EB .....orign...... 09 73 69 6D 76 6D 65 6E 64 00 .simvmend
上面是指令码,其中带有 simvm 标识的为VMP代码,带有orgin的为原始代码,对于simvm的代码走虚拟机执行引擎,对于orgin标识通过反编译引擎,并重定位执行。
493F70 会调用473A04 上面的逻辑主要在本函数执行。
CODE:00473A04 sub_473A04 proc near ; CODE XREF: CODE:0049403B↓p CODE:00473A04 CODE:00473A04 var_2C = dword ptr -2Ch CODE:00473A04 var_8 = dword ptr -8 CODE:00473A04 var_4 = dword ptr -4 CODE:00473A04 var_s0 = dword ptr 0 CODE:00473A04 arg_4 = dword ptr 0Ch CODE:00473A04 arg_8 = dword ptr 10h CODE:00473A04 CODE:00473A04 push ebp CODE:00473A05 mov ebp, esp CODE:00473A07 leave CODE:00473A08 push dword ptr [esp+0] CODE:00473A0B push [esp+var_s0] CODE:00473A0E push [esp+4+var_4] CODE:00473A11 pusha CODE:00473A12 pushf CODE:00473A13 call sub_4723EC CODE:00473A18 mov ebx, eax CODE:00473A1A xor eax, eax CODE:00473A1C mov [ebx+1050h], eax CODE:00473A22 mov eax, 0FFFFFFFFh CODE:00473A27 mov [ebx+1054h], eax CODE:00473A2D mov [esp+2Ch+var_8], ebx CODE:00473A31 mov eax, [esp+2Ch+arg_8] ; eax = encryptCodeAddr CODE:00473A35 mov [esp+2Ch+var_4], eax CODE:00473A39 mov eax, [esp+2Ch+arg_4] CODE:00473A3D mov [esp+2Ch+var_s0], eax CODE:00473A41 mov eax, [ebx+1090h] CODE:00473A47 cmp eax, 0 CODE:00473A4A jnz short loc_473A57 CODE:00473A4C mov eax, offset codeCrypt CODE:00473A51 mov [ebx+1090h], eax CODE:00473A57 CODE:00473A57 loc_473A57: ; CODE XREF: sub_473A04+46↑j CODE:00473A57 popf CODE:00473A58 popa CODE:00473A59 call HandleCode CODE:00473A5E pushf CODE:00473A5F pushf CODE:00473A60 pushf CODE:00473A61 pusha CODE:00473A62 pushf CODE:00473A63 jmp short loc_473A89 CODE:00473A65 ; --------------------------------------------------------------------------- CODE:00473A65 CODE:00473A65 loc_473A65: ; CODE XREF: sub_473A04+98↓j CODE:00473A65 mov eax, [ebx+1058h] CODE:00473A6B mov [esp+2Ch+var_s0], eax CODE:00473A6F mov eax, [ebx+1050h] CODE:00473A75 mov [esp+2Ch+var_4], eax CODE:00473A79 mov [esp+2Ch+var_8], ebx CODE:00473A7D popf CODE:00473A7E popa CODE:00473A7F call HandleCode CODE:00473A84 pushf CODE:00473A85 pushf CODE:00473A86 pushf CODE:00473A87 pusha CODE:00473A88 pushf CODE:00473A89 CODE:00473A89 loc_473A89: ; CODE XREF: sub_473A04+5F↑j CODE:00473A89 call sub_4723EC CODE:00473A8E mov ebx, eax CODE:00473A90 mov eax, [ebx+1050h] CODE:00473A96 cmp eax, [ebx+1054h] CODE:00473A9C jb short loc_473A65 CODE:00473A9E mov eax, [ebx+1050h] CODE:00473AA4 mov [esp+30h], eax CODE:00473AA8 mov eax, [esp+2Ch+var_2C] CODE:00473AAB mov [esp+2Ch+var_s0], eax CODE:00473AAF popf CODE:00473AB0 popa CODE:00473AB1 add esp, 8 CODE:00473AB4 popf CODE:00473AB5 retn 0Ch CODE:00473AB5 sub_473A04 endp CODE:00473AB5
而其核心函数为HandleCode(472EAC)
int __usercall HandleCode@<eax>(int a1@<ebx>, int a2@<edi>, int a3@<esi>, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15) { unsigned int v15; // et0 int (__fastcall *v16)(unsigned int *); // ST10_4 unsigned int v18; // [esp+10h] [ebp-30h] int v19; // [esp+30h] [ebp-10h] void **v20; // [esp+34h] [ebp-Ch] int *v21; // [esp+38h] [ebp-8h] int v22; // [esp+3Ch] [ebp-4h] unsigned int vars0; // [esp+40h] [ebp+0h] void *retaddr; // [esp+44h] [ebp+4h] vars0 = a3; v22 = a2; v21 = (int *)&vars0; v20 = &retaddr; v19 = a1; v15 = __readeflags(); *(_DWORD *)(a13 + 4188) = retaddr; DecryptData(a13, a14, a12, (char *)a15, &v21, (int *)&v20, &v19); vars0 = v18; __writeeflags(v18); __writeeflags(v18); return v16(&vars0); }
其中 "16(&vars0);"语句为执行重定位后的代码。而虚拟机以及原始代码重定位在DecryptData函数(472EAC)如下
DWORD *__stdcall DecryptData(int a1, int orgAddr, int a3, char *dataOfFile, _DWORD *a5, int *a6, _DWORD *a7) { _DWORD *global; // ebx int v8; // esi int v9; // edi int v10; // eax int v11; // ecx int v12; // esi int v13; // esi int v14; // eax int v15; // ST18_4 unsigned int v17; // [esp+1Ch] [ebp-77Ch] void *v18; // [esp+20h] [ebp-778h] int *v19; // [esp+24h] [ebp-774h] int v20; // [esp+34h] [ebp-764h] int v21; // [esp+38h] [ebp-760h] char data[1024]; // [esp+3Fh] [ebp-759h] int v23; // [esp+440h] [ebp-358h] char v24; // [esp+444h] [ebp-354h] char v25; // [esp+544h] [ebp-254h] unsigned __int8 orgCodeLen; // [esp+77Ah] [ebp-1Eh] char v27; // [esp+77Bh] [ebp-1Dh] char *nextData; // [esp+77Ch] [ebp-1Ch] char *data1; // [esp+780h] [ebp-18h] _BYTE *v30; // [esp+784h] [ebp-14h] int outDataLen; // [esp+788h] [ebp-10h] int v32; // [esp+78Ch] [ebp-Ch] int opCodeLen; // [esp+790h] [ebp-8h] _DWORD *v34; // [esp+794h] [ebp-4h] int vars0; // [esp+798h] [ebp+0h] v21 = 0; v20 = 0; v30 = 0; v19 = &vars0; v18 = &loc_4732B2; v17 = __readfsdword(0); __writefsdword(0, (unsigned int)&v17); global = sub_4723EC(); v34 = (_DWORD *)(vars0 + 8); data1 = data; v8 = *(_DWORD *)off_497644; *(_DWORD *)(*(_DWORD *)off_497644 + 52) = 0; v27 = 0; while ( 1 ) { callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); while ( 1 ) { while ( *(_DWORD *)(v8 + 52) == 1 ) { orgCodeLen = 0; nextData = callVmpHandle(v8, (_BYTE *)orgAddr, data, (int)&orgCodeLen); opCodeLen = nextData - data; GetNextValueByLen(&dataOfFile, nextData - data); GetNextValueByLen(&orgAddr, orgCodeLen); callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); } if ( ifCode_simvm_orign(v8, &data1) != 1 )// 不是 simvm break; data1 = data; v27 = 1; simvm_Handle(global, v34); } data1 = data; if ( !v27 ) break; v27 = 0; orgin_Handle(global, v34); } outDataLen = off_498CA0(data, outDataLen, 0x400000, &v23, 4, v17);// 执行原始code *a5 = outDataLen; v9 = unknown_libname_29(32 - outDataLen - 6); data1 = (char *)global + v9 + 4144; sub_464FA4(data1, data, outDataLen); *((_BYTE *)global + v9 + outDataLen + 4144) = 104; GetCharFormTstring((int)&v30, &v25); if ( (unsigned __int8)sub_472520(v30, global[1047]) ) { GetCharFormTstring((int)&v30, &v24); opCodeLen = sub_465C88((int)&str___29[1], (int)v30); v10 = GetJSLen(v30); System::__linkproc__ LStrCopy((int)v30, opCodeLen + 1, v10 - opCodeLen, (int)&v30); opCodeLen = sub_465CEC(v30); if ( outDataLen - 1 >= 0 ) { v11 = outDataLen; v32 = 0; do { *((_BYTE *)global + v9 + v32++ + 4144) = -112; --v11; } while ( v11 ); } opCodeLen += outDataLen; v12 = sub_471F04(v8, data, opCodeLen); } else if ( sub_465C88((int)&str_CALL_0[1], (int)v30) == 1 ) { GetCharFormTstring((int)&v30, &v24); if ( sub_465C88((int)&str_FF_0[1], (int)v30) != 1 ) { opCodeLen = sub_465C88((int)&str___29[1], (int)v30); v32 = opCodeLen - 1; v13 = (opCodeLen - 1) / 2; data1 = (char *)global + v9 + v13 + 4144; v14 = GetJSLen(v30); System::__linkproc__ LStrCopy((int)v30, opCodeLen + 1, v14 - opCodeLen, (int)&v30); opCodeLen = sub_465CEC(v30); v32 = opCodeLen + orgAddr - ((_DWORD)global + v9 + 4144); sub_464FA4(data1, &v32, outDataLen - v13); } opCodeLen = outDataLen; v12 = outDataLen; } else { opCodeLen = outDataLen; v12 = outDataLen; } *a7 = opCodeLen; opCodeLen = a3; data1 = (char *)global + v9 + outDataLen + 4145; sub_464FA4(data1, &opCodeLen, 4u); *((_BYTE *)global + v9 + outDataLen + 4149) = 0xC3u; *a6 = (int)global + v9 + 0x1030; global[1044] = orgAddr + *a7; global[1046] = &dataOfFile[v12]; GetCharFormTstring((int)&v21, &v25); v15 = v21; GetCharFormTstring((int)&v20, &v24); sub_4736D4((int)global, *a6, orgAddr, v15, v20, outDataLen); __writefsdword(0, v17); v19 = (int *)&loc_4732B9; System::__linkproc__ LStrArrayClr(&v20, 2); return System::__linkproc__ LStrClr(&v30); }
其中如下代码为执行VMP代码
while ( 1 ) { callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); while ( 1 ) { while ( *(_DWORD *)(v8 + 52) == 1 ) { orgCodeLen = 0; nextData = callVmpHandle(v8, (_BYTE *)orgAddr, data, (int)&orgCodeLen); opCodeLen = nextData - data; GetNextValueByLen(&dataOfFile, nextData - data); GetNextValueByLen(&orgAddr, orgCodeLen); callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); } if ( ifCode_simvm_orign(v8, &data1) != 1 )// 不是 simvm break; data1 = data; v27 = 1; simvm_Handle(global, v34); } data1 = data; if ( !v27 ) break; v27 = 0; orgin_Handle(global, v34); }
后半部分为执行原始代码,进行反编译从定位。
下面是虚拟程序相关函数:
char *__fastcall callVmpHandle(int unknowGlogal, _BYTE *orgAddr, _BYTE *data, int global) { int unknowGlogal_1; // ebx char *data_2; // [esp+4h] [ebp-8h] char *data_1; // [esp+8h] [ebp-4h] data_1 = data; unknowGlogal_1 = unknowGlogal; data_2 = data; if ( *(_DWORD *)(unknowGlogal + 52) == 1 ) { if ( ifCode_simvm_orign(unknowGlogal, &data_1) == 2 ) { data_2 = data_1; // orgin } else { data_2 = data_1; if ( *data_1 == byte_497214 ) data_2 = vmpHandle(unknowGlogal_1, data_1, (char *)global); else *(_DWORD *)(unknowGlogal_1 + 52) = 2; } } return data_2; } char *__fastcall vmpHandle(int unknowGlogal, char *data, char *a3) { char *v3; // ST1C_4 int unknowGlogal_1; // edi char num0Data; // bl int num6Data; // ebp char *dataEnd; // [esp+4h] [ebp-38h] char num5Data; // [esp+8h] [ebp-34h] int num7Data; // [esp+Ch] [ebp-30h] int num8Data; // [esp+10h] [ebp-2Ch] int num9Data; // [esp+14h] [ebp-28h] int num1Data; // [esp+18h] [ebp-24h] int num2Data; // [esp+1Ch] [ebp-20h] int num3Data; // [esp+20h] [ebp-1Ch] int num4Data; // [esp+24h] [ebp-18h] char *data_1; // [esp+28h] [ebp-14h] v3 = a3; unknowGlogal_1 = unknowGlogal; dataEnd = data + 0x24; data_1 = data; GetNextValueByLen(&data_1, 1); num0Data = *data_1; GetNextValueByLen(&data_1, 1); num1Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num2Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num3Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num4Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num5Data = *data_1; GetNextValueByLen(&data_1, 1); num6Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num7Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num8Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); num9Data = *(_DWORD *)data_1; GetNextValueByLen(&data_1, 4); *v3 = *data_1; if ( num0Data || num5Data ) { if ( num0Data && num5Data ) { sub_471CDC(num0Data, num9Data, num8Data, num7Data, num6Data, num4Data, num3Data); } else if ( !num0Data || num5Data ) { if ( !num0Data && num5Data ) call_vmp_add_reg_value( unknowGlogal_1, num1Data, num2Data, num3Data, num4Data, num6Data, num7Data, num8Data, num9Data, num5Data); } else { call_vmp_memcpy_regAndReg_num( unknowGlogal_1, num1Data, num2Data, num3Data, num4Data, num6Data, num7Data, num8Data, num9Data, num0Data); } } else { sub_471C08(unknowGlogal_1, num1Data, num2Data, num3Data, num4Data, num6Data, num7Data, num8Data, num9Data, 0); } return dataEnd; }
int __fastcall call_vmp_add_reg_value(int unknowGlogal, int num1Data, int num2Data, int num3Data, int num4Data, int num6Data, int num7Data, int num8Data, int num9Data, char num5Data) { if ( num1Data && num6Data ) return vmp_add_reg_value(unknowGlogal, num1Data, num3Data, num6Data, num8Data, num5Data); if ( num1Data && num7Data ) return vmp_add_reg_value(unknowGlogal, num1Data, num3Data, num7Data, num8Data, num5Data); if ( num1Data && num9Data ) return vmp_add_reg_value(unknowGlogal, num1Data, num3Data, num9Data, 0, 0); if ( num2Data && num6Data ) return vmp_add_reg_value(unknowGlogal, num2Data, num3Data, num6Data, num8Data, num5Data); if ( num2Data && num7Data ) return vmp_add_reg_value(unknowGlogal, num2Data, num3Data, num7Data, num8Data, num5Data); if ( num2Data ) { if ( num9Data ) unknowGlogal = vmp_add_reg_value(unknowGlogal, num2Data, num3Data, num9Data, 0, 0); } return unknowGlogal; }
就是一些简单的寄存器读取以及加减乘除运算。
下面的函数是针对代码解密的,就是异或0xFF.
DWORD *__fastcall codeCrypt(int a1, int dataOfFile, char *outData, _DWORD *a4) { int v4; // ecx char v5; // zf _DWORD *v6; // eax unsigned int v8; // [esp+8h] [ebp-20h] void *v9; // [esp+Ch] [ebp-1Ch] int *v10; // [esp+10h] [ebp-18h] int v11; // [esp+20h] [ebp-8h] char *outData1; // [esp+24h] [ebp-4h] int savedregs; // [esp+28h] [ebp+0h] v11 = 0; v10 = &savedregs; v9 = &loc_473839; v8 = __readfsdword(0); __writefsdword(0, (unsigned int)&v8); *a4 = 0x400; outData1 = outData; v4 = 0; do { outData1[v4] = ~*(_BYTE *)(dataOfFile + v4); ++v4; } while ( v4 != 0x400 ); GetCharFormTstring((int)&v11, outData1 + 2); System::__linkproc__ LStrCmp(v11, &str_simvmend[1]._top); if ( v5 ) // 判断代码是否结束 { v6 = sub_4723EC(); v6[0x415] = v6[0x414]; } __writefsdword(0, v8); v10 = (int *)&loc_473840; return System::__linkproc__ LStrClr(&v11); }
三、sn
如下vm指令的主要功能就是解密最后的字符串"a123"
73 69 6D 76 6D 01 00 05 00 .......simvm.... 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 C5 3F 49 00 05 .............I.. 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 02 01 01 02 00 00 F0 00 00 00 00 F3 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 01 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F2 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 02 00 00 00 00 ................ 00 00 00 03 01 01 02 00 00 F0 00 00 00 00 F1 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 03 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F0 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 ................ 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF FF 00 ................ 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 00 00 ................ 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 6F 72 69 67 6E 83 C0 7F ........orign兝 . 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 00 00 3襰 imvm......... 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 00 00 ................ 00 00 F3 FF FF FF 00 00 00 00 03 6F 72 69 67 6E ...........orign 3B C2 75 52 73 69 6D 76 6D 01 00 07 00 00 F0 00 ;聈 Rsimvm....... 00 00 00 00 00 00 00 00 00 00 00 04 02 00 00 F0 ................ 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 01 ................ 07 00 00 F0 00 00 00 00 01 00 00 00 00 00 00 00 ................ 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D 76 6D .orign兝 .3襰 imvm 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 02 00 00 F0 00 00 00 00 F2 FF FF FF 00 ................ 00 00 00 03 6F 72 69 67 6E 3B C2 75 3F 73 69 6D ....orign;聈 ?sim 76 6D 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 00 00 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF ................ FF 00 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 ................ 00 00 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 ................ 00 02 00 00 00 00 00 00 00 04 6F 72 69 67 6E 83 ..........orign. C0 7F 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 ..3襰 imvm....... 00 00 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 ................ 00 00 00 00 F1 FF FF FF 00 00 00 00 03 6F 72 69 .............ori 67 6E 3B C2 75 2C 73 69 6D 76 6D 01 00 07 00 00 gn;聈 ,simvm..... F0 00 00 00 00 00 00 00 00 00 00 00 00 04 02 00 ................ 00 F0 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 ................ 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 ................ 00 01 07 00 00 F0 00 00 00 00 03 00 00 00 00 00 ................ 00 00 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D ...orign兝 .3襰 im 76 6D 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 01 00 00 00 01 02 00 00 F0 00 00 00 00 F0 FF FF ................ FF 00 00 00 00 03 6F 72 69 67 6E 3B C2 75 19 8D ......orign;聈 .. 85 E0 FB FF FF 50 33 C9 73 69 6D 76 6D 01 00 05 呧 ...P3蓅 imvm... 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 E8 41 49 00 ............鐰 I. 05 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 04 04 00 00 F0 00 00 00 00 34 03 00 00 ............4... 00 00 00 00 06 6F 72 69 67 6E E8 27 DD FF FF EB .....orign...... 09 73 69 6D 76 6D 65 6E 64 00 .simvmend
sn为 :simpower91a123
CODE:00491DCC sub_491DCC proc near ; CODE XREF: _Tfrmcrackme_FormCreate+81↓p CODE:00491DCC push ebx CODE:00491DCD mov ebx, eax CODE:00491DCF mov eax, ebx CODE:00491DD1 call sub_491B78 ; call function CODE:00491DD6 mov eax, [ebx+40h] CODE:00491DD9 mov [eax+2A4h], ebx CODE:00491DDF mov dword ptr [eax+2A0h], offset sub_492088 CODE:00491DE9 pop ebx CODE:00491DEA retn CODE:00491DEA sub_491DCC endp
其中sub_492088函数比较可疑。设置个断点,输入 “
simpower91111
”果然断了下了。
二、回调
sub_492088
int __userpurge sub_492088@<eax>(int a1@<eax>, int a2@<edx>, int a3@<ecx>, int a4@<ebx>, int a5@<esi>, int edi0@<edi>, _WORD *a6, int a7, int a8, int a9, int a10, int a11) { int v12; // ebx int v13; // esi int v14; // eax int v15; // eax Classes::TStrings *v16; // esi int v17; // ST14_4 int v18; // ST10_4 unsigned int v20; // [esp-14h] [ebp-34h] void *v21; // [esp-10h] [ebp-30h] int *v22; // [esp-Ch] [ebp-2Ch] int v23; // [esp-8h] [ebp-28h] int v24; // [esp-4h] [ebp-24h] int v25; // [esp+0h] [ebp-20h] int v26; // [esp+4h] [ebp-1Ch] int v27; // [esp+8h] [ebp-18h] char v28[4]; // [esp+Ch] [ebp-14h] int v29; // [esp+10h] [ebp-10h] int System::AnsiString; // [esp+14h] [ebp-Ch] int v31; // [esp+18h] [ebp-8h] int v32; // [esp+1Ch] [ebp-4h] int savedregs; // [esp+20h] [ebp+0h] System::AnsiString = 0; v29 = 0; *(_DWORD *)v28 = 0; v27 = 0; v26 = 0; v25 = 0; v24 = a4; v23 = a5; v31 = a3; v32 = a2; v12 = a1; v22 = &savedregs; v21 = &loc_4921D1; v20 = __readfsdword(0); __writefsdword(0, (unsigned int)&v20); Variants::__linkproc__ VarToLStr(&v29, a11); v13 = sub_465C88((int)&str__sptWBCallback_[1], v29); if ( v13 > 0 ) { *a6 = -1; Variants::__linkproc__ VarToLStr(&System::AnsiString, a11); v14 = GetJSLen(System::AnsiString); v15 = System::__linkproc__ LStrCopy(System::AnsiString, v13 + 15, v14 - v13 - 14, (int)&System::AnsiString); LOBYTE(v15) = 1; unknown_libname_161(System::AnsiString, (int)&str___41[1], (int)&str____19[1], v12, edi0, v13, (int)v28, v15); System::__linkproc__ LStrLAsg(&System::AnsiString, *(signed __int32 *)v28); v16 = (Classes::TStrings *)TStreamCreate((int)cls_Classes_TStringList, 1); (*(void (__fastcall **)(Classes::TStrings *, int))(*(_DWORD *)v16 + 44))(v16, System::AnsiString); if ( *(_WORD *)(v12 + 50) ) { Classes::TStrings::GetValue(v16, (const int)&str_params[1], (int)&v27); v17 = v27; Classes::TStrings::GetValue(v16, (const int)&str_eventName[1], (int)&v26); v18 = v26; Classes::TStrings::GetValue(v16, (const int)&str_id[1], (int)&v25); (*(void (__fastcall **)(_DWORD, int, int, int))(v12 + 48))(*(_DWORD *)(v12 + 52), v25, v18, v17); } } if ( *(_WORD *)(v12 + 58) ) (*(void (__fastcall **)(_DWORD, int, int, int, int, int, int, int, _WORD *))(v12 + 0x38))( *(_DWORD *)(v12 + 60), v32, v31, a11, a10, a9, a8, a7, a6); __writefsdword(0, v20); v22 = (int *)&loc_4921D8; return System::__linkproc__ LStrArrayClr(&v25, 6); }
核心处理函数为 V12+0X38,地址为;493F70
int __userpurge sub_492088@<eax>(int a1@<eax>, int a2@<edx>, int a3@<ecx>, int a4@<ebx>, int a5@<esi>, int edi0@<edi>, _WORD *a6, int a7, int a8, int a9, int a10, int a11) { int v12; // ebx int v13; // esi int v14; // eax int v15; // eax Classes::TStrings *v16; // esi int v17; // ST14_4 int v18; // ST10_4 unsigned int v20; // [esp-14h] [ebp-34h] void *v21; // [esp-10h] [ebp-30h] int *v22; // [esp-Ch] [ebp-2Ch] int v23; // [esp-8h] [ebp-28h] int v24; // [esp-4h] [ebp-24h] int v25; // [esp+0h] [ebp-20h] int v26; // [esp+4h] [ebp-1Ch] int v27; // [esp+8h] [ebp-18h] char v28[4]; // [esp+Ch] [ebp-14h] int v29; // [esp+10h] [ebp-10h] int System::AnsiString; // [esp+14h] [ebp-Ch] int v31; // [esp+18h] [ebp-8h] int v32; // [esp+1Ch] [ebp-4h] int savedregs; // [esp+20h] [ebp+0h] System::AnsiString = 0; v29 = 0; *(_DWORD *)v28 = 0; v27 = 0; v26 = 0; v25 = 0; v24 = a4; v23 = a5; v31 = a3; v32 = a2; v12 = a1; v22 = &savedregs; v21 = &loc_4921D1; v20 = __readfsdword(0); __writefsdword(0, (unsigned int)&v20); Variants::__linkproc__ VarToLStr(&v29, a11); v13 = sub_465C88((int)&str__sptWBCallback_[1], v29); if ( v13 > 0 ) { *a6 = -1; Variants::__linkproc__ VarToLStr(&System::AnsiString, a11); v14 = GetJSLen(System::AnsiString); v15 = System::__linkproc__ LStrCopy(System::AnsiString, v13 + 15, v14 - v13 - 14, (int)&System::AnsiString); LOBYTE(v15) = 1; unknown_libname_161(System::AnsiString, (int)&str___41[1], (int)&str____19[1], v12, edi0, v13, (int)v28, v15); System::__linkproc__ LStrLAsg(&System::AnsiString, *(signed __int32 *)v28); v16 = (Classes::TStrings *)TStreamCreate((int)cls_Classes_TStringList, 1); (*(void (__fastcall **)(Classes::TStrings *, int))(*(_DWORD *)v16 + 44))(v16, System::AnsiString); if ( *(_WORD *)(v12 + 50) ) { Classes::TStrings::GetValue(v16, (const int)&str_params[1], (int)&v27); v17 = v27; Classes::TStrings::GetValue(v16, (const int)&str_eventName[1], (int)&v26); v18 = v26; Classes::TStrings::GetValue(v16, (const int)&str_id[1], (int)&v25); (*(void (__fastcall **)(_DWORD, int, int, int))(v12 + 48))(*(_DWORD *)(v12 + 52), v25, v18, v17); } } if ( *(_WORD *)(v12 + 58) ) (*(void (__fastcall **)(_DWORD, int, int, int, int, int, int, int, _WORD *))(v12 + 0x38))( *(_DWORD *)(v12 + 60), v32, v31, a11, a10, a9, a8, a7, a6); __writefsdword(0, v20); v22 = (int *)&loc_4921D8; return System::__linkproc__ LStrArrayClr(&v25, 6); }
核心处理函数为 V12+0X38,地址为;493F70
三、 493F70函数
loc_493F70: ; DATA XREF: _Tfrmcrackme_FormCreate+87↑o CODE:00493F70 push ebp CODE:00493F71 mov ebp, esp CODE:00493F73 CODE:00493F73 loc_493F73: ; CODE XREF: CODE:00493FC5↓j CODE:00493F73 add esp, 0FFFFFBD8h CODE:00493F79 push ebx CODE:00493F7A push esi CODE:00493F7B xor ebx, ebx CODE:00493F7D mov [ebp-428h], ebx CODE:00493F83 mov [ebp-424h], ebx CODE:00493F89 mov [ebp-420h], ebx CODE:00493F8F mov [ebp-14h], edx CODE:00493F92 mov ebx, eax CODE:00493F94 mov eax, [ebp-14h] CODE:00493F97 call @System@@LStrAddRef$qqrpv ; System::__linkproc__ LStrAddRef(void *) CODE:00493F9C mov eax, [ebp+8] CODE:00493F9F call @System@@LStrAddRef$qqrpv ; System::__linkproc__ LStrAddRef(void *) CODE:00493FA4 xor eax, eax CODE:00493FA6 push ebp CODE:00493FA7 push offset loc_4941BA CODE:00493FAC push dword ptr fs:[eax] CODE:00493FAF mov fs:[eax], esp CODE:00493FB2 mov eax, [ebp-14h] CODE:00493FB5 call GetJSLen ; BDS 2005-2007 and Delphi6-7 Visual Component Library CODE:00493FBA cmp eax, 4 CODE:00493FBD jnz loc_494181 CODE:00493FC3 jmp short loc_493FE6 CODE:00493FC5 ; --------------------------------------------------------------------------- CODE:00493FC5 loopne near ptr loc_493F73+4 CODE:00493FC7 mov cl, 0B2h CODE:00493FC9 mov edx, offset byte_494045 CODE:00493FCE mov [ebp-4], edx CODE:00493FD1 mov edx, offset loc_4940D0 CODE:00493FD6 mov [ebp-8], edx CODE:00493FD9 mov edx, offset dword_494168 CODE:00493FDE mov [ebp-0Ch], edx CODE:00493FE1 jmp loc_4940DA CODE:00493FE6 ; --------------------------------------------------------------------------- CODE:00493FE6 CODE:00493FE6 loc_493FE6: ; CODE XREF: CODE:00493FC3↑j CODE:00493FE6 mov eax, offset _str_data_txt_1.Text CODE:00493FEB call @Sysutils@FileExists$qqrx17System@AnsiString ; Sysutils::FileExists(System::AnsiString) CODE:00493FF0 test al, al CODE:00493FF2 jz short loc_494010 CODE:00493FF4 mov dl, 1 CODE:00493FF6 mov eax, off_416648 CODE:00493FFB call TStreamCreate ; BDS 2005-2007 and Delphi6-7 Visual Component Library CODE:00494000 mov esi, eax CODE:00494002 mov edx, offset _str_data_txt_1.Text CODE:00494007 mov eax, esi CODE:00494009 call @Ibsql@TIBXSQLVAR@LoadFromFile$qqrx17System@AnsiString ; Ibsql::TIBXSQLVAR::LoadFromFile(System::AnsiString) CODE:0049400E jmp short loc_494025 CODE:00494010 ; --------------------------------------------------------------------------- CODE:00494010 CODE:00494010 loc_494010: ; CODE XREF: CODE:00493FF2↑j CODE:00494010 or ecx, 0FFFFFFFFh CODE:00494013 mov edx, offset _str_data_txt_1.Text CODE:00494018 mov eax, [ebx+330h] CODE:0049401E call GetVmpCode CODE:00494023 mov esi, eax CODE:00494025 CODE:00494025 loc_494025: ; CODE XREF: CODE:0049400E↑j CODE:00494025 mov edx, offset byte_494045 CODE:0049402A mov [ebp-4], edx CODE:0049402D mov eax, [ebp-4] CODE:00494030 push eax CODE:00494031 mov eax, [esi+4] CODE:00494034 push eax CODE:00494035 mov eax, ds:dword_498F3C CODE:0049403A push eax CODE:0049403B call sub_473A04 CODE:0049403B ; --------------------------------------------------------------------------- CODE:00494040 dd 0 CODE:00494044 db 0 CODE:00494045 byte_494045 db 0 ; DATA XREF: CODE:00493FC9↑o CODE:00494045 ; CODE:loc_494025↑o CODE:00494046 dd 0 CODE:0049404A align 4 CODE:0049404C dd 1Ah dup(0) CODE:004940B4 db 2 dup(0) CODE:004940B6 dd 0 CODE:004940BA align 4 CODE:004940BC dd 5 dup(0)
这个函数与去年的类似,程序对 地址 494045代码进行解密,里面存在一个反汇编引擎,对代码进行重定位,并一条一条执行,同时存在一个简单的VMP。
loc_493F70: ; DATA XREF: _Tfrmcrackme_FormCreate+87↑o CODE:00493F70 push ebp CODE:00493F71 mov ebp, esp CODE:00493F73 CODE:00493F73 loc_493F73: ; CODE XREF: CODE:00493FC5↓j CODE:00493F73 add esp, 0FFFFFBD8h CODE:00493F79 push ebx CODE:00493F7A push esi CODE:00493F7B xor ebx, ebx CODE:00493F7D mov [ebp-428h], ebx CODE:00493F83 mov [ebp-424h], ebx CODE:00493F89 mov [ebp-420h], ebx CODE:00493F8F mov [ebp-14h], edx CODE:00493F92 mov ebx, eax CODE:00493F94 mov eax, [ebp-14h] CODE:00493F97 call @System@@LStrAddRef$qqrpv ; System::__linkproc__ LStrAddRef(void *) CODE:00493F9C mov eax, [ebp+8] CODE:00493F9F call @System@@LStrAddRef$qqrpv ; System::__linkproc__ LStrAddRef(void *) CODE:00493FA4 xor eax, eax CODE:00493FA6 push ebp CODE:00493FA7 push offset loc_4941BA CODE:00493FAC push dword ptr fs:[eax] CODE:00493FAF mov fs:[eax], esp CODE:00493FB2 mov eax, [ebp-14h] CODE:00493FB5 call GetJSLen ; BDS 2005-2007 and Delphi6-7 Visual Component Library CODE:00493FBA cmp eax, 4 CODE:00493FBD jnz loc_494181 CODE:00493FC3 jmp short loc_493FE6 CODE:00493FC5 ; --------------------------------------------------------------------------- CODE:00493FC5 loopne near ptr loc_493F73+4 CODE:00493FC7 mov cl, 0B2h CODE:00493FC9 mov edx, offset byte_494045 CODE:00493FCE mov [ebp-4], edx CODE:00493FD1 mov edx, offset loc_4940D0 CODE:00493FD6 mov [ebp-8], edx CODE:00493FD9 mov edx, offset dword_494168 CODE:00493FDE mov [ebp-0Ch], edx CODE:00493FE1 jmp loc_4940DA CODE:00493FE6 ; --------------------------------------------------------------------------- CODE:00493FE6 CODE:00493FE6 loc_493FE6: ; CODE XREF: CODE:00493FC3↑j CODE:00493FE6 mov eax, offset _str_data_txt_1.Text CODE:00493FEB call @Sysutils@FileExists$qqrx17System@AnsiString ; Sysutils::FileExists(System::AnsiString) CODE:00493FF0 test al, al CODE:00493FF2 jz short loc_494010 CODE:00493FF4 mov dl, 1 CODE:00493FF6 mov eax, off_416648 CODE:00493FFB call TStreamCreate ; BDS 2005-2007 and Delphi6-7 Visual Component Library CODE:00494000 mov esi, eax CODE:00494002 mov edx, offset _str_data_txt_1.Text CODE:00494007 mov eax, esi CODE:00494009 call @Ibsql@TIBXSQLVAR@LoadFromFile$qqrx17System@AnsiString ; Ibsql::TIBXSQLVAR::LoadFromFile(System::AnsiString) CODE:0049400E jmp short loc_494025 CODE:00494010 ; --------------------------------------------------------------------------- CODE:00494010 CODE:00494010 loc_494010: ; CODE XREF: CODE:00493FF2↑j CODE:00494010 or ecx, 0FFFFFFFFh CODE:00494013 mov edx, offset _str_data_txt_1.Text CODE:00494018 mov eax, [ebx+330h] CODE:0049401E call GetVmpCode CODE:00494023 mov esi, eax CODE:00494025 CODE:00494025 loc_494025: ; CODE XREF: CODE:0049400E↑j CODE:00494025 mov edx, offset byte_494045 CODE:0049402A mov [ebp-4], edx CODE:0049402D mov eax, [ebp-4] CODE:00494030 push eax CODE:00494031 mov eax, [esi+4] CODE:00494034 push eax CODE:00494035 mov eax, ds:dword_498F3C CODE:0049403A push eax CODE:0049403B call sub_473A04 CODE:0049403B ; --------------------------------------------------------------------------- CODE:00494040 dd 0 CODE:00494044 db 0 CODE:00494045 byte_494045 db 0 ; DATA XREF: CODE:00493FC9↑o CODE:00494045 ; CODE:loc_494025↑o CODE:00494046 dd 0 CODE:0049404A align 4 CODE:0049404C dd 1Ah dup(0) CODE:004940B4 db 2 dup(0) CODE:004940B6 dd 0 CODE:004940BA align 4 CODE:004940BC dd 5 dup(0)
这个函数与去年的类似,程序对 地址 494045代码进行解密,里面存在一个反汇编引擎,对代码进行重定位,并一条一条执行,同时存在一个简单的VMP。
73 69 6D 76 6D 01 00 05 00 .......simvm.... 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 C5 3F 49 00 05 .............I.. 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 02 01 01 02 00 00 F0 00 00 00 00 F3 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 01 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F2 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 02 00 00 00 00 ................ 00 00 00 03 01 01 02 00 00 F0 00 00 00 00 F1 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 03 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F0 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 ................ 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF FF 00 ................ 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 00 00 ................ 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 6F 72 69 67 6E 83 C0 7F ........orign兝 . 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 00 00 3襰 imvm......... 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 00 00 ................ 00 00 F3 FF FF FF 00 00 00 00 03 6F 72 69 67 6E ...........orign 3B C2 75 52 73 69 6D 76 6D 01 00 07 00 00 F0 00 ;聈 Rsimvm....... 00 00 00 00 00 00 00 00 00 00 00 04 02 00 00 F0 ................ 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 01 ................ 07 00 00 F0 00 00 00 00 01 00 00 00 00 00 00 00 ................ 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D 76 6D .orign兝 .3襰 imvm 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 02 00 00 F0 00 00 00 00 F2 FF FF FF 00 ................ 00 00 00 03 6F 72 69 67 6E 3B C2 75 3F 73 69 6D ....orign;聈 ?sim 76 6D 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 00 00 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF ................ FF 00 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 ................ 00 00 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 ................ 00 02 00 00 00 00 00 00 00 04 6F 72 69 67 6E 83 ..........orign. C0 7F 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 ..3襰 imvm....... 00 00 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 ................ 00 00 00 00 F1 FF FF FF 00 00 00 00 03 6F 72 69 .............ori 67 6E 3B C2 75 2C 73 69 6D 76 6D 01 00 07 00 00 gn;聈 ,simvm..... F0 00 00 00 00 00 00 00 00 00 00 00 00 04 02 00 ................ 00 F0 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 ................ 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 ................ 00 01 07 00 00 F0 00 00 00 00 03 00 00 00 00 00 ................ 00 00 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D ...orign兝 .3襰 im 76 6D 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 01 00 00 00 01 02 00 00 F0 00 00 00 00 F0 FF FF ................ FF 00 00 00 00 03 6F 72 69 67 6E 3B C2 75 19 8D ......orign;聈 .. 85 E0 FB FF FF 50 33 C9 73 69 6D 76 6D 01 00 05 呧 ...P3蓅 imvm... 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 E8 41 49 00 ............鐰 I. 05 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 04 04 00 00 F0 00 00 00 00 34 03 00 00 ............4... 00 00 00 00 06 6F 72 69 67 6E E8 27 DD FF FF EB .....orign...... 09 73 69 6D 76 6D 65 6E 64 00 .simvmend
上面是指令码,其中带有 simvm 标识的为VMP代码,带有orgin的为原始代码,对于simvm的代码走虚拟机执行引擎,对于orgin标识通过反编译引擎,并重定位执行。
73 69 6D 76 6D 01 00 05 00 .......simvm.... 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 C5 3F 49 00 05 .............I.. 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 02 01 01 02 00 00 F0 00 00 00 00 F3 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 01 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F2 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 05 00 00 F0 00 00 00 00 02 00 00 00 00 ................ 00 00 00 03 01 01 02 00 00 F0 00 00 00 00 F1 FF ................ FF FF 00 00 00 00 00 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 01 00 07 00 00 F0 00 00 ................ 00 00 00 00 00 00 01 00 00 00 01 05 00 00 F0 00 ................ 00 00 00 03 00 00 00 00 00 00 00 03 01 01 02 00 ................ 00 F0 00 00 00 00 F0 FF FF FF 00 00 00 00 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 03 ................ 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 ................ 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF FF 00 ................ 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 00 00 ................ 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 00 00 ................ 00 00 00 00 00 00 00 03 6F 72 69 67 6E 83 C0 7F ........orign兝 . 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 00 00 3襰 imvm......... 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 00 00 ................ 00 00 F3 FF FF FF 00 00 00 00 03 6F 72 69 67 6E ...........orign 3B C2 75 52 73 69 6D 76 6D 01 00 07 00 00 F0 00 ;聈 Rsimvm....... 00 00 00 00 00 00 00 00 00 00 00 04 02 00 00 F0 ................ 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 00 07 ................ 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 01 ................ 07 00 00 F0 00 00 00 00 01 00 00 00 00 00 00 00 ................ 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D 76 6D .orign兝 .3襰 imvm 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 01 00 ................ 00 00 01 02 00 00 F0 00 00 00 00 F2 FF FF FF 00 ................ 00 00 00 03 6F 72 69 67 6E 3B C2 75 3F 73 69 6D ....orign;聈 ?sim 76 6D 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 00 00 00 00 04 02 00 00 F0 00 00 00 00 EC FF FF ................ FF 00 00 00 00 03 01 00 07 00 00 F0 00 00 00 00 ................ 00 00 00 00 00 00 00 00 01 07 00 00 F0 00 00 00 ................ 00 02 00 00 00 00 00 00 00 04 6F 72 69 67 6E 83 ..........orign. C0 7F 33 D2 73 69 6D 76 6D 01 00 05 00 00 F0 00 ..3襰 imvm....... 00 00 00 00 00 00 00 01 00 00 00 01 02 00 00 F0 ................ 00 00 00 00 F1 FF FF FF 00 00 00 00 03 6F 72 69 .............ori 67 6E 3B C2 75 2C 73 69 6D 76 6D 01 00 07 00 00 gn;聈 ,simvm..... F0 00 00 00 00 00 00 00 00 00 00 00 00 04 02 00 ................ 00 F0 00 00 00 00 EC FF FF FF 00 00 00 00 03 01 ................ 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 ................ 00 01 07 00 00 F0 00 00 00 00 03 00 00 00 00 00 ................ 00 00 04 6F 72 69 67 6E 83 C0 7F 33 D2 73 69 6D ...orign兝 .3襰 im 76 6D 01 00 05 00 00 F0 00 00 00 00 00 00 00 00 vm.............. 01 00 00 00 01 02 00 00 F0 00 00 00 00 F0 FF FF ................ FF 00 00 00 00 03 6F 72 69 67 6E 3B C2 75 19 8D ......orign;聈 .. 85 E0 FB FF FF 50 33 C9 73 69 6D 76 6D 01 00 05 呧 ...P3蓅 imvm... 00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 00 00 00 00 00 00 00 00 E8 41 49 00 ............鐰 I. 05 01 00 07 00 00 F0 00 00 00 00 00 00 00 00 00 ................ 00 00 00 04 04 00 00 F0 00 00 00 00 34 03 00 00 ............4... 00 00 00 00 06 6F 72 69 67 6E E8 27 DD FF FF EB .....orign...... 09 73 69 6D 76 6D 65 6E 64 00 .simvmend
上面是指令码,其中带有 simvm 标识的为VMP代码,带有orgin的为原始代码,对于simvm的代码走虚拟机执行引擎,对于orgin标识通过反编译引擎,并重定位执行。
493F70 会调用473A04 上面的逻辑主要在本函数执行。
CODE:00473A04 sub_473A04 proc near ; CODE XREF: CODE:0049403B↓p CODE:00473A04 CODE:00473A04 var_2C = dword ptr -2Ch CODE:00473A04 var_8 = dword ptr -8 CODE:00473A04 var_4 = dword ptr -4 CODE:00473A04 var_s0 = dword ptr 0 CODE:00473A04 arg_4 = dword ptr 0Ch CODE:00473A04 arg_8 = dword ptr 10h CODE:00473A04 CODE:00473A04 push ebp CODE:00473A05 mov ebp, esp CODE:00473A07 leave CODE:00473A08 push dword ptr [esp+0] CODE:00473A0B push [esp+var_s0] CODE:00473A0E push [esp+4+var_4] CODE:00473A11 pusha CODE:00473A12 pushf CODE:00473A13 call sub_4723EC CODE:00473A18 mov ebx, eax CODE:00473A1A xor eax, eax CODE:00473A1C mov [ebx+1050h], eax CODE:00473A22 mov eax, 0FFFFFFFFh CODE:00473A27 mov [ebx+1054h], eax CODE:00473A2D mov [esp+2Ch+var_8], ebx CODE:00473A31 mov eax, [esp+2Ch+arg_8] ; eax = encryptCodeAddr CODE:00473A35 mov [esp+2Ch+var_4], eax CODE:00473A39 mov eax, [esp+2Ch+arg_4] CODE:00473A3D mov [esp+2Ch+var_s0], eax CODE:00473A41 mov eax, [ebx+1090h] CODE:00473A47 cmp eax, 0 CODE:00473A4A jnz short loc_473A57 CODE:00473A4C mov eax, offset codeCrypt CODE:00473A51 mov [ebx+1090h], eax CODE:00473A57 CODE:00473A57 loc_473A57: ; CODE XREF: sub_473A04+46↑j CODE:00473A57 popf CODE:00473A58 popa CODE:00473A59 call HandleCode CODE:00473A5E pushf CODE:00473A5F pushf CODE:00473A60 pushf CODE:00473A61 pusha CODE:00473A62 pushf CODE:00473A63 jmp short loc_473A89 CODE:00473A65 ; --------------------------------------------------------------------------- CODE:00473A65 CODE:00473A65 loc_473A65: ; CODE XREF: sub_473A04+98↓j CODE:00473A65 mov eax, [ebx+1058h] CODE:00473A6B mov [esp+2Ch+var_s0], eax CODE:00473A6F mov eax, [ebx+1050h] CODE:00473A75 mov [esp+2Ch+var_4], eax CODE:00473A79 mov [esp+2Ch+var_8], ebx CODE:00473A7D popf CODE:00473A7E popa CODE:00473A7F call HandleCode CODE:00473A84 pushf CODE:00473A85 pushf CODE:00473A86 pushf CODE:00473A87 pusha CODE:00473A88 pushf CODE:00473A89 CODE:00473A89 loc_473A89: ; CODE XREF: sub_473A04+5F↑j CODE:00473A89 call sub_4723EC CODE:00473A8E mov ebx, eax CODE:00473A90 mov eax, [ebx+1050h] CODE:00473A96 cmp eax, [ebx+1054h] CODE:00473A9C jb short loc_473A65 CODE:00473A9E mov eax, [ebx+1050h] CODE:00473AA4 mov [esp+30h], eax CODE:00473AA8 mov eax, [esp+2Ch+var_2C] CODE:00473AAB mov [esp+2Ch+var_s0], eax CODE:00473AAF popf CODE:00473AB0 popa CODE:00473AB1 add esp, 8 CODE:00473AB4 popf CODE:00473AB5 retn 0Ch CODE:00473AB5 sub_473A04 endp CODE:00473AB5
而其核心函数为HandleCode(472EAC)
CODE:00473A04 sub_473A04 proc near ; CODE XREF: CODE:0049403B↓p CODE:00473A04 CODE:00473A04 var_2C = dword ptr -2Ch CODE:00473A04 var_8 = dword ptr -8 CODE:00473A04 var_4 = dword ptr -4 CODE:00473A04 var_s0 = dword ptr 0 CODE:00473A04 arg_4 = dword ptr 0Ch CODE:00473A04 arg_8 = dword ptr 10h CODE:00473A04 CODE:00473A04 push ebp CODE:00473A05 mov ebp, esp CODE:00473A07 leave CODE:00473A08 push dword ptr [esp+0] CODE:00473A0B push [esp+var_s0] CODE:00473A0E push [esp+4+var_4] CODE:00473A11 pusha CODE:00473A12 pushf CODE:00473A13 call sub_4723EC CODE:00473A18 mov ebx, eax CODE:00473A1A xor eax, eax CODE:00473A1C mov [ebx+1050h], eax CODE:00473A22 mov eax, 0FFFFFFFFh CODE:00473A27 mov [ebx+1054h], eax CODE:00473A2D mov [esp+2Ch+var_8], ebx CODE:00473A31 mov eax, [esp+2Ch+arg_8] ; eax = encryptCodeAddr CODE:00473A35 mov [esp+2Ch+var_4], eax CODE:00473A39 mov eax, [esp+2Ch+arg_4] CODE:00473A3D mov [esp+2Ch+var_s0], eax CODE:00473A41 mov eax, [ebx+1090h] CODE:00473A47 cmp eax, 0 CODE:00473A4A jnz short loc_473A57 CODE:00473A4C mov eax, offset codeCrypt CODE:00473A51 mov [ebx+1090h], eax CODE:00473A57 CODE:00473A57 loc_473A57: ; CODE XREF: sub_473A04+46↑j CODE:00473A57 popf CODE:00473A58 popa CODE:00473A59 call HandleCode CODE:00473A5E pushf CODE:00473A5F pushf CODE:00473A60 pushf CODE:00473A61 pusha CODE:00473A62 pushf CODE:00473A63 jmp short loc_473A89 CODE:00473A65 ; --------------------------------------------------------------------------- CODE:00473A65 CODE:00473A65 loc_473A65: ; CODE XREF: sub_473A04+98↓j CODE:00473A65 mov eax, [ebx+1058h] CODE:00473A6B mov [esp+2Ch+var_s0], eax CODE:00473A6F mov eax, [ebx+1050h] CODE:00473A75 mov [esp+2Ch+var_4], eax CODE:00473A79 mov [esp+2Ch+var_8], ebx CODE:00473A7D popf CODE:00473A7E popa CODE:00473A7F call HandleCode CODE:00473A84 pushf CODE:00473A85 pushf CODE:00473A86 pushf CODE:00473A87 pusha CODE:00473A88 pushf CODE:00473A89 CODE:00473A89 loc_473A89: ; CODE XREF: sub_473A04+5F↑j CODE:00473A89 call sub_4723EC CODE:00473A8E mov ebx, eax CODE:00473A90 mov eax, [ebx+1050h] CODE:00473A96 cmp eax, [ebx+1054h] CODE:00473A9C jb short loc_473A65 CODE:00473A9E mov eax, [ebx+1050h] CODE:00473AA4 mov [esp+30h], eax CODE:00473AA8 mov eax, [esp+2Ch+var_2C] CODE:00473AAB mov [esp+2Ch+var_s0], eax CODE:00473AAF popf CODE:00473AB0 popa CODE:00473AB1 add esp, 8 CODE:00473AB4 popf CODE:00473AB5 retn 0Ch CODE:00473AB5 sub_473A04 endp CODE:00473AB5
而其核心函数为HandleCode(472EAC)
int __usercall HandleCode@<eax>(int a1@<ebx>, int a2@<edi>, int a3@<esi>, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15) { unsigned int v15; // et0 int (__fastcall *v16)(unsigned int *); // ST10_4 unsigned int v18; // [esp+10h] [ebp-30h] int v19; // [esp+30h] [ebp-10h] void **v20; // [esp+34h] [ebp-Ch] int *v21; // [esp+38h] [ebp-8h] int v22; // [esp+3Ch] [ebp-4h] unsigned int vars0; // [esp+40h] [ebp+0h] void *retaddr; // [esp+44h] [ebp+4h] vars0 = a3; v22 = a2; v21 = (int *)&vars0; v20 = &retaddr; v19 = a1; v15 = __readeflags(); *(_DWORD *)(a13 + 4188) = retaddr; DecryptData(a13, a14, a12, (char *)a15, &v21, (int *)&v20, &v19); vars0 = v18; __writeeflags(v18); __writeeflags(v18); return v16(&vars0); }
其中 "16(&vars0);"语句为执行重定位后的代码。而虚拟机以及原始代码重定位在DecryptData函数(472EAC)如下
int __usercall HandleCode@<eax>(int a1@<ebx>, int a2@<edi>, int a3@<esi>, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15) { unsigned int v15; // et0 int (__fastcall *v16)(unsigned int *); // ST10_4 unsigned int v18; // [esp+10h] [ebp-30h] int v19; // [esp+30h] [ebp-10h] void **v20; // [esp+34h] [ebp-Ch] int *v21; // [esp+38h] [ebp-8h] int v22; // [esp+3Ch] [ebp-4h] unsigned int vars0; // [esp+40h] [ebp+0h] void *retaddr; // [esp+44h] [ebp+4h] vars0 = a3; v22 = a2; v21 = (int *)&vars0; v20 = &retaddr; v19 = a1; v15 = __readeflags(); *(_DWORD *)(a13 + 4188) = retaddr; DecryptData(a13, a14, a12, (char *)a15, &v21, (int *)&v20, &v19); vars0 = v18; __writeeflags(v18); __writeeflags(v18); return v16(&vars0); }
其中 "16(&vars0);"语句为执行重定位后的代码。而虚拟机以及原始代码重定位在DecryptData函数(472EAC)如下
DWORD *__stdcall DecryptData(int a1, int orgAddr, int a3, char *dataOfFile, _DWORD *a5, int *a6, _DWORD *a7) { _DWORD *global; // ebx int v8; // esi int v9; // edi int v10; // eax int v11; // ecx int v12; // esi int v13; // esi int v14; // eax int v15; // ST18_4 unsigned int v17; // [esp+1Ch] [ebp-77Ch] void *v18; // [esp+20h] [ebp-778h] int *v19; // [esp+24h] [ebp-774h] int v20; // [esp+34h] [ebp-764h] int v21; // [esp+38h] [ebp-760h] char data[1024]; // [esp+3Fh] [ebp-759h] int v23; // [esp+440h] [ebp-358h] char v24; // [esp+444h] [ebp-354h] char v25; // [esp+544h] [ebp-254h] unsigned __int8 orgCodeLen; // [esp+77Ah] [ebp-1Eh] char v27; // [esp+77Bh] [ebp-1Dh] char *nextData; // [esp+77Ch] [ebp-1Ch] char *data1; // [esp+780h] [ebp-18h] _BYTE *v30; // [esp+784h] [ebp-14h] int outDataLen; // [esp+788h] [ebp-10h] int v32; // [esp+78Ch] [ebp-Ch] int opCodeLen; // [esp+790h] [ebp-8h] _DWORD *v34; // [esp+794h] [ebp-4h] int vars0; // [esp+798h] [ebp+0h] v21 = 0; v20 = 0; v30 = 0; v19 = &vars0; v18 = &loc_4732B2; v17 = __readfsdword(0); __writefsdword(0, (unsigned int)&v17); global = sub_4723EC(); v34 = (_DWORD *)(vars0 + 8); data1 = data; v8 = *(_DWORD *)off_497644; *(_DWORD *)(*(_DWORD *)off_497644 + 52) = 0; v27 = 0; while ( 1 ) { callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); while ( 1 ) { while ( *(_DWORD *)(v8 + 52) == 1 ) { orgCodeLen = 0; nextData = callVmpHandle(v8, (_BYTE *)orgAddr, data, (int)&orgCodeLen); opCodeLen = nextData - data; GetNextValueByLen(&dataOfFile, nextData - data); GetNextValueByLen(&orgAddr, orgCodeLen); callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); } if ( ifCode_simvm_orign(v8, &data1) != 1 )// 不是 simvm break; data1 = data; v27 = 1; simvm_Handle(global, v34); } data1 = data; if ( !v27 ) break; v27 = 0; orgin_Handle(global, v34); } outDataLen = off_498CA0(data, outDataLen, 0x400000, &v23, 4, v17);// 执行原始code *a5 = outDataLen; v9 = unknown_libname_29(32 - outDataLen - 6); data1 = (char *)global + v9 + 4144; sub_464FA4(data1, data, outDataLen); *((_BYTE *)global + v9 + outDataLen + 4144) = 104; GetCharFormTstring((int)&v30, &v25); if ( (unsigned __int8)sub_472520(v30, global[1047]) ) { GetCharFormTstring((int)&v30, &v24); opCodeLen = sub_465C88((int)&str___29[1], (int)v30); v10 = GetJSLen(v30); System::__linkproc__ LStrCopy((int)v30, opCodeLen + 1, v10 - opCodeLen, (int)&v30); opCodeLen = sub_465CEC(v30); if ( outDataLen - 1 >= 0 ) { v11 = outDataLen; v32 = 0; do { *((_BYTE *)global + v9 + v32++ + 4144) = -112; --v11; } while ( v11 ); } opCodeLen += outDataLen; v12 = sub_471F04(v8, data, opCodeLen); } else if ( sub_465C88((int)&str_CALL_0[1], (int)v30) == 1 ) { GetCharFormTstring((int)&v30, &v24); if ( sub_465C88((int)&str_FF_0[1], (int)v30) != 1 ) { opCodeLen = sub_465C88((int)&str___29[1], (int)v30); v32 = opCodeLen - 1; v13 = (opCodeLen - 1) / 2; data1 = (char *)global + v9 + v13 + 4144; v14 = GetJSLen(v30); System::__linkproc__ LStrCopy((int)v30, opCodeLen + 1, v14 - opCodeLen, (int)&v30); opCodeLen = sub_465CEC(v30); v32 = opCodeLen + orgAddr - ((_DWORD)global + v9 + 4144); sub_464FA4(data1, &v32, outDataLen - v13); } opCodeLen = outDataLen; v12 = outDataLen; } else { opCodeLen = outDataLen; v12 = outDataLen; } *a7 = opCodeLen; opCodeLen = a3; data1 = (char *)global + v9 + outDataLen + 4145; sub_464FA4(data1, &opCodeLen, 4u); *((_BYTE *)global + v9 + outDataLen + 4149) = 0xC3u; *a6 = (int)global + v9 + 0x1030; global[1044] = orgAddr + *a7; global[1046] = &dataOfFile[v12]; GetCharFormTstring((int)&v21, &v25); v15 = v21; GetCharFormTstring((int)&v20, &v24); sub_4736D4((int)global, *a6, orgAddr, v15, v20, outDataLen); __writefsdword(0, v17); v19 = (int *)&loc_4732B9; System::__linkproc__ LStrArrayClr(&v20, 2); return System::__linkproc__ LStrClr(&v30); }
其中如下代码为执行VMP代码
DWORD *__stdcall DecryptData(int a1, int orgAddr, int a3, char *dataOfFile, _DWORD *a5, int *a6, _DWORD *a7) { _DWORD *global; // ebx int v8; // esi int v9; // edi int v10; // eax int v11; // ecx int v12; // esi int v13; // esi int v14; // eax int v15; // ST18_4 unsigned int v17; // [esp+1Ch] [ebp-77Ch] void *v18; // [esp+20h] [ebp-778h] int *v19; // [esp+24h] [ebp-774h] int v20; // [esp+34h] [ebp-764h] int v21; // [esp+38h] [ebp-760h] char data[1024]; // [esp+3Fh] [ebp-759h] int v23; // [esp+440h] [ebp-358h] char v24; // [esp+444h] [ebp-354h] char v25; // [esp+544h] [ebp-254h] unsigned __int8 orgCodeLen; // [esp+77Ah] [ebp-1Eh] char v27; // [esp+77Bh] [ebp-1Dh] char *nextData; // [esp+77Ch] [ebp-1Ch] char *data1; // [esp+780h] [ebp-18h] _BYTE *v30; // [esp+784h] [ebp-14h] int outDataLen; // [esp+788h] [ebp-10h] int v32; // [esp+78Ch] [ebp-Ch] int opCodeLen; // [esp+790h] [ebp-8h] _DWORD *v34; // [esp+794h] [ebp-4h] int vars0; // [esp+798h] [ebp+0h] v21 = 0; v20 = 0; v30 = 0; v19 = &vars0; v18 = &loc_4732B2; v17 = __readfsdword(0); __writefsdword(0, (unsigned int)&v17); global = sub_4723EC(); v34 = (_DWORD *)(vars0 + 8); data1 = data; v8 = *(_DWORD *)off_497644; *(_DWORD *)(*(_DWORD *)off_497644 + 52) = 0; v27 = 0; while ( 1 ) { callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); while ( 1 ) { while ( *(_DWORD *)(v8 + 52) == 1 ) { orgCodeLen = 0; nextData = callVmpHandle(v8, (_BYTE *)orgAddr, data, (int)&orgCodeLen); opCodeLen = nextData - data; GetNextValueByLen(&dataOfFile, nextData - data); GetNextValueByLen(&orgAddr, orgCodeLen); callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); } if ( ifCode_simvm_orign(v8, &data1) != 1 )// 不是 simvm break; data1 = data; v27 = 1; simvm_Handle(global, v34); } data1 = data; if ( !v27 ) break; v27 = 0; orgin_Handle(global, v34); } outDataLen = off_498CA0(data, outDataLen, 0x400000, &v23, 4, v17);// 执行原始code *a5 = outDataLen; v9 = unknown_libname_29(32 - outDataLen - 6); data1 = (char *)global + v9 + 4144; sub_464FA4(data1, data, outDataLen); *((_BYTE *)global + v9 + outDataLen + 4144) = 104; GetCharFormTstring((int)&v30, &v25); if ( (unsigned __int8)sub_472520(v30, global[1047]) ) { GetCharFormTstring((int)&v30, &v24); opCodeLen = sub_465C88((int)&str___29[1], (int)v30); v10 = GetJSLen(v30); System::__linkproc__ LStrCopy((int)v30, opCodeLen + 1, v10 - opCodeLen, (int)&v30); opCodeLen = sub_465CEC(v30); if ( outDataLen - 1 >= 0 ) { v11 = outDataLen; v32 = 0; do { *((_BYTE *)global + v9 + v32++ + 4144) = -112; --v11; } while ( v11 ); } opCodeLen += outDataLen; v12 = sub_471F04(v8, data, opCodeLen); } else if ( sub_465C88((int)&str_CALL_0[1], (int)v30) == 1 ) { GetCharFormTstring((int)&v30, &v24); if ( sub_465C88((int)&str_FF_0[1], (int)v30) != 1 ) { opCodeLen = sub_465C88((int)&str___29[1], (int)v30); v32 = opCodeLen - 1; v13 = (opCodeLen - 1) / 2; data1 = (char *)global + v9 + v13 + 4144; v14 = GetJSLen(v30); System::__linkproc__ LStrCopy((int)v30, opCodeLen + 1, v14 - opCodeLen, (int)&v30); opCodeLen = sub_465CEC(v30); v32 = opCodeLen + orgAddr - ((_DWORD)global + v9 + 4144); sub_464FA4(data1, &v32, outDataLen - v13); } opCodeLen = outDataLen; v12 = outDataLen; } else { opCodeLen = outDataLen; v12 = outDataLen; } *a7 = opCodeLen; opCodeLen = a3; data1 = (char *)global + v9 + outDataLen + 4145; sub_464FA4(data1, &opCodeLen, 4u); *((_BYTE *)global + v9 + outDataLen + 4149) = 0xC3u; *a6 = (int)global + v9 + 0x1030; global[1044] = orgAddr + *a7; global[1046] = &dataOfFile[v12]; GetCharFormTstring((int)&v21, &v25); v15 = v21; GetCharFormTstring((int)&v20, &v24); sub_4736D4((int)global, *a6, orgAddr, v15, v20, outDataLen); __writefsdword(0, v17); v19 = (int *)&loc_4732B9; System::__linkproc__ LStrArrayClr(&v20, 2); return System::__linkproc__ LStrClr(&v30); }
其中如下代码为执行VMP代码
while ( 1 ) { callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); while ( 1 ) { while ( *(_DWORD *)(v8 + 52) == 1 ) { orgCodeLen = 0; nextData = callVmpHandle(v8, (_BYTE *)orgAddr, data, (int)&orgCodeLen); opCodeLen = nextData - data; GetNextValueByLen(&dataOfFile, nextData - data); GetNextValueByLen(&orgAddr, orgCodeLen); callCodeDecrypt((int)global, dataOfFile, data, &outDataLen); } if ( ifCode_simvm_orign(v8, &data1) != 1 )// 不是 simvm break; data1 = data; v27 = 1; simvm_Handle(global, v34); } data1 = data; if ( !v27 ) break; v27 = 0; orgin_Handle(global, v34); }
后半部分为执行原始代码,进行反编译从定位。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-3-25 11:16
被oooAooo编辑
,原因:
赞赏记录
参与人
雪币
留言
时间
一笑人间万事
为你点赞~
2023-1-27 04:05
皮豪
为你点赞~
2019-3-26 19:06
谢威
为你点赞~
2019-3-26 14:30
绝世银月
为你点赞~
2019-3-26 08:17
赞赏
|
|
---|---|
|
大神我问一下,这些题在哪里找啊,为什么我找不到,麻烦告知一下,谢谢
|
|
https://ctf.pediy.com/game-team_list-10-5.htm
|
|
oooAooo https://ctf.pediy.com/game-team_list-10-5.htm谢谢大神的回答 |
|
感谢大佬分享,请多多指教
|
|
太牛了可谓非常详尽了。
|
他的文章
- 看雪CTF 2019总决赛 第六题 三道八佛 IDA脱壳脚本 5670
- [原创]看雪CTF2019Q3第四题WP 5935
- [原创]看雪CTF2019Q3 第二题WP 6762
- [2019看雪CTF晋级赛Q3第九题WP 12492
- [原创]看雪CTF2019晋级赛Q2第三题 5022
看原图
赞赏
雪币:
留言: