终于有天被asprotect给
, 于是操起ollydbg 和 IDA 来个大卸八块.
与此之前很多大虾已经给出了手脱的方法.如.
http://bbs.pediy.com/showthread.php?threadid=24007
本文用的也是上面这个链接中的目标程序.
这里主要对壳的代码进行详细的分析. 本人分析壳喜欢在分析到脑中能浮现出C代码为止
call XXXX的修复 是这个壳的难点. 正如很多大虾指出,这个 call有3层,我们具体看看每层究竟干了什么.
push ebx
seg000:00DA0004 pushf
seg000:00DA0005 mov ebx, 4283E2h
seg000:00DA000A jmp short loc_DA000D
seg000:00DA000A ; seg000:00DA000C db 9Ah ; ?
seg000:00DA000D ;
seg000:00DA000D
seg000:00DA000D loc_DA000D: ; CODE XREF: seg000:00DA000Aj
seg000:00DA000D add ebx, [esp+18h]
seg000:00DA0011 jmp short loc_DA0015 ; allocate 20h bytes to save registers
seg000:00DA0011 ;
seg000:00DA0013 db 0CDh ; ?
seg000:00DA0014 db 20h
seg000:00DA0015 ;
seg000:00DA0015
seg000:00DA0015 loc_DA0015: ; CODE XREF: seg000:00DA0011j
seg000:00DA0015 sub esp, 20h ; old esp = fp
seg000:00DA0018 jmp short loc_DA001B ; junk
seg000:00DA0018 ;
seg000:00DA001A db 0C7h ; ?
seg000:00DA001B ; seg000:00DA001B
seg000:00DA001B loc_DA001B: ; CODE XREF: seg000:00DA0018j
seg000:00DA001B xor ebx, [esp+8] ; junk
seg000:00DA001F xor ebx, [esp+28h] ; junk
seg000:00DA0023 mov ebx, 42BD2Ah ; junk
seg000:00DA0028 db 65h
seg000:00DA0028 jmp short loc_DA002C
seg000:00DA0028 ; seg000:00DA002B db 0F2h ; ò
seg000:00DA002C ; seg000:00DA002C
seg000:00DA002C loc_DA002C: ; CODE XREF: seg000:00DA0028j
seg000:00DA002C and ebx, 0FFFFFFA8h
seg000:00DA002F jmp short loc_DA0032
seg000:00DA002F ;
seg000:00DA0031 db 9Ah ; ?
seg000:00DA0032 ; seg000:00DA0032
seg000:00DA0032 loc_DA0032: ; CODE XREF: seg000:00DA002Fj
seg000:00DA0032 rep jmp short loc_DA0037
seg000:00DA0032 ; seg000:00DA0035 db 0CDh ; ?
seg000:00DA0036 db 20h
seg000:00DA0037 ;
seg000:00DA0037
seg000:00DA0037 loc_DA0037: ; CODE XREF: seg000:loc_DA0032j
seg000:00DA0037 lea ebx, [esi+ebx*2+0Ch]
seg000:00DA003B lea ebx, [esp+ecx+7Ch] ; ebx = esp + ecx + 7c
seg000:00DA003F jmp short loc_DA0042 ; ebx = esp + 7c
seg000:00DA003F ;
seg000:00DA0042 ; seg000:00DA0042
seg000:00DA0042 loc_DA0042: ; CODE XREF: seg000:00DA003Fj
seg000:00DA0042 sub ebx, ecx ; ebx = esp + 7c
seg000:00DA0044 repne jmp short loc_DA0048
seg000:00DA0044 ;
seg000:00DA0047 db 0E8h ; è
seg000:00DA0048 ; seg000:00DA0048
seg000:00DA0048 loc_DA0048: ; CODE XREF: seg000:00DA0044j
seg000:00DA0048 jmp short loc_DA004B ; ebx = fp
seg000:00DA0048 ; seg000:00DA004A db 0E8h ; è
seg000:00DA004B ; seg000:00DA004B
seg000:00DA004B loc_DA004B: ; CODE XREF: seg000:loc_DA0048j
seg000:00DA004B lea ebx, [ebx-7Ch] ; ebx = fp
seg000:00DA004E mov [ebx+4], ecx ; ecx ->fp + 4
seg000:00DA0051 xor ecx, [esp+8]
seg000:00DA0055 xor ecx, [esp+28h]
seg000:00DA0059 push edx
seg000:00DA005A pop dword ptr [ebx+8] ; edx -> fp + 8
seg000:00DA005D jmp short loc_DA0061
seg000:00DA005D ; seg000:00DA005F db 0CDh ; ?
seg000:00DA0060 db 20h
seg000:00DA0061 ; seg000:00DA0061
seg000:00DA0061 loc_DA0061: ; CODE XREF: seg000:00DA005Dj
seg000:00DA0061 xor edx, ecx
seg000:00DA0063 mov [ebx+1Ch], edi ; save edi
seg000:00DA0066 mov edi, 493522h
seg000:00DA006B rcl edi, 0Dh
seg000:00DA006E push eax
seg000:00DA006F rep jmp short loc_DA0074 ; eax -> fp
seg000:00DA006F ;seg000:00DA0072 db 0CDh ; ?
seg000:00DA0073 db 20h
seg000:00DA0074 ;seg000:00DA0074
seg000:00DA0074 loc_DA0074: ; CODE XREF: seg000:00DA006Fj
seg000:00DA0074 pop dword ptr [ebx+0] ; eax -> fp
seg000:00DA0078 mov eax, 41A402h
seg000:00DA007D mov eax, 475EFAh
seg000:00DA0082 jmp short loc_DA0086 ; save ebp
seg000:00DA0082 ; seg000:00DA0084 db 0CDh ; ?
seg000:00DA0085 db 20h
seg000:00DA0086 ;
seg000:00DA0086
seg000:00DA0086 loc_DA0086: ; CODE XREF: seg000:00DA0082j
seg000:00DA0086 mov [ebx+14h], ebp ; save ebp
seg000:00DA0089 xor ebp, [esp+28h]
seg000:00DA008D mov ebp, 485AE2h
seg000:00DA0092 push esi
seg000:00DA0093 pop dword ptr [ebx+18h] ; esi -> fp + 18
seg000:00DA0096 db 64h
seg000:00DA0096 jmp short loc_DA009B
seg000:00DA0096 ; seg000:00DA0099 db 0CDh ; ?
seg000:00DA009A db 20h
seg000:00DA009B ;
seg000:00DA009B
seg000:00DA009B loc_DA009B: ; CODE XREF: seg000:00DA0096j
seg000:00DA009B lea esi, [ebp+esi+447058h]
seg000:00DA00A2 db 65h
seg000:00DA00A2 jmp short loc_DA00A6
seg000:00DA00A2 ;seg000:00DA00A5 db 69h ; i
seg000:00DA00A6 ;
seg000:00DA00A6
seg000:00DA00A6 loc_DA00A6: ; CODE XREF: seg000:00DA00A2j
seg000:00DA00A6 adc ecx, 0FFFFFFD0h
seg000:00DA00A9 or ecx, ebx
seg000:00DA00AB jmp short loc_DA00AE
seg000:00DA00AB ; seg000:00DA00AD db 0F3h ; ó
seg000:00DA00AE ;
seg000:00DA00AE
seg000:00DA00AE loc_DA00AE: ; CODE XREF: seg000:00DA00ABj
seg000:00DA00AE lea ecx, [ebx+ecx+4Eh]
seg000:00DA00B2 lea ecx, [esp+74h] ; ecx=esp+74
seg000:00DA00B6 rep jmp short loc_DA00BB ; ecx=esp+ebp
seg000:00DA00B6 ;
seg000:00DA00B9 db 0CDh ; ?
seg000:00DA00BA db 20h
seg000:00DA00BB ;
seg000:00DA00BB
seg000:00DA00BB loc_DA00BB: ; CODE XREF: seg000:00DA00B6j
seg000:00DA00BB lea ecx, [ecx+ebp-74h] ; ecx=esp+ebp
seg000:00DA00BF jmp short loc_DA00C2 ; ecx=fp
seg000:00DA00BF ;
seg000:00DA00C1 db 0C7h ; ?
seg000:00DA00C2 ;
seg000:00DA00C2
seg000:00DA00C2 loc_DA00C2: ; CODE XREF: seg000:00DA00BFj
seg000:00DA00C2 sub ecx, ebp ; ecx=fp
seg000:00DA00C4 rep jmp short loc_DA00C9 ; ecx = fp + ebx + 2c;
seg000:00DA00C4 ;
seg000:00DA00C7 db 0CDh ; ?
seg000:00DA00C8 db 20h
seg000:00DA00C9 ;
seg000:00DA00C9
seg000:00DA00C9 loc_DA00C9: ; CODE XREF: seg000:00DA00C4j
seg000:00DA00C9 lea ecx, [ecx+ebx+2Ch] ; ecx = fp + ebx + 2c;
seg000:00DA00CD sub ecx, ebx ; ecx = ecx + 2c = fp +2c
seg000:00DA00CF push ecx ; save ecx
seg000:00DA00D0 mov ecx, 45ACD2h
seg000:00DA00D5 sub ecx, 65h ; 'e'
seg000:00DA00D8 push ebx ; save ebx
seg000:00DA00D9 and ecx, ecx
seg000:00DA00DB jmp short loc_DA00DF
seg000:00DA00DB ;
seg000:00DA00DD db 0CDh ; ?
seg000:00DA00DE db 20h
seg000:00DA00DF ;
seg000:00DA00DF
seg000:00DA00DF loc_DA00DF: ; CODE XREF: seg000:00DA00DBj
seg000:00DA00DF xor ecx, 742A204Fh
seg000:00DA00E5 lea ecx, [ebx+37h] ; ecx = fp + 37
seg000:00DA00E9 lea ecx, [ecx-37h] ; ecx = fp
seg000:00DA00ED add ecx, 20h ; ' ' ; ecx = fp + 20
seg000:00DA00F0 db 3Eh
seg000:00DA00F0 jmp short loc_DA00F5
seg000:00DA00F0 ;
seg000:00DA00F3 db 0CDh ; ?
seg000:00DA00F4 db 20h
seg000:00DA00F5 ;
seg000:00DA00F5
seg000:00DA00F5 loc_DA00F5: ; CODE XREF: seg000:00DA00F0j
seg000:00DA00F5 mov ecx, [ecx]
seg000:00DA00F7 push ecx
seg000:00DA00F8 db 26h
seg000:00DA00F8 jmp short loc_DA00FD
seg000:00DA00F8 ;
seg000:00DA00FB db 0CDh ; ?
seg000:00DA00FC db 20h
seg000:00DA00FD ;
seg000:00DA00FD
seg000:00DA00FD loc_DA00FD: ; CODE XREF: seg000:00DA00F8j
seg000:00DA00FD lea ecx, [ebp+esi+2]
seg000:00DA0101 lea ecx, [ecx-2]
seg000:00DA0104 rep jmp short loc_DA0109
seg000:00DA0104 ;
seg000:00DA0107 db 0CDh ; ?
seg000:00DA0108 db 20h
seg000:00DA0109 ;
seg000:00DA0109
seg000:00DA0109 loc_DA0109: ; CODE XREF: seg000:00DA0104j
seg000:00DA0109 add ecx, ecx
seg000:00DA010B xor ecx, 647084D2h
seg000:00DA0111 jmp short loc_DA0115
seg000:00DA0111 ;
seg000:00DA0113 db 0CDh ; ?
seg000:00DA0114 db 20h
seg000:00DA0115 ;
seg000:00DA0115
seg000:00DA0115 loc_DA0115: ; CODE XREF: seg000:00DA0111j
seg000:00DA0115 sub ecx, 66510D97h
seg000:00DA011B jmp short loc_DA011F
seg000:00DA011B ;
seg000:00DA011D db 0CDh ; ?
seg000:00DA011E db 20h
seg000:00DA011F ;
seg000:00DA011F
seg000:00DA011F loc_DA011F: ; CODE XREF: seg000:00DA011Bj
seg000:00DA011F lea ecx, [ebx+ebp+3Eh]
seg000:00DA0123 sub ecx, ebp
seg000:00DA0125 sub ecx, 3Eh ; '>'
seg000:00DA0128 lea ecx, [ecx+28h] ; ecx = fp + 28
seg000:00DA012B push dword ptr [ecx]
seg000:00DA012D mov ecx, 403F46h
seg000:00DA0132 repne jmp short loc_DA0136
seg000:00DA0132 ;
seg000:00DA0135 db 0F3h ; ó
seg000:00DA0136 ;
seg000:00DA0136
seg000:00DA0136 loc_DA0136: ; CODE XREF: seg000:00DA0132j
seg000:00DA0136 mov ecx, 49B80Ah
seg000:00DA013B pop ecx
seg000:00DA013C lea ecx, [ecx-5]
seg000:00DA0140 add ecx, 5D4h
seg000:00DA0146 push ecx
seg000:00DA0147 sbb ecx, ebx
seg000:00DA0149 mov ecx, 41ECEAh
seg000:00DA014E xor ecx, [esp+8]
seg000:00DA0152 push 0B704B8h
seg000:00DA0157 and ecx, 53711992h
seg000:00DA015D pop ecx
seg000:00DA015E push ecx
seg000:00DA015F rcl ecx, 7Bh
seg000:00DA0162 sbb ecx, 57h ; 'W'
seg000:00DA0165 xor ebx, ebx
seg000:00DA0167 sbb ebx, ebx
seg000:00DA0169 db 36h
seg000:00DA0169 jmp short loc_DA016D
seg000:00DA0169 ;
seg000:00DA016C db 0Fh
seg000:00DA016D ;
seg000:00DA016D
seg000:00DA016D loc_DA016D: ; CODE XREF: seg000:00DA0169j
seg000:00DA016D lea ebx, [edi+0B64BC0h]
seg000:00DA0174 sub ebx, edi
seg000:00DA0176 call ebx (call B64BC0)
注段代码的主要功能是将寄存器入栈. (我顶你个肺,pushad,不就行了, 还费这个劲,里面不少填充的junk code,且好像是随机的).
在 00DA0176 进入 call ebx 之前,堆栈如下
0012FF54 00B704B8 const
0012FF58 00B10C84 call + <process id>
0012FF5C 00000282 flag word
0012FF60 0012FF68 esp?
0012FF64 0012FF94 指针, 存放调用DA0000 时传入的参数.
0012FF68 0 0055BA88 eax
0012FF6C 4 00A3FD78 ecx
0012FF70 8 00B102D0 edx
0012FF74 0c 00B10000
0012FF78 10 00B58D88
0012FF7C 14 0012FFA4 ebp
0012FF80 18 005B58AA esi
0012FF84 1c 0012FFA8 edi
0012FF88 20 00000282
0012FF8C 24 00B703EC ebx
0012FF90 28 00B106B5
请注意,0012FF58处的值, call 0DA0000 是在 B106B0 发生的, 这里的值是 B106b0+5d4.(参看代码DA013C-DA0146).
12FF54 的值在 00DA0152 push 0B704B8h 压入
上篇说到通过call ebx 进入 B64BC0, 这篇主要分析这个call.
sub_B64BC0 proc near ; DATA XREF: seg001:loc_DA00164r
seg000:00B64BC0
seg000:00B64BC0 var_p = dword ptr -8
seg000:00B64BC0 var_4 = dword ptr -4
seg000:00B64BC0 arg_0 = dword ptr 8
seg000:00B64BC0 arg_4 = dword ptr 0Ch
seg000:00B64BC0 arg_8 = dword ptr 10h
seg000:00B64BC0 arg_C = dword ptr 14h
seg000:00B64BC0 arg_10 = dword ptr 18h
seg000:00B64BC0
seg000:00B64BC0 push ebp
seg000:00B64BC1 mov ebp, esp
seg000:00B64BC3 add esp, 0FFFFFFF8h
seg000:00B64BC6 push ebx
seg000:00B64BC7 push esi
seg000:00B64BC8 push edi
seg000:00B64BC9 mov ebx, [ebp+arg_0] ; ebx = pushed constan 0b704b8
seg000:00B64BCC jmp short loc_B64BCF
seg000:00B64BCC ;
seg000:00B64BCE db 9Ah ; ?
seg000:00B64BCF ;
seg000:00B64BCF
seg000:00B64BCF loc_B64BCF: ; CODE XREF: sub_B64BC0+Cj
seg000:00B64BCF mov eax, [ebp+arg_10]
seg000:00B64BD2 sub eax, 8
seg000:00B64BD5 mov eax, [eax] ; saved ebx in stack
seg000:00B64BD7 push eax
seg000:00B64BD8 mov cl, [ebx+8Eh]
seg000:00B64BDE mov edx, [ebp+arg_C] ; edx = esp?
seg000:00B64BE1 mov eax, ebx
seg000:00B64BE3 call set_array_val ; ebx -> fp + 0c
seg000:00B64BE8 mov eax, [ebp+arg_10]
seg000:00B64BEB push eax
seg000:00B64BEC mov cl, 4
seg000:00B64BEE mov edx, [ebp+arg_C]
seg000:00B64BF1 mov eax, ebx
seg000:00B64BF3 call set_array_val ; old esp => fp + 10
seg000:00B64BF8 jmp short loc_B64BFB ; esi = [ebx + 30]
seg000:00B64BF8 ;
seg000:00B64BFA db 69h ; i
seg000:00B64BFB ;
seg000:00B64BFB
seg000:00B64BFB loc_B64BFB: ; CODE XREF: sub_B64BC0+38j
seg000:00B64BFB mov esi, [ebx+30h] ; esi = [ebx + 30]
seg000:00B64BFE mov edi, [ebx+14h] ; edi = [ebx + 14]
seg000:00B64C01 mov eax, ds:g_iat?
seg000:00B64C06 mov eax, [eax+34h]
seg000:00B64C09 call eax ; GetCurrentProcessId
seg000:00B64C0B sub [ebp+0Ch], eax ; restore the call address
参看(1) 00DA0136-00DA0140, 存放的是call DA0000发生的地址 + 当前 process id, 这里恢复
seg000:00B64C0E mov eax, [ebp+0Ch]
seg000:00B64C11 sub eax, [ebx+18h] ; ebx + 18 holds the OEP address
seg000:00B64C14 sub eax, [ebx+68h]
seg000:00B64C17 mov [ebp+var_4], eax ; var_4 = call address relative to OEP - [ebx + 68]
注意这里的var_4 是根据 DA00000 调用发生的地址 - OEP 再 减去一个 数算出来的
seg000:00B64C1A lea eax, [ebx+24h]
seg000:00B64C1D mov [ebp+var_p], eax ; ebx + 24 -> var_p
seg000:00B64C20 test edi, edi ; [ebx + 14 ] == 0
seg000:00B64C22 jbe short loc_B64C5C
seg000:00B64C24 jmp short loc_B64C27
seg000:00B64C24 ;
seg000:00B64C26 db 0C7h ; ?
seg000:00B64C27 ;
seg000:00B64C27
seg000:00B64C27 loc_B64C27: ; CODE XREF: sub_B64BC0+64j
seg000:00B64C27 ; sub_B64BC0+9Aj
seg000:00B64C27 mov eax, [ebp+var_p]
seg000:00B64C2A movzx eax, byte ptr [eax]
seg000:00B64C2D mov edx, [ebx+eax*4+40h]
seg000:00B64C31 mov eax, esi ; eax = esi = [ ebx + 30]
seg000:00B64C33 call edx ; return [eax + 28h]
这个call edx 进去是一堆垃圾指令, 作用就是 返回 [eax+28h],再顶你个肺
seg000:00B64C35 cmp eax, [ebp+var_4]
seg000:00B64C38 jnz short loc_B64C54
seg000:00B64C3A mov eax, [ebp+10h]
seg000:00B64C3D push eax
seg000:00B64C3E mov eax, [ebp+14h]
seg000:00B64C41 push eax
seg000:00B64C42 call sub_B648BC
seg000:00B64C47 push eax ; SEH header
seg000:00B64C48 mov ecx, esi
seg000:00B64C4A mov edx, [ebp+18h]
seg000:00B64C4D mov eax, ebx
seg000:00B64C4F call sub_B64668
seg000:00B64C54
seg000:00B64C54 loc_B64C54: ; CODE XREF: sub_B64BC0+78j
seg000:00B64C54 dec edi
seg000:00B64C55 add esi, [ebx+6Ch]
seg000:00B64C58 test edi, edi
seg000:00B64C5A ja short loc_B64C27
对于每个call DA00000, 都存放了一个表,这个循环其实就是根据call发生的地址来搜寻这张表.
seg000:00B64C5C
seg000:00B64C5C loc_B64C5C: ; CODE XREF: sub_B64BC0+62j
seg000:00B64C5C push 0B64C78h
seg000:00B64C61 call sub_B551E4
seg000:00B64C66 pop edi
seg000:00B64C67 pop esi
seg000:00B64C68 pop ebx
seg000:00B64C69 pop ecx
seg000:00B64C6A pop ecx
seg000:00B64C6B pop ebp
seg000:00B64C6C retn 14h
seg000:00B64C6C sub_B64BC0 endp ; sp = -10h
写到这里, 想问一下,他明白了,你明白了没有? 如果没有,不要紧, 看下下面的总结:
对于每个变形的call DA0000. 请注意2样东西,这两样东西决定了这个call的具体行为.
1)call DA0000发生的地址,
2)压入的参数 (这个参数目前好像还没用到),在后续的分析中应该会用到.
在内存中存放了2张表, 第一张表是存放每个call DA00000的 具体属性,另外还有一张全局的表, 存放着一些函数指针, 偏移常数.
第一层
在进入call DA00000后, 将寄存器压栈,
第二层 然后根据call DA0000的地址,查找第一张表,得到一个当前call DA0000的表项.
(参看指令B64C17-B64C5A),然后将这个表项作为参数调用 B64668.
进入B646688后干什么呢, 坐好了,演出开始了.
seg000:00B64668 push ebp
seg000:00B64669 mov ebp, esp
seg000:00B6466B add esp, 0FFFFFFF4h
seg000:00B6466E push ebx
seg000:00B6466F push esi
seg000:00B64670 push edi
seg000:00B64671 mov esi, ecx
seg000:00B64673 mov [ebp+var_parg], edx
seg000:00B64676 mov [ebp+var_g_table], eax
seg000:00B64679 mov eax, [ebp+var_g_table] ; faint, junk code or stupid code?
seg000:00B6467C lea ebx, [eax+24h] ; ebx = eax+24
seg000:00B6467F xor eax, eax
seg000:00B64681 mov al, [ebx+2] ; al = var_g_table + 26h
seg000:00B64684 mov edx, [ebp+var_g_table]
seg000:00B64687 mov edi, [edx+eax*4+40h]
seg000:00B6468B mov eax, esi
seg000:00B6468D call edi
seg000:00B6468F mov edi, eax ; save result in edi
seg000:00B64691 xor eax, eax
seg000:00B64693 mov al, [ebx+3]
seg000:00B64696 mov edx, [ebp+var_g_table]
seg000:00B64699 mov edx, [edx+eax*4+40h]
seg000:00B6469D mov eax, esi
seg000:00B6469F call edx
seg000:00B646A1 mov [ebp+var_itemoff17], eax
seg000:00B646A4 xor eax, eax
seg000:00B646A6 mov al, [ebx+1]
seg000:00B646A9 mov edx, [ebp+var_g_table]
seg000:00B646AC mov edx, [edx+eax*4+40h] ; edx = var_g_table + 40 + (var_g_table + 26 ) *4
seg000:00B646B0 mov eax, esi
seg000:00B646B2 call edx
seg000:00B646B4 sub al, 2
这里, 针对不同的表项里的数据,会走向不同的分支.
seg000:00B646B6 jb short loc_B646C3
seg000:00B646B8 jz short loc_B646ED
seg000:00B646BA dec al
seg000:00B646BC jz short loc_B64731
seg000:00B646BE jmp loc_B64785
seg000:00B646C3 ;
seg000:00B646C3
seg000:00B646C3 loc_B646C3: ; CODE XREF: sub_B64668+4Ej
seg000:00B646C3 mov eax, [ebp+var_g_table]
seg000:00B646C6 mov edx, [eax+68h] ; edx = g_table + 68
seg000:00B646C9 mov eax, edx
seg000:00B646CB add eax, edi ; eax = [g_table + 68] + [item + 1d], assume it's off
seg000:00B646CD cmp eax, 0FFFFFFFFh
seg000:00B646D0 jnz short loc_B646E2
seg000:00B646D2 mov eax, edx
seg000:00B646D4 add eax, [ebp+var_itemoff17]
seg000:00B646D7 mov edx, [ebp+var_g_table]
seg000:00B646DA add eax, [edx+10h]
seg000:00B646DD jmp loc_B6478A
seg000:00B646E2 ;
seg000:00B646E2
seg000:00B646E2 loc_B646E2: ; CODE XREF: sub_B64668+68j
seg000:00B646E2 mov edx, [ebp+var_g_table]
seg000:00B646E5 add eax, [edx+18h]
seg000:00B646E8 jmp loc_B6478A
seg000:00B646ED ;
seg000:00B646ED
seg000:00B646ED loc_B646ED: ; CODE XREF: sub_B64668+50j
seg000:00B646ED xor eax, eax
seg000:00B646EF mov al, [ebx+4]
seg000:00B646F2 mov edx, [ebp+var_g_table]
seg000:00B646F5 mov edx, [edx+eax*4+40h]
seg000:00B646F9 mov eax, esi
seg000:00B646FB call edx
seg000:00B646FD mov ebx, eax
seg000:00B646FF mov ecx, [ebp+arg_8]
seg000:00B64702 mov edx, ebx
seg000:00B64704 mov eax, [ebp+var_g_table]
seg000:00B64707 call sub_B6490C
seg000:00B6470C test al, al
seg000:00B6470E jz short loc_B64721
seg000:00B64710 mov eax, [ebp+var_g_table]
seg000:00B64713 mov eax, [eax+18h]
seg000:00B64716 add eax, [ebp+var_itemoff17]
seg000:00B64719 mov edx, [ebp+var_g_table]
seg000:00B6471C add eax, [edx+68h]
seg000:00B6471F jmp short loc_B6478A
seg000:00B64721 ;
seg000:00B64721
seg000:00B64721 loc_B64721: ; CODE XREF: sub_B64668+A6j
seg000:00B64721 mov eax, [ebp+var_g_table]
seg000:00B64724 mov eax, [eax+18h]
seg000:00B64727 add eax, edi
seg000:00B64729 mov edx, [ebp+var_g_table]
seg000:00B6472C add eax, [edx+68h]
seg000:00B6472F jmp short loc_B6478A
seg000:00B64731 ;
seg000:00B64731
seg000:00B64731 loc_B64731: ; CODE XREF: sub_B64668+54j
seg000:00B64731 mov ecx, esi
seg000:00B64733 mov edx, [ebp+arg_4]
seg000:00B64736 mov eax, [ebp+var_g_table]
seg000:00B64739 call sub_B64544
seg000:00B6473E mov [ebp+arg_8], eax
seg000:00B64741 xor eax, eax
seg000:00B64743 mov al, [ebx+4]
seg000:00B64746 mov edx, [ebp+var_g_table]
seg000:00B64749 mov edx, [edx+eax*4+40h]
seg000:00B6474D mov eax, esi
seg000:00B6474F call edx
seg000:00B64751 mov ebx, eax
seg000:00B64753 mov ecx, [ebp+arg_8]
seg000:00B64756 mov edx, ebx
seg000:00B64758 mov eax, [ebp+var_g_table]
seg000:00B6475B call sub_B6490C
seg000:00B64760 test al, al
seg000:00B64762 jz short loc_B64775
seg000:00B64764 mov eax, [ebp+var_g_table]
seg000:00B64767 mov eax, [eax+18h]
seg000:00B6476A add eax, [ebp+var_itemoff17]
seg000:00B6476D mov edx, [ebp+var_g_table]
seg000:00B64770 add eax, [edx+68h]
seg000:00B64773 jmp short loc_B6478A
seg000:00B64775 ;
seg000:00B64775
seg000:00B64775 loc_B64775: ; CODE XREF: sub_B64668+FAj
seg000:00B64775 mov eax, [ebp+var_g_table]
seg000:00B64778 mov eax, [eax+18h]
seg000:00B6477B add eax, edi
seg000:00B6477D mov edx, [ebp+var_g_table]
seg000:00B64780 add eax, [edx+68h] ; eax = g_table[18] + off
seg000:00B64783 jmp short loc_B6478A
seg000:00B64785 ;
seg000:00B64785
seg000:00B64785 loc_B64785: ; CODE XREF: sub_B64668+56j
seg000:00B64785 mov eax, 0B551E4h
seg000:00B6478A
seg000:00B6478A loc_B6478A: ; CODE XREF: sub_B64668+75j
seg000:00B6478A ; sub_B64668+80j ...
seg000:00B6478A mov edx, [ebp+var_parg]
seg000:00B6478D sub edx, 4
seg000:00B64790 mov [edx], eax ; modify return address = eax = g_table[18] + off
注意这里, 在干什么? 修改 栈里的call DA00000 的返回地址!!!!!
seg000:00B64792 mov eax, [ebp+arg_0]
seg000:00B64795 call getSEH
seg000:00B6479A push [ebp+var_parg]
seg000:00B6479D push [ebp+arg_8]
seg000:00B647A0 push [ebp+arg_4]
seg000:00B647A3 mov eax, [ebp+var_g_table]
seg000:00B647A6 jmp dword ptr [eax+20h]
seg000:00B647A6 sub_B64668 endp
这里的var_g_table 就是前面所说的第二张表,也就是全局表. b6474f中存的 call edx 最终的地址是查这张表获得的!
先来看看走到 B647A6的这个分支,(到达OEP后第一个call DA0000会走到这里) 其它分支在续文中继续介绍.
jump 的地址是全局表中偏移20h的地址. 这里是 DB0000 也就是 jump 到DB0000.
调来调去, 跳来跳去, 好玩吧.
来到 DB0000
看看DB0000的代码
Þt
seg000:00DB0000 ;
seg000:00DB0000
seg000:00DB0000 ; Segment type: Pure code
seg000:00DB0000 seg000 segment byte public 'CODE' use32
seg000:00DB0000 assume cs:seg000
seg000:00DB0000 ;org 0DB0000h
seg000:00DB0000 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
seg000:00DB0000 jmp short loc_DB0003
seg000:00DB0002 ;
seg000:00DB0002 nop
seg000:00DB0003
seg000:00DB0003 loc_DB0003: ; CODE XREF: seg000:00DB0000j
seg000:00DB0003 nop
seg000:00DB0004 jmp short loc_DB0008
seg000:00DB0004 ;
seg000:00DB0006 db 90h ;
seg000:00DB0007 db 90h ;
seg000:00DB0008 ;
seg000:00DB0008
seg000:00DB0008 loc_DB0008: ; CODE XREF: seg000:00DB0004j
seg000:00DB0008 lea ebx, [ecx+edx+451F90h]
seg000:00DB000F pop ebx ; ebx = stack location of saved eax
seg000:00DB0010 db 2Eh
seg000:00DB0010 jmp short loc_DB0014
seg000:00DB0010 ;
seg000:00DB0013 db 90h ;
seg000:00DB0014 ;
seg000:00DB0014
seg000:00DB0014 loc_DB0014: ; CODE XREF: seg000:00DB0010j
seg000:00DB0014 nop
seg000:00DB0015 nop
seg000:00DB0016 nop
seg000:00DB0017 nop
seg000:00DB0018 nop
seg000:00DB0019 nop
seg000:00DB001A nop
seg000:00DB001B nop
seg000:00DB001C nop
seg000:00DB001D nop
seg000:00DB001E nop
seg000:00DB001F nop
seg000:00DB0020 nop
seg000:00DB0021 nop
seg000:00DB0022 jmp short loc_DB0025
seg000:00DB0022 ;
seg000:00DB0024 db 90h ;
seg000:00DB0025 ;
seg000:00DB0025
seg000:00DB0025 loc_DB0025: ; CODE XREF: seg000:00DB0022j
seg000:00DB0025 nop
seg000:00DB0026 nop
seg000:00DB0027 nop
seg000:00DB0028 nop
seg000:00DB0029 nop
seg000:00DB002A nop
seg000:00DB002B nop
seg000:00DB002C nop
seg000:00DB002D db 64h
seg000:00DB002D jmp short loc_DB0032
seg000:00DB002D ;
seg000:00DB0030 db 90h ;
seg000:00DB0031 db 90h ;
seg000:00DB0032 ;
seg000:00DB0032
seg000:00DB0032 loc_DB0032: ; CODE XREF: seg000:00DB002Dj
seg000:00DB0032 lea ecx, [ebx+4]
seg000:00DB0035 mov ecx, [ecx] ; saved ecx -> ecx
seg000:00DB0037 nop
seg000:00DB0038 nop
seg000:00DB0039 nop
seg000:00DB003A nop
seg000:00DB003B nop
seg000:00DB003C nop
seg000:00DB003D push dword ptr [ebx+8]
seg000:00DB0040 jmp short loc_DB0043
seg000:00DB0040 ;
seg000:00DB0042 db 0C7h ; Ç
seg000:00DB0043 ;
seg000:00DB0043
seg000:00DB0043 loc_DB0043: ; CODE XREF: seg000:00DB0040j
seg000:00DB0043 nop
seg000:00DB0044 nop
seg000:00DB0045 nop
seg000:00DB0046 nop
seg000:00DB0047 nop
seg000:00DB0048 nop
seg000:00DB0049 nop
seg000:00DB004A nop
seg000:00DB004B nop
seg000:00DB004C nop
seg000:00DB004D pop edx ; saved edx -> edx
seg000:00DB004E jmp short loc_DB0051
seg000:00DB004E ;
seg000:00DB0050 db 90h ;
seg000:00DB0051 ;
seg000:00DB0051
seg000:00DB0051 loc_DB0051: ; CODE XREF: seg000:00DB004Ej
seg000:00DB0051 lea edi, [ebp+esi-3]
seg000:00DB0055 push dword ptr [ebx+1Ch]
seg000:00DB0058 nop
seg000:00DB0059 nop
seg000:00DB005A nop
seg000:00DB005B nop
seg000:00DB005C nop
seg000:00DB005D nop
seg000:00DB005E pop edi ; saved edi -> edi
seg000:00DB005F lea eax, [ebx+5Ah]
seg000:00DB0062 push dword ptr [ebx+0]
seg000:00DB0066 nop
seg000:00DB0067 nop
seg000:00DB0068 pop eax ; saved eax -> eax
seg000:00DB0069 nop
seg000:00DB006A nop
seg000:00DB006B nop
seg000:00DB006C nop
seg000:00DB006D nop
seg000:00DB006E nop
seg000:00DB006F nop
seg000:00DB0070 nop
seg000:00DB0071 lea ebp, [ebx+14h]
seg000:00DB0074 lea ebp, [ebp+ecx+6Fh]
seg000:00DB0078 nop
seg000:00DB0079 jmp short loc_DB007D
seg000:00DB0079 ;
seg000:00DB007B db 90h ;
seg000:00DB007C db 90h ;
seg000:00DB007D ;
seg000:00DB007D
seg000:00DB007D loc_DB007D: ; CODE XREF: seg000:00DB0079j
seg000:00DB007D sub ebp, ecx
seg000:00DB007F lea ebp, [ebp-6Fh]
seg000:00DB0082 jmp short loc_DB0085
seg000:00DB0082 ;
seg000:00DB0084 db 0C7h ; Ç
seg000:00DB0085 ;
seg000:00DB0085
seg000:00DB0085 loc_DB0085: ; CODE XREF: seg000:00DB0082j
seg000:00DB0085 lea ebp, [ebp+66h]
seg000:00DB0088
seg000:00DB008A db 90h ;
seg000:00DB008B ;
seg000:00DB008B
seg000:00DB008B loc_DB008B: ; CODE XREF: seg000:00DB0088j
seg000:00DB008B db 36h
seg000:00DB008B jmp short loc_DB008F
seg000:00DB008B ;
seg000:00DB008E db 90h ;
seg000:00DB008F ;
seg000:00DB008F
seg000:00DB008F loc_DB008F: ; CODE XREF: seg000:loc_DB008Bj
seg000:00DB008F lea ebp, [ebp-66h]
seg000:00DB0092 db 2Eh
seg000:00DB0092 jmp short loc_DB0096
seg000:00DB0092 ;
seg000:00DB0095 db 0F3h ; ó
seg000:00DB0096 ;
seg000:00DB0096
seg000:00DB0096 loc_DB0096: ; CODE XREF: seg000:00DB0092j
seg000:00DB0096 lea ebp, [ebp+esi+3Eh]
seg000:00DB009A jmp short loc_DB009D
seg000:00DB009A ;
seg000:00DB009C db 90h ;
seg000:00DB009D ;
seg000:00DB009D
seg000:00DB009D loc_DB009D: ; CODE XREF: seg000:00DB009Aj
seg000:00DB009D sub ebp, esi
seg000:00DB009F sub ebp, 3Eh ; '>'
seg000:00DB00A2 db 36h
seg000:00DB00A2 jmp short loc_DB00A6
seg000:00DB00A2 ;
seg000:00DB00A5 db 90h ;
seg000:00DB00A6 ;
seg000:00DB00A6
seg000:00DB00A6 loc_DB00A6: ; CODE XREF: seg000:00DB00A2j
seg000:00DB00A6 mov ebp, [ebp+0]
seg000:00DB00A9 nop
seg000:00DB00AA nop
seg000:00DB00AB nop
seg000:00DB00AC nop
seg000:00DB00AD nop
seg000:00DB00AE nop
seg000:00DB00AF nop
seg000:00DB00B0 nop
seg000:00DB00B1 nop
seg000:00DB00B2 jmp short loc_DB00B5
seg000:00DB00B2 ;
seg000:00DB00B4 db 90h ;
seg000:00DB00B5 ;
seg000:00DB00B5
seg000:00DB00B5 loc_DB00B5: ; CODE XREF: seg000:00DB00B2j
seg000:00DB00B5 lea esi, [edi+eax+1Bh]
seg000:00DB00B9 lea esi, [ebx+18h]
seg000:00DB00BC nop
seg000:00DB00BD jmp short loc_DB00C0
seg000:00DB00BD ;
seg000:00DB00BF db 90h ;
seg000:00DB00C0 ;
seg000:00DB00C0
seg000:00DB00C0 loc_DB00C0: ; CODE XREF: seg000:00DB00BDj
seg000:00DB00C0 push dword ptr [esi]
seg000:00DB00C2 sbb esi, 0FFFFFF91h
seg000:00DB00C5 xor esi, [esp+28h]
seg000:00DB00C9 pop esi ; saved esi -> esi
seg000:00DB00CA nop
seg000:00DB00CB jmp short loc_DB00CE
seg000:00DB00CB ;
seg000:00DB00CD db 90h ;
seg000:00DB00CE ;
seg000:00DB00CE
seg000:00DB00CE loc_DB00CE: ; CODE XREF: seg000:00DB00CBj
seg000:00DB00CE push dword ptr [ebx+0Ch]
seg000:00DB00D1 nop
seg000:00DB00D2 nop
seg000:00DB00D3 nop
seg000:00DB00D4 nop
seg000:00DB00D5 nop
seg000:00DB00D6 nop
seg000:00DB00D7 nop
seg000:00DB00D8 nop
seg000:00DB00D9 pop ebx ; saved ebx -> ebx
seg000:00DB00DA popf
seg000:00DB00DB nop
seg000:00DB00DC jmp short loc_DB00DF ; saved esp
seg000:00DB00DC ;
seg000:00DB00DE db 90h ;
seg000:00DB00DF ;
seg000:00DB00DF
seg000:00DB00DF loc_DB00DF: ; CODE XREF: seg000:00DB00DCj
seg000:00DB00DF pop esp ; saved esp
seg000:00DB00E0 jmp dword ptr [esp-4] ; return
DB0000的代码其实异常简单, 所有恢复所有寄存器,返回. 注意了,前面提到栈中的返回地址被修改了. 所以,返回是返回到这个被修改的地址上.
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)