能力值:
( LV2,RANK:10 )
3 楼
【文章标题】: MFC实战--Hex Workshop V4.2破解笔记(三)
【文章作者】: frank
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
下面来解析函数:key_verify
.text:10002BA0 key_verify proc near ; CODE XREF: _102+2Ep
.text:10002BA0 ; sub_10003DE0+15Fp
.text:10002BA0
.text:10002BA0 var_1D8= dword ptr -1D8h
.text:10002BA0 var_1C8= byte ptr -1C8h
.text:10002BA0 var_1C7= dword ptr -1C7h
.text:10002BA0 var_1C0= dword ptr -1C0h
.text:10002BA0 var_1BC= dword ptr -1BCh
.text:10002BA0 var_1B8= dword ptr -1B8h
.text:10002BA0 var_1B4= dword ptr -1B4h
.text:10002BA0 var_1B0= dword ptr -1B0h
.text:10002BA0 var_190= dword ptr -190h
.text:10002BA0 var_140= dword ptr -140h
.text:10002BA0 var_F0= byte ptr -0F0h
.text:10002BA0 var_D0= dword ptr -0D0h
.text:10002BA0 var_B0= dword ptr -0B0h
.text:10002BA0 var_AC= dword ptr -0ACh
.text:10002BA0 var_A8= dword ptr -0A8h
.text:10002BA0 var_A4= dword ptr -0A4h
.text:10002BA0 var_A0= dword ptr -0A0h
.text:10002BA0 var_9C= dword ptr -9Ch
.text:10002BA0 var_98= dword ptr -98h
.text:10002BA0 var_94= dword ptr -94h
.text:10002BA0 var_90= dword ptr -90h
.text:10002BA0 var_8C= dword ptr -8Ch
.text:10002BA0 var_88= dword ptr -88h
.text:10002BA0 pProgramFile= dword ptr 8
.text:10002BA0 arg_4= dword ptr 0Ch
.text:10002BA0 arg_8= dword ptr 10h
.text:10002BA0 arg_C= dword ptr 14h
.text:10002BA0 pName= dword ptr 18h
.text:10002BA0 pCompany= dword ptr 1Ch
.text:10002BA0 pKey= dword ptr 20h
.text:10002BA0
.text:10002BA0 55 push ebp
.text:10002BA1 8B EC mov ebp, esp
.text:10002BA3 83 E4 F8 and esp, 0FFFFFFF8h
.text:10002BA6 81 EC CC 01 00 00 sub esp, 1CCh
.text:10002BAC 53 push ebx
.text:10002BAD 56 push esi
.text:10002BAE 57 push edi
.text:10002BAF 6A 00 push 0
.text:10002BB1 E8 6C 35 00 00 call __time64 =》生成随机变量
.text:10002BB1
.text:10002BB6 8B 5D 20 mov ebx, [ebp+pKey]
.text:10002BB9 83 C4 04 add esp, 4
.text:10002BBC 8B FB mov edi, ebx
.text:10002BBE 8B F0 mov esi, eax
.text:10002BC0 89 54 24 24 mov [esp+1D8h+var_1B4], edx
.text:10002BC4 E8 E7 F9 FF FF call sub_100025B0
.text:10002BC4
.text:10002BC9 84 C0 test al, al
.text:10002BCB 0F 85 0E 02 00 00 jnz loc_10002DDF
.text:10002BCB
.text:10002BD1 8D 44 24 12 lea eax, [esp+1D8h+var_1C7+1]
.text:10002BD5 50 push eax ; int
.text:10002BD6 8D 4C 24 14 lea ecx, [esp+14h] ; [esp+1DCh+var_1C8]
.text:10002BDA 51 push ecx ; int
.text:10002BDB 8D 54 24 1B lea edx, [esp+1E0h+var_1C7+2]
.text:10002BDF 52 push edx ; int
.text:10002BE0 8D 44 24 20 lea eax, [esp+1E4h+var_1C7+3] ; [esp+1E4h+var_1C4]
.text:10002BE4 50 push eax ; int
.text:10002BE5 8D 4C 24 21 lea ecx, [esp+1E8h+var_1C7]
.text:10002BE9 51 push ecx ; int
.text:10002BEA 8D 54 24 2C lea edx, [esp+1ECh+var_1C0]
.text:10002BEE 52 push edx ; int
.text:10002BEF 8D 44 24 34 lea eax, [esp+1F0h+var_1BC]
.text:10002BF3 50 push eax ; int
.text:10002BF4 53 push ebx ; char *
.text:10002BF5 E8 36 F7 FF FF call sub_10002330 ; Byte func(pKey, pInt, pInt, pByte,
.text:10002BF5 ; pInt, pByte, pByte, pByte);
.text:10002BF5 ;
.text:10002BF5 ; 参数:1/pKey
.text:10002BF5 ;
.text:10002BF5 ; 返回值:0/失败,非0/成功
.text:10002BF5
.text:10002BFA 83 C4 20 add esp, 20h
.text:10002BFD 84 C0 test al, al
.text:10002BFF 0F 84 F2 01 00 00 jz loc_10002DF7
.text:10002BFF
.text:10002C05 8B 4D 0C mov ecx, [ebp+arg_4] ; 04
.text:10002C08 38 4C 24 11 cmp byte ptr [esp+1D8h+var_1C7], cl
.text:10002C0C 0F 85 C1 01 00 00 jnz loc_10002DD3
.text:10002C0C
.text:10002C12 8B 44 24 14 mov eax, [esp+1D8h+var_1C7+3] ; [esp+1D8h+var_1C4]
.text:10002C12 ; 0b***00111
.text:10002C16 8B 7D 10 mov edi, [ebp+arg_8]
.text:10002C19 3B C7 cmp eax, edi
.text:10002C1B 0F 8C B2 01 00 00 jl loc_10002DD3
.text:10002C1B
.text:10002C21 8D 54 24 28 lea edx, [esp+1D8h+var_1B0]
.text:10002C25 52 push edx
.text:10002C26 50 push eax ; 2722
.text:10002C27 8B 45 08 mov eax, [ebp+pProgramFile] ; Hex WorkShop
.text:10002C2A 51 push ecx ; 04->BE
.text:10002C2B 50 push eax
.text:10002C2C E8 0F F1 FF FF call sub_10001D40 ; 注册表键值变形
.text:10002C2C ; 并将结果存入
.text:10002C2C ; 参数4所指地址
.text:10002C2C
.text:10002C31 83 C4 10 add esp, 10h
.text:10002C34 84 C0 test al, al
.text:10002C36 75 10 jnz short loc_10002C48
.text:10002C36
.text:10002C38 B9 6B 00 00 00 mov ecx, 6Bh
.text:10002C3D 33 C0 xor eax, eax
.text:10002C3F 8D 7C 24 28 lea edi, [esp+1D8h+var_1B0]
.text:10002C43 F3 AB rep stosd ; 函数返回值为0时
.text:10002C43 ; 使用_time64函数
.text:10002C43 ; 返回值低32bit填充缓冲区
.text:10002C45 8B 7D 10 mov edi, [ebp+arg_8]
.text:10002C45
.text:10002C48
.text:10002C48 loc_10002C48: ; CODE XREF: key_verify+96j
.text:10002C48 8D 54 24 28 lea edx, [esp+1D8h+var_1B0]
.text:10002C4C 8B C3 mov eax, ebx ; pKey
.text:10002C4E 2B D3 sub edx, ebx
.text:10002C4E
.text:10002C50
.text:10002C50 loc_10002C50: ; CODE XREF: key_verify+B8j
.text:10002C50 8A 08 mov cl, [eax]
.text:10002C52 88 0C 02 mov [edx+eax], cl
.text:10002C55 40 inc eax
.text:10002C56 84 C9 test cl, cl
.text:10002C58 75 F6 jnz short loc_10002C50
.text:10002C58
.text:10002C5A 8B 45 18 mov eax, [ebp+pName] ; pName
.text:10002C5D 8D 54 24 48 lea edx, [esp+1D8h+var_190]
.text:10002C61 2B D0 sub edx, eax
.text:10002C61
.text:10002C63
.text:10002C63 loc_10002C63: ; CODE XREF: key_verify+CBj
.text:10002C63 8A 08 mov cl, [eax]
.text:10002C65 88 0C 02 mov [edx+eax], cl
.text:10002C68 40 inc eax
.text:10002C69 84 C9 test cl, cl
.text:10002C6B 75 F6 jnz short loc_10002C63
.text:10002C6B
.text:10002C6D 8B 45 1C mov eax, [ebp+pCompany] ; pComapany
.text:10002C70 8D 94 24 98 00 00 00 lea edx, [esp+1D8h+var_140]
.text:10002C77 2B D0 sub edx, eax
.text:10002C79 8D A4 24 00 00 00 00 lea esp, [esp+0]
.text:10002C79
.text:10002C80
.text:10002C80 loc_10002C80: ; CODE XREF: key_verify+E8j
.text:10002C80 8A 08 mov cl, [eax]
.text:10002C82 88 0C 02 mov [edx+eax], cl
.text:10002C85 40 inc eax
.text:10002C86 84 C9 test cl, cl
.text:10002C88 75 F6 jnz short loc_10002C80
.text:10002C88
.text:10002C8A 8B 4C 24 1C mov ecx, [esp+1D8h+var_1BC]
.text:10002C8E 51 push ecx ; ****04$$-******-****
.text:10002C8E ; $$:0b***00111
.text:10002C8E ; field1-field2-field3
.text:10002C8E ; =>field2
.text:10002C8F 8D 94 24 EC 00 00 00 lea edx, [esp+1DCh+var_F0]
.text:10002C96 68 B4 C9 01 10 push offset s_06d ; "%06d"
.text:10002C9B 52 push edx ; char *
.text:10002C9C E8 B3 28 00 00 call _sprintf
.text:10002C9C
.text:10002CA1 8B 5D 08 mov ebx, [ebp+pProgramFile]
.text:10002CA4 8D 94 24 14 01 00 00 lea edx, [esp+1E4h+var_D0]
.text:10002CAB 83 C4 0C add esp, 0Ch
.text:10002CAE 8B C3 mov eax, ebx
.text:10002CB0 2B D3 sub edx, ebx
.text:10002CB0
.text:10002CB2
.text:10002CB2 loc_10002CB2: ; CODE XREF: key_verify+11Aj
.text:10002CB2 8A 08 mov cl, [eax] ; strcpy(var_D0, pProgramFile)
.text:10002CB4 88 0C 02 mov [edx+eax], cl
.text:10002CB7 40 inc eax
.text:10002CB8 84 C9 test cl, cl
.text:10002CBA 75 F6 jnz short loc_10002CB2
.text:10002CBA
.text:10002CBC 8B 44 24 18 mov eax, [esp+1D8h+var_1C0] ; ****04$$-******-****
.text:10002CBC ; $$:0b***00111
.text:10002CBC ; field1-field2-field3
.text:10002CBC ; =>*pArg3
.text:10002CC0 8B 4D 14 mov ecx, [ebp+arg_C] ; [esi+288h]
.text:10002CC3 89 84 24 28 01 00 00 mov [esp+1D8h+var_B0], eax
.text:10002CCA 8A 44 24 10 mov al, [esp+1D8h+var_1C8] ; *pArg7
.text:10002CCE 84 C0 test al, al
.text:10002CD0 89 8C 24 50 01 00 00 mov [esp+1D8h+var_88], ecx
.text:10002CD7 74 7C jz short loc_10002D55
.text:10002CD7
.text:10002CD9 8B 8C 24 38 01 00 00 mov ecx, [esp+1D8h+var_A0]
.text:10002CE0 85 C9 test ecx, ecx
.text:10002CE2 B8 01 00 00 00 mov eax, 1
.text:10002CE7 89 84 24 2C 01 00 00 mov [esp+1D8h+var_AC], eax
.text:10002CEE 0F 85 B7 00 00 00 jnz loc_10002DAB
.text:10002CEE
.text:10002CF4 6A 00 push 0
.text:10002CF6 6A 00 push 0
.text:10002CF8 6A 00 push 0
.text:10002CFA 6A 0F push 0Fh
.text:10002CFC 8D 4C 24 30 lea ecx, [esp+1E8h+var_1B8]
.text:10002D00 C7 84 24 40 01 00 00 00+mov [esp+1E8h+var_A8], 0
.text:10002D0B 89 84 24 44 01 00 00 mov [esp+1E8h+var_A4], eax
.text:10002D12 89 84 24 48 01 00 00 mov [esp+1E8h+var_A0], eax
.text:10002D19 C7 84 24 4C 01 00 00 0F+mov [esp+1E8h+var_9C], 0Fh
.text:10002D24 89 B4 24 50 01 00 00 mov [esp+1E8h+var_98], esi
.text:10002D2B 89 B4 24 54 01 00 00 mov [esp+1E8h+var_94], esi
.text:10002D32 E8 69 FB FF FF call sub_100028A0
.text:10002D32
.text:10002D37 8B 08 mov ecx, [eax]
.text:10002D39 8B 50 04 mov edx, [eax+4]
.text:10002D3C 8B 45 0C mov eax, [ebp+arg_4]
.text:10002D3F 03 CE add ecx, esi
.text:10002D41 57 push edi
.text:10002D42 50 push eax
.text:10002D43 89 54 24 2C mov [esp+1E0h+var_1B4], edx
.text:10002D47 89 8C 24 50 01 00 00 mov [esp+1E0h+var_90], ecx
.text:10002D4E E8 8D EE FF FF call sub_10001BE0
.text:10002D4E
.text:10002D53 EB 53 jmp short loc_10002DA8
.text:10002D53
.text:10002D55 ; ---------------------------------------------------------------------------
.text:10002D55
.text:10002D55 loc_10002D55: ; CODE XREF: key_verify+137j
.text:10002D55 8B 4D 0C mov ecx, [ebp+arg_4]
.text:10002D58 33 C0 xor eax, eax
.text:10002D5A 57 push edi
.text:10002D5B 51 push ecx
.text:10002D5C 89 84 24 34 01 00 00 mov [esp+1E0h+var_AC], eax
.text:10002D63 89 84 24 38 01 00 00 mov [esp+1E0h+var_A8], eax
.text:10002D6A 89 84 24 3C 01 00 00 mov [esp+1E0h+var_A4], eax
.text:10002D71 C7 84 24 40 01 00 00 01+mov [esp+1E0h+var_A0], 1
.text:10002D7C C7 84 24 44 01 00 00 FF+mov [esp+1E0h+var_9C], 0FFFFFFFFh
.text:10002D87 89 B4 24 48 01 00 00 mov [esp+1E0h+var_98], esi
.text:10002D8E 89 B4 24 4C 01 00 00 mov [esp+1E0h+var_94], esi
.text:10002D95 89 B4 24 50 01 00 00 mov [esp+1E0h+var_90], esi
.text:10002D9C 89 84 24 54 01 00 00 mov [esp+1E0h+var_8C], eax
.text:10002DA3 E8 A8 EE FF FF call sub_10001C50
.text:10002DA3
.text:10002DA8
.text:10002DA8 loc_10002DA8: ; CODE XREF: key_verify+1B3j
.text:10002DA8 83 C4 08 add esp, 8
.text:10002DA8
.text:10002DAB
.text:10002DAB loc_10002DAB: ; CODE XREF: key_verify+14Ej
.text:10002DAB 8B 45 0C mov eax, [ebp+arg_4]
.text:10002DAE 8D 54 24 28 lea edx, [esp+1D8h+var_1B0]
.text:10002DB2 52 push edx
.text:10002DB3 57 push edi
.text:10002DB4 50 push eax
.text:10002DB5 53 push ebx
.text:10002DB6 E8 E5 F1 FF FF call sub_10001FA0 ; 返回值:0/失败, 1/成功
.text:10002DB6
.text:10002DBB 83 C4 10 add esp, 10h
.text:10002DBE F6 D8 neg al
.text:10002DC0 1B C0 sbb eax, eax
.text:10002DC2 25 FF FE FF FF and eax, 0FFFFFEFFh
.text:10002DC7 05 01 01 00 00 add eax, 101h ; 最后返回值:0/成功, 非0/失败
.text:10002DC7 ; 非0:0x101, 5, 2
.text:10002DCC 5F pop edi
.text:10002DCD 5E pop esi
.text:10002DCE 5B pop ebx
.text:10002DCF 8B E5 mov esp, ebp
.text:10002DD1 5D pop ebp
.text:10002DD2 C3 retn
.text:10002DD2
.text:10002DD3 ; ---------------------------------------------------------------------------
.text:10002DD3
.text:10002DD3 loc_10002DD3: ; CODE XREF: key_verify+6Cj
.text:10002DD3 ; key_verify+7Bj
.text:10002DD3 B8 05 00 00 00 mov eax, 5
.text:10002DD8 5F pop edi
.text:10002DD9 5E pop esi
.text:10002DDA 5B pop ebx
.text:10002DDB 8B E5 mov esp, ebp
.text:10002DDD 5D pop ebp
.text:10002DDE C3 retn
.text:10002DDE
.text:10002DDF ; ---------------------------------------------------------------------------
.text:10002DDF
.text:10002DDF loc_10002DDF: ; CODE XREF: key_verify+2Bj
.text:10002DDF 8B 3D 54 C2 01 10 mov edi, ds:Sleep
.text:10002DE5 BE 0A 00 00 00 mov esi, 0Ah
.text:10002DEA 8D 9B 00 00 00 00 lea ebx, [ebx+0]
.text:10002DEA
.text:10002DF0
.text:10002DF0 loc_10002DF0: ; CODE XREF: key_verify+255j
.text:10002DF0 6A 64 push 64h ; dwMilliseconds
.text:10002DF2 FF D7 call edi ; Sleep
.text:10002DF4 4E dec esi
.text:10002DF5 75 F9 jnz short loc_10002DF0
.text:10002DF5
.text:10002DF7
.text:10002DF7 loc_10002DF7: ; CODE XREF: key_verify+5Fj
.text:10002DF7 5F pop edi
.text:10002DF8 5E pop esi
.text:10002DF9 B8 02 00 00 00 mov eax, 2
.text:10002DFE 5B pop ebx
.text:10002DFF 8B E5 mov esp, ebp
.text:10002E01 5D pop ebp
.text:10002E02 C3 retn
.text:10002E02
.text:10002E02 key_verify endp
.text:10002E02
该函数同样分支众多,我们来一一解析。
第一部分
========
首先第一个可能导致函数返回非零值的分支出现在对函数sub_100025B0返回值的检查上--0/继续执行, 非0/sleep会儿然后返回2.
跟进函数sub_100025B0为:
.text:100025B0 sub_100025B0 proc near ; CODE XREF: key_verify+24p
.text:100025B0
.text:100025B0 var_4= dword ptr -4
.text:100025B0
.text:100025B0 53 push ebx
.text:100025B1 32 DB xor bl, bl
.text:100025B3 E8 B8 FF FF FF call sub_10002570
.text:100025B3
.text:100025B8 A1 A8 31 02 10 mov eax, off_100231A8
.text:100025BD 85 C0 test eax, eax
.text:100025BF 74 35 jz short loc_100025F6
.text:100025BF
.text:100025C1 B8 A8 31 02 10 mov eax, offset off_100231A8
.text:100025C6 56 push esi
.text:100025C7 8B F0 mov esi, eax
.text:100025C9 8D A4 24 00 00 00 00 lea esp, [esp+0]
.text:100025C9
.text:100025D0
.text:100025D0 loc_100025D0: ; CODE XREF: sub_100025B0+3Aj
.text:100025D0 8B 00 mov eax, [eax]
.text:100025D2 50 push eax ; char *
.text:100025D3 57 push edi ; char *
.text:100025D4 E8 87 38 00 00 call _strstr
.text:100025D4
.text:100025D9 83 C4 08 add esp, 8
.text:100025DC 85 C0 test eax, eax
.text:100025DE 75 11 jnz short loc_100025F1
.text:100025DE
.text:100025E0 8B 4E 04 mov ecx, [esi+4]
.text:100025E3 83 C6 04 add esi, 4
.text:100025E6 85 C9 test ecx, ecx
.text:100025E8 8B C6 mov eax, esi
.text:100025EA 75 E4 jnz short loc_100025D0
.text:100025EA
.text:100025EC 5E pop esi
.text:100025ED 8A C3 mov al, bl
.text:100025EF 5B pop ebx
.text:100025F0 C3 retn
.text:100025F0
.text:100025F1 ; ---------------------------------------------------------------------------
.text:100025F1
.text:100025F1 loc_100025F1: ; CODE XREF: sub_100025B0+2Ej
.text:100025F1 5E pop esi
.text:100025F2 B0 01 mov al, 1
.text:100025F4 5B pop ebx
.text:100025F5 C3 retn
.text:100025F5
.text:100025F6 ; ---------------------------------------------------------------------------
.text:100025F6
.text:100025F6 loc_100025F6: ; CODE XREF: sub_100025B0+Fj
.text:100025F6 8A C3 mov al, bl
.text:100025F8 5B pop ebx
.text:100025F9 C3 retn
.text:100025F9
.text:100025F9 sub_100025B0 endp
.text:100025F9
.text:100025F9 ; ---------------------------------------------------------------------------
可以看出函数在对一个字符串数组进行循环比对,如果用户输入的key值是该数组某个元素的字串的话返回非0,如果都不是则返回0.
那么这个数组是什么呢?进一步跟进发现该数组是个全局变量(在.data段中),数组每个元素所指的字符串也是全局变量,但均为乱码!!
这说明程序启动以后还会对该乱码进行变化以使其变为正常的字符串。那么必然有函数引用该全局数组!!果然我们看到除函数sub_100025B0
引用概述组外,还有一个函数sub_10002570对其进行了引用!
.data:100231A7 00 align 4
.data:100231A8 5C 31 02 10 off_100231A8 dd offset s_LmlmmkoN
.data:100231A8 ; DATA XREF: sub_10002570+9r
.data:100231A8 ; sub_10002570+19o
.data:100231A8 ; sub_100025B0+8r
.data:100231A8 ; sub_100025B0+11o
.data:100231A8 ; "媽媽寠廂嵑"
.data:100231AC 68 31 02 10 dd offset s_Lmlmmkokn ; "媽媽寠帄嵑"
.data:100231B0 74 31 02 10 dd offset s_Lkoknckilkglc ; "媻帄崡妶媻儖楕偤"
.data:100231B4 88 31 02 10 dd offset s_Lkoknckilgolc ; "媻帄崡妶媰帇楟孇嫼"
.data:100231B8 9C 31 02 10 dd offset s_Lmlmnkoknk ; "媽媽崐帄崐"
跳到该函数为:
.text:10002570 sub_10002570 proc near ; CODE XREF: sub_100025B0+3p
.text:10002570 A0 80 49 02 10 mov al, byte_10024980 ; xor
.text:10002575 84 C0 test al, al
.text:10002577 75 35 jnz short locret_100025AE
.text:10002577
.text:10002579 A1 A8 31 02 10 mov eax, off_100231A8
.text:1000257E 85 C0 test eax, eax
.text:10002580 C6 05 80 49 02 10 01 mov byte_10024980, 1
.text:10002587 74 25 jz short locret_100025AE
.text:10002587
.text:10002589 B8 A8 31 02 10 mov eax, offset off_100231A8
.text:1000258E 8B C8 mov ecx, eax
.text:1000258E
.text:10002590
.text:10002590 loc_10002590: ; CODE XREF: sub_10002570+3Cj
.text:10002590 8B 00 mov eax, [eax]
.text:10002592 80 38 00 cmp byte ptr [eax], 0
.text:10002595 74 0B jz short loc_100025A2
.text:10002595
.text:10002597
.text:10002597 loc_10002597: ; CODE XREF: sub_10002570+30j
.text:10002597 80 30 BA xor byte ptr [eax], 0BAh
.text:1000259A 8A 50 01 mov dl, [eax+1]
.text:1000259D 40 inc eax
.text:1000259E 84 D2 test dl, dl
.text:100025A0 75 F5 jnz short loc_10002597
.text:100025A0
.text:100025A2
.text:100025A2 loc_100025A2: ; CODE XREF: sub_10002570+25j
.text:100025A2 8B 51 04 mov edx, [ecx+4]
.text:100025A5 83 C1 04 add ecx, 4
.text:100025A8 85 D2 test edx, edx
.text:100025AA 8B C1 mov eax, ecx
.text:100025AC 75 E2 jnz short loc_10002590
.text:100025AC
.text:100025AE
.text:100025AE locret_100025AE: ; CODE XREF: sub_10002570+7j
.text:100025AE ; sub_10002570+17j
.text:100025AE C3 retn
.text:100025AE
.text:100025AE sub_10002570 endp
.text:100025AE
该函数比较简单,不再做详细解释。以下是我对该函数的逆向源代码:
#define FILTER_MAX 5
Byte g_byte1[] = {0x8B, 0x8C, 0x8B, 0x8C, 0x8C, 0x8A, 0x8E, 0xFB, 0x8D, 0xBA, 0x00};
Byte g_byte2[] = {0x8B, 0x8C, 0x8B, 0x8C, 0x8C, 0x8A, 0x8E, 0x8A, 0x8D, 0XBA, 0x00};
Byte g_byte3[] = {0x8B, 0x8A, 0x8E, 0x8A, 0x8D, 0x97, 0x8A, 0x88, 0x8B, 0x8A, 0x83,
0x8B, 0x97, 0xF8, 0xF8, 0xFE, 0x82, 0xBA, 0x00};
Byte g_byte4[] = {0x8B, 0x8A, 0x8E, 0x8A, 0x8D, 0x97, 0x8A, 0x88, 0x8B, 0x83, 0x8E,
0x8B, 0x97, 0xFE, 0x8B, 0xFE, 0x00};
Byte g_byte5[] = {0x8B, 0x8C, 0x8B, 0x8C, 0x8D, 0x8A, 0x8E, 0x8A, 0x8D, 0x8A, 0x00};
PBYTE g_strArray[] = {g_byte1, g_byte2, g_byte3, g_byte4, g_byte5, 0};
static void SetFilter()
{
int i=0, j=0;
PBYTE temp = NULL;
while (temp = g_strArray[i]) {
#ifdef _DEBUG
printf("Original value: ");
j = 0;
while (temp[j]) {
printf("0x%02X ", temp[j]);
j++;
}
printf("\n");
#endif
j = 0;
while (temp[j]) {
temp[j] ^= 0xBA;
j++;
}
#ifdef _DEBUG
printf("New value: %s\n\n", temp);
#endif
i++;
}
return;
}
通过运行该函数可以得到个字符串为:
Original value: 0x8B 0x8C 0x8B 0x8C 0x8C 0x8A 0x8E 0xFB 0x8D 0xBA
New value: 1616604A7
Original value: 0x8B 0x8C 0x8B 0x8C 0x8C 0x8A 0x8E 0x8A 0x8D 0xBA
New value: 161660407
Original value: 0x8B 0x8A 0x8E 0x8A 0x8D 0x97 0x8A 0x88 0x8B 0x8A 0x83 0x8B 0x97
0xF8 0xF8 0xFE 0x82 0xBA
New value: 10407-021091-BBD8
Original value: 0x8B 0x8A 0x8E 0x8A 0x8D 0x97 0x8A 0x88 0x8B 0x83 0x8E 0x8B 0x97
0xFE 0x8B 0xFE
New value: 10407-021941-D1D
Original value: 0x8B 0x8C 0x8B 0x8C 0x8D 0x8A 0x8E 0x8A 0x8D 0x8A
New value: 1616704070
因此输入的key值切不可为以上5个字符串中任何一个的字串!!!--不过话说回来真正想命中这些字串还是比较有难度的,所以我们可以不必
太在乎这个纸老虎。
第二部份
========
第二个分支发生在对函数sub_10002330调用完毕后进行返回值检查时:0/失败--返回2,非0/成功--继续执行。
下面对该函数进行详细讲解(其实该函数才是真正对Key进行变换验证的地方):
函数共有8个参数:除参数1为用户输入的key以外,其余参数均为局部变量地址--说明该函数需要将解析所得值填入这些局部变量!!
7个局部变量参数中,除参数2、3、5为指向DWORD型指针外,其余均为指向BYTE型指针!!
返回值只检查al--说明返回值类型也为BYTE型。
据此我们可以写出函数原型为:
call sub_10002330 ; Byte sub_10002330(pKey, pInt, pInt, pByte,
; pInt, pByte, pByte, pByte);
;
; 参数:1/pKey
;
; 返回值:0/失败,非0/成功
2.1 key_parse函数逆向
sub_10002330函数同样也是个拥有众多分支的函数,限于篇幅我把关键的几个地方的分析贴出来供大家参考:
.text:10002350 8D 54 24 64 lea edx, [esp+164h+field3]
.text:10002354 52 push edx ; field3
.text:10002355 8D 84 24 A8 00 00 00 lea eax, [esp+168h+field2]
.text:1000235C 50 push eax ; field2
.text:1000235D 8D 4C 24 2C lea ecx, [esp+16Ch+field1]
.text:10002361 51 push ecx ; field1
.text:10002362 8D 94 24 F0 00 00 00 lea edx, [esp+170h+key]
.text:10002369 52 push edx ; char *
.text:1000236A E8 E1 FE FF FF call key_parse ; 解析参数1所指字符串:****0407-******-****
.text:1000236A
同样key_parse也是我重命名的结果,大家可以参考地址找到原函数。该函数的作用是把用户输入的Key值按'-'字符分隔开,并把
每段字串地址的指针付给三个输入的指针参数。比如输入Key为10000407-123456-0512,分割后会变成"10000407","123456","0512"。
注意:该函数还对段数以及每段字串长度做了检查--第一段长度不得小于5,第二段长度必须为6,第三段长度必须为4!
以下是我对该函数的逆向源代码:
Byte key_parse (char *pKey, char *field1, char *field2, char *field3)
{
char *temp = NULL;
/* Field1 parse */
temp = strtok(pKey, "-");
if(temp==NULL || strlen(temp) < FIELD1_LEN_MIN)
return 0;
else
strcpy(field1, temp);
#ifdef _DEBUG
printf("\nfield1: %s", field1);
#endif
/* Field2 parse */
temp = strtok(NULL, "-");
if(temp==NULL || strlen(temp) != FIELD2_LEN)
return 0;
else
strcpy(field2, temp);
#ifdef _DEBUG
printf("\nfield2: %s", field2);
#endif
/* Field3 parse */
temp = strtok(NULL, "-");
if(temp==NULL || strlen(temp) != FIELD3_LEN)
return 0;
else
strcpy(field3, temp);
#ifdef _DEBUG
printf("\nfield3: %s", field3);
#endif
return 1;
}
2.2 sub_10002330函数逆向
经过上述解析后sub_10002330函数的逆向工作变得简单起来,重点部分我已经在注释中说明了:
.text:1000237A 8D 44 24 18 lea eax, [esp+158h+field1]
.text:1000237E 8D 50 01 lea edx, [eax+1]
.text:1000237E
.text:10002381
.text:10002381 loc_10002381: ; CODE XREF: sub_10002330+56j
.text:10002381 8A 08 mov cl, [eax]
.text:10002383 40 inc eax
.text:10002384 84 C9 test cl, cl
.text:10002386 75 F9 jnz short loc_10002381
.text:10002386
.text:10002388 2B C2 sub eax, edx
.text:1000238A 83 F8 05 cmp eax, 5 ; 再次比较field1长度>=5
.text:1000238D 0F 8C B0 01 00 00 jl loc_10002543
.text:1000238D
.text:10002393 56 push esi
.text:10002394 8D 74 04 18 lea esi, [esp+eax+15Ch+var_144]
.text:10002398 8D 54 24 0C lea edx, [esp+15Ch+var_150]
.text:1000239C 8B C6 mov eax, esi
.text:1000239E 2B D6 sub edx, esi
.text:1000239E
.text:100023A0
.text:100023A0 loc_100023A0: ; CODE XREF: sub_10002330+78j
.text:100023A0 8A 08 mov cl, [eax] ; field最后4个字节copy到var_150变量中去
.text:100023A2 88 0C 02 mov [edx+eax], cl
.text:100023A5 40 inc eax
.text:100023A6 84 C9 test cl, cl
.text:100023A8 75 F6 jnz short loc_100023A0
.text:100023A8
.text:100023AA 88 0E mov [esi], cl
.text:100023AC 80 7C 24 1C 2A cmp byte ptr [esp+15Ch+field1], 2Ah ; '*'
.text:100023B1 75 0F jnz short loc_100023C2
.text:100023B1
.text:100023B3 8B 84 24 68 01 00 00 mov eax, [esp+15Ch+arg_8]
.text:100023BA C7 00 FF FF FF FF mov dword ptr [eax], 0FFFFFFFFh
.text:100023C0 EB 1D jmp short loc_100023DF
.text:100023C0
.text:100023C2 ; ---------------------------------------------------------------------------
.text:100023C2
.text:100023C2 loc_100023C2: ; CODE XREF: sub_10002330+81j
.text:100023C2 6A 0A push 0Ah ; int
.text:100023C4 8D 4C 24 0C lea ecx, [esp+160h+var_154]
.text:100023C8 51 push ecx ; char **
.text:100023C9 8D 54 24 24 lea edx, [esp+164h+field1]
.text:100023CD 52 push edx ; char *
.text:100023CE E8 2F 39 00 00 call _strtol ; field1头4个字节转为long
.text:100023CE
.text:100023D3 8B 8C 24 74 01 00 00 mov ecx, [esp+168h+arg_8]
.text:100023DA 83 C4 0C add esp, 0Ch
.text:100023DD 89 01 mov [ecx], eax ; 结果赋值参数3所指变量
.text:100023DD
.text:100023DF
.text:100023DF loc_100023DF: ; CODE XREF: sub_10002330+90j
.text:100023DF 8A 54 24 0C mov dl, byte ptr [esp+15Ch+var_150]
.text:100023E3 8A 44 24 0D mov al, byte ptr [esp+15Ch+var_150+1]
.text:100023E7 6A 10 push 10h ; int
.text:100023E9 8D 4C 24 0C lea ecx, [esp+160h+var_154]
.text:100023ED 88 54 24 1C mov [esp+160h+var_144], dl
.text:100023F1 51 push ecx ; char **
.text:100023F2 8D 54 24 20 lea edx, [esp+164h+var_144]
.text:100023F6 52 push edx ; char *
.text:100023F7 88 44 24 25 mov [esp+25h], al ; field1倒数第3个字节
.text:100023F7 ; 存放到栈变量中
.text:100023FB C6 44 24 26 00 mov byte ptr [esp+26h], 0
.text:10002400 E8 14 39 00 00 call _strtoul ; field1倒数第4,3个字节
.text:10002400 ; 按16进制转为long
.text:10002400
.text:10002405 8B 8C 24 78 01 00 00 mov ecx, [esp+168h+arg_C]
.text:1000240C 8B 54 24 14 mov edx, [esp+168h+var_154]
.text:10002410 88 01 mov [ecx], al ; 结果赋值参数4所指变量
.text:10002412 8A 02 mov al, [edx]
.text:10002414 83 C4 0C add esp, 0Ch
.text:10002417 84 C0 test al, al
.text:10002419 0F 85 2E 01 00 00 jnz loc_1000254D
.text:10002419
.text:1000241F 8A 44 24 0E mov al, byte ptr [esp+15Ch+var_150+2] ; field1倒数第2个字节
.text:10002423 8A 4C 24 0F mov cl, byte ptr [esp+15Ch+var_150+3] ; 最后个
.text:10002427 6A 10 push 10h ; int
.text:10002429 8D 54 24 0C lea edx, [esp+160h+var_154]
.text:1000242D 88 44 24 18 mov [esp+160h+var_148], al
.text:10002431 52 push edx ; char **
.text:10002432 8D 44 24 1C lea eax, [esp+164h+var_148]
.text:10002436 50 push eax ; char *
.text:10002437 88 4C 24 21 mov [esp+21h], cl ; 最后个字节存放栈变量
.text:1000243B C6 44 24 22 00 mov byte ptr [esp+22h], 0
.text:10002440 E8 D4 38 00 00 call _strtoul ; 倒数后2个字节按16进制long
.text:10002440
.text:10002445 8B 4C 24 14 mov ecx, [esp+168h+var_154]
.text:10002449 8A 11 mov dl, [ecx]
.text:1000244B 83 C4 0C add esp, 0Ch
.text:1000244E 84 D2 test dl, dl
.text:10002450 0F 85 F7 00 00 00 jnz loc_1000254D
.text:10002450
.text:10002456 8B B4 24 70 01 00 00 mov esi, [esp+15Ch+arg_10] ; 参数5
.text:1000245D 8B 9C 24 7C 01 00 00 mov ebx, [esp+15Ch+arg_1C] ; 参数8
.text:10002464 33 D2 xor edx, edx
.text:10002466 8A D0 mov dl, al
.text:10002468 8A C8 mov cl, al
.text:1000246A 80 E1 20 and cl, 20h
.text:1000246D 55 push ebp
.text:1000246E 8B AC 24 7C 01 00 00 mov ebp, [esp+160h+arg_18] ; 参数7
.text:10002475 57 push edi
.text:10002476 8B BC 24 7C 01 00 00 mov edi, [esp+164h+arg_14] ; 参数6
.text:1000247D 83 E2 1F and edx, 1Fh
.text:10002480 80 F9 20 cmp cl, 20h
.text:10002483 89 16 mov [esi], edx ; 转换结果&0x1F
.text:10002483 ; 存放到参数5所指变量
.text:10002485 0F 94 C2 setz dl
.text:10002488 8A C8 mov cl, al
.text:1000248A 80 E1 40 and cl, 40h
.text:1000248D 88 17 mov [edi], dl ; 转换结果与&0x20
.text:1000248D ; 结果赋值参数6所指变量
.text:1000248F 80 F9 40 cmp cl, 40h
.text:10002492 0F 94 C2 setz dl
.text:10002495 24 80 and al, 80h
.text:10002497 88 55 00 mov [ebp+0], dl ; 转换结果与&0x40
.text:10002497 ; 结果赋值参数7所指变量
.text:1000249A 6A 0A push 0Ah ; int
.text:1000249C 8D 4C 24 14 lea ecx, [esp+168h+var_154]
.text:100024A0 3C 80 cmp al, 80h
.text:100024A2 51 push ecx ; char **
.text:100024A3 8D 94 24 AC 00 00 00 lea edx, [esp+16Ch+field2]
.text:100024AA 0F 94 C0 setz al
.text:100024AD 52 push edx ; char *
.text:100024AE 88 03 mov [ebx], al ; 转换结果与&0x80
.text:100024AE ; 结果赋值参数8所指变量
.text:100024AE ;
.text:100024B0 E8 4D 38 00 00 call _strtol ; field2按10进制转为long
.text:100024B0
.text:100024B5 8B 8C 24 78 01 00 00 mov ecx, [esp+170h+arg_4]
.text:100024BC 8B 54 24 1C mov edx, [esp+170h+var_154]
.text:100024C0 89 01 mov [ecx], eax ; 结果赋值参数2所指变量
.text:100024C2 8A 02 mov al, [edx]
.text:100024C4 83 C4 0C add esp, 0Ch
.text:100024C7 84 C0 test al, al
.text:100024C9 0F 85 89 00 00 00 jnz loc_10002558
.text:100024C9
.text:100024CF 6A 10 push 10h ; int
.text:100024D1 8D 44 24 14 lea eax, [esp+168h+var_154]
.text:100024D5 50 push eax ; char **
.text:100024D6 8D 4C 24 6C lea ecx, [esp+16Ch+field3]
.text:100024DA 51 push ecx ; char *
.text:100024DB E8 39 38 00 00 call _strtoul ; field3转为16进制
.text:100024DB
.text:100024E0 8B 54 24 1C mov edx, [esp+170h+var_154]
.text:100024E4 89 44 24 20 mov [esp+170h+var_150], eax ; 结果赋值变量var_150
.text:100024E8 8A 02 mov al, [edx]
.text:100024EA 83 C4 0C add esp, 0Ch
.text:100024ED 84 C0 test al, al
.text:100024EF 75 67 jnz short loc_10002558
.text:100024EF
.text:100024F1 33 C0 xor eax, eax
.text:100024F3 8A 03 mov al, [ebx] ; 原参数8所指字节
.text:100024F5 33 C9 xor ecx, ecx
.text:100024F7 8A 4D 00 mov cl, [ebp+0] ; 原参数7所指字节
.text:100024FA 33 D2 xor edx, edx
.text:100024FC 8A 17 mov dl, [edi] ; 原参数6所指字节
.text:100024FE 50 push eax
.text:100024FF 8B 06 mov eax, [esi]
.text:10002501 51 push ecx
.text:10002502 8B 8C 24 7C 01 00 00 mov ecx, [esp+16Ch+arg_C]
.text:10002509 52 push edx
.text:1000250A 33 D2 xor edx, edx
.text:1000250C 8A 11 mov dl, [ecx]
.text:1000250E 50 push eax ; 原参数5所指Int
.text:1000250F 8B 84 24 80 01 00 00 mov eax, [esp+174h+arg_8]
.text:10002516 8B 08 mov ecx, [eax]
.text:10002518 52 push edx ; 原参数4所指字节
.text:10002519 8B 94 24 80 01 00 00 mov edx, [esp+178h+arg_4]
.text:10002520 8B 02 mov eax, [edx]
.text:10002522 51 push ecx ; 原参数3所指Int
.text:10002522 ; field1头4个字节
.text:10002522 ; strtol转换结果
.text:10002523 50 push eax ; 原参数2所指Int
.text:10002523 ; strtol(field2)
.text:10002524 E8 97 FC FF FF call sub_100021C0 ; func(arg2, arg3, arg4, arg5, arg6, arg7, arg8)
.text:10002524
.text:10002529 83 C4 1C add esp, 1Ch
.text:1000252C 0F B7 C8 movzx ecx, ax
.text:1000252F 8B 44 24 14 mov eax, [esp+164h+var_150]
.text:10002533 5F pop edi
.text:10002534 5D pop ebp
.text:10002535 3B C1 cmp eax, ecx
.text:10002537 5E pop esi
.text:10002538 0F 94 C0 setz al
.text:1000253B 5B pop ebx
.text:1000253C 81 C4 54 01 00 00 add esp, 154h
.text:10002542 C3 retn
.text:10002542
.text:10002543 ; ---------------------------------------------------------------------------
.text:10002543
.text:10002543 loc_10002543: ; CODE XREF: sub_10002330+5Dj
.text:10002543 32 C0 xor al, al
.text:10002545 5B pop ebx
.text:10002546 81 C4 54 01 00 00 add esp, 154h
.text:1000254C C3 retn
.text:1000254C
.text:1000254D ; ---------------------------------------------------------------------------
.text:1000254D
.text:1000254D loc_1000254D: ; CODE XREF: sub_10002330+E9j
.text:1000254D ; sub_10002330+120j
.text:1000254D 5E pop esi
.text:1000254E 32 C0 xor al, al
.text:10002550 5B pop ebx
.text:10002551 81 C4 54 01 00 00 add esp, 154h
.text:10002557 C3 retn
.text:10002557
.text:10002558 ; ---------------------------------------------------------------------------
.text:10002558
.text:10002558 loc_10002558: ; CODE XREF: sub_10002330+199j
.text:10002558 ; sub_10002330+1BFj
.text:10002558 5F pop edi
.text:10002559 5D pop ebp
.text:1000255A 5E pop esi
.text:1000255B 32 C0 xor al, al
.text:1000255D 5B pop ebx
.text:1000255E 81 C4 54 01 00 00 add esp, 154h
.text:10002564 C3 retn
.text:10002564
.text:10002565 ; ---------------------------------------------------------------------------
.text:10002565
.text:10002565 loc_10002565: ; CODE XREF: sub_10002330+44j
.text:10002565 8A C3 mov al, bl
.text:10002567 5B pop ebx
.text:10002568 81 C4 54 01 00 00 add esp, 154h
.text:1000256E C3 retn
.text:1000256E
.text:1000256E sub_10002330 endp
.text:1000256E
下面给出该函数的逆向源代码:
#define KEYBUF_LEN 0x80
#define FIELD_BUF_LEN 0x40
#define OTHER_BUF_LEN 0x08
Byte sub_10002330(char *pKey, int *pArg2, int *pArg3,
PBYTE pArg4, int *pArg5, PBYTE pArg6, PBYTE pArg7, PBYTE pArg8)
{
char key_buf[KEYBUF_LEN], field1_buf[FIELD_BUF_LEN];
char field2_buf[FIELD_BUF_LEN], field3_buf[FIELD_BUF_LEN];
int var_144=0, var_148=0;
char other_buf[OTHER_BUF_LEN], *pEndPtr;
int len = 0;
Byte rc = 0, tmp = 0;
strncpy(key_buf, pKey, KEYBUF_LEN);
if (key_parse(key_buf, field1_buf, field2_buf, field3_buf) == 0) {
/* key_parse failed: return 0 */
return rc;
}
if ((len = strlen(field1_buf)) < 5) {
return rc;
}
strcpy(other_buf, &field1_buf[len-4]);
field1_buf[len-4] = '\0';
if (field1_buf[0] == '*')
*pArg3 = -1;
else {
*pArg3 = strtol(field1_buf, &pEndPtr, 0x0A);
}
((char *)&var_144)[0] = other_buf[0];
((char *)&var_144)[1] = other_buf[1];
*pArg4 = (Byte) strtol((char *)&var_144, &pEndPtr, 0x10);
if (*pArg4 == 0)
return rc;
((char *)&var_148)[0] = other_buf[2];
((char *)&var_148)[1] = other_buf[3];
tmp = (Byte) strtol((char *)&var_148, &pEndPtr, 0x10);
if (*pEndPtr != NULL)
return rc;
*pArg5 = tmp & 0x1F;
*pArg6 = tmp & 0x20;
*pArg7 = tmp & 0x40;
*pArg8 = tmp & 0x80;
*pArg2 = strtol(field2_buf, &pEndPtr, 0x0A);
if (*pEndPtr != NULL)
return rc;
var_144 = strtol(field3_buf, &pEndPtr, 0x10);
if(*pEndPtr != NULL)
return rc;
var_148 = sub_100021C0(*pArg2, *pArg3, *pArg4, *pArg5, *pArg6, *pArg7, *pArg8);
if ((var_148 & 0xFFFF) == var_144)
rc = 1;
#ifdef _DEBUG
printf("%s(%d): return value %d\n", rc);
#endif
return rc;
}
声明:其中几个变量使用没有严格按照汇编代码翻译,而是做了多用途使用:var_144, var_148。
2.3 sub_100021C0函数逆向
该函数是函数sub_10002330调用的最后一个函数,其返回值直接决定sub_10002330函数的最后成败。
下面给出对该函数的分析:
返回值:ax--WORD型值
参数:共7个,观察得到为sub_10002330函数参数2-8指针所指向的变量值!
这些变量在调用sub_100021C0函数之前已经被赋予了值--具体参见2.2。
下面给出对该函数的逆向:
#define BUF_LEN 9
unsigned sub_100021C0 (int arg1, int arg2, Byte arg3, int arg4, Byte arg5, Byte arg6, Byte arg7)
{
unsigned buf[BUF_LEN] = {
arg1, ~arg1, arg2, ~arg2,
(unsigned)arg3, arg4,
(unsigned)arg5, (unsigned)arg6,
(unsigned)arg7
};
unsigned result;
result = sub_10004070((PBYTE)buf, sizeof(buf));
result = (result >> 16) ^ result;
#ifdef _DEBUG
printf("%s(%d)--result=%08X\n", __FILE__, __LINE__, result);
#endif
return result;
}
其中sub_10004070函数在程序中多处用到(后面注册表键值修改时还要用到),这里也给出对其的逆向:
#define XOR_SEED 0x1021
#define INNER_LOOP_MAX 7
int sub_10004070 (PBYTE buf, unsigned len)
{
int result=0xB0BAB0BA, temp = 0;
unsigned i=0, j=0;
if (len <= 0 )
return result;
while (i<len) {
temp = (int) (char)buf[i];
result ^= (temp << 8);
j = 0;
while (j++ < INNER_LOOP_MAX) {
if (result < 0) {
result = (result << 1) ^ XOR_SEED;
}
else
result <<= 1;
}
i++;
}
#ifdef _DEBUG
printf("\n%s(%d)--result=%08X\n", __FILE__, __LINE__, result);
#endif
return result;
}
2.4 计算返回值
就像2.2给出的源代码所示,程序用field3字段转化后的结果与sub_100021C0函数返回值比较--相等返回1(成功),不相等返回0(失败)。
第三部分--修改注册表键值
===========
上述两部分都正确执行以后就可以正确注册了,key_verify函数剩下的工作就是修改注册表以便下次启动能判断出是否已经注册过了。
本部分工作相对不这么重要,读者可自行分析。下面给出相关的几个函数逆向:
#ifdef _DEBUG
#define COLUM_LEN 8
static void DebugPrint(char *pTitle, PBYTE pData, int nDataLen)
{
int i = 0, j, temp;
printf("\n%s\n", pTitle);
printf("=====\n");
for (; i<nDataLen/COLUM_LEN; i++) {
printf("%08x: ", i);
temp = i<<3;
for (j=0; j<COLUM_LEN; j++)
printf("%02X ", pData[temp+j]);
printf("\n");
}
if (nDataLen % COLUM_LEN) {
printf("%08x: ", i);
temp = i<<3;
for (temp = i<<3; temp<nDataLen; temp++)
printf("%02X ", pData[temp]);
printf("\n");
}
}
#endif
static void RegKeyProcess(PBYTE pData, int nDataLen, DWORD seed)
{
int i=0, temp;
if (nDataLen<=0)
return;
for (; i<nDataLen; i+=4) {
temp = seed >> 31;
seed += seed;
temp |= seed;
seed = (i >> 2) ^ temp;
*(DWORD *)&pData[i] ^= seed;
}
#ifdef _DEBUG
DebugPrint("RegValue after process", (PBYTE)pData, nDataLen);
#endif
return;
}
#define VALUE_BUF_LEN 0x80
#define REGDATA_LEN 0x1AC
Byte sub_10001D40 (char *pProgramFile, int arg2, int arg3, char *pOutPut)
{
char ValueName[VALUE_BUF_LEN];
HGLOBAL pData;
HKEY hKey;
DWORD cbData = REGDATA_LEN, type = 3;
LONG rc = ERROR_SUCCESS;
int temp;
Byte result = 0;
sprintf(ValueName, "%s (%d-%02X)", pProgramFile,
(arg3 ^ (~0x55A) & 0XFFF), (arg2 ^ 0xBA));
temp = sub_10004070((PBYTE)ValueName, strlen(ValueName));
#ifdef _DEBUG
printf("\nValueName: %s, len=%d\n", ValueName, strlen(ValueName));
#endif
pData = GlobalAlloc(0, REGDATA_LEN);
RegOpenKeyEx(HKEY_CURRENT_USER, BREAK_LICENSE_MANAGER, 0, 0x20019, &hKey);
RegQueryValueEx(hKey, ValueName, 0, &type, (PBYTE)pData, &cbData);
#ifdef _DEBUG
DebugPrint(ValueName, (PBYTE)pData, cbData);
#endif
if (cbData == REGDATA_LEN) {
RegKeyProcess((PBYTE)pData, cbData, temp);
memcpy(pOutPut, pData, REGDATA_LEN);
temp = *(DWORD *)&pOutPut[0x1A8];
*(DWORD *)&pOutPut[0x1A8] = 0x0AC1DBA5E;
rc = sub_10004070((PBYTE)pOutPut, REGDATA_LEN);
*(DWORD *)&pOutPut[0x1A8] = temp;
if (temp == rc)
result = 1;
#ifdef _DEBUG
printf("%s(%d): result is %d\n", __FILE__, __LINE__, result);
#endif
}
RegCloseKey(hKey);
GlobalFree(pData);
return result;
}
到这里Hex Workshop V4.2加密算法部分的逆向基本完成了。注册表部分还是很有乐趣的,我这里限于篇幅没有做过多介绍--其实因为
文笔是在太烂了:).
--------------------------------------------------------------------------------
【经验总结】
1、关于本软件
用户输入Key值需如下格式:****04$7-******-****
其中第一个字段必须长度>=5(我采用了8个字节长), 第二、三字段长度分为6,4。
字段1会被解析成6个值,字段2按照16进制转为long型,字段3按照10进制转为long型。
字段1的6个值和字段2的值作为参数经过函数sub_100021C0运算后的返回值与字段3比较,相等则认为输入的Key正确,否则
返回错误。
2、关于MFC程序
1- 查找注册资源(如果有该资源的话)
2- 通过基类构造函数判断出正确的虚函数表
3- 通过相关虚函数或者AFX_MSG_ENTRY找到相应按钮处理函数
4- 如果有输入,可以通过重载的DoDataExchange静态分析出相应数据成员
进而可以进行算法分析了。
最后我采用的注册码为:10000407-123456-5162
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2009年01月29日 13:11:59
能力值:
( LV2,RANK:10 )
4 楼
因为本人帖子数量不够所以没有办法上传附件,特把此文件内容贴出来。各位只要把以下内容粘贴到注册表文件后,直接导入注册表即可将软件变为未注册。
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\BreakPoint License Manager]
"Hex Workshop (2722-BE)"=hex:b9,ef,4d,d9,9f,0a,6c,6c,f7,d5,3b,34,67,0f,fd,e0,\
cb,1e,fa,c1,92,3d,f4,83,23,7b,e8,07,41,f6,d0,0f,df,82,d3,7a,7a,b0,30,4b,55,\
c0,e2,1a,6b,64,0f,fd,db,c8,1e,fa,ba,91,3d,f4,7b,23,7b,e8,f8,46,f6,d0,e1,8d,\
ec,a1,d2,1b,d9,43,b6,37,b2,87,7e,6f,64,0f,e8,de,c8,1e,c5,bd,91,3d,9c,7b,23,\
7b,2f,f7,46,f6,47,ee,8d,ec,96,dc,1b,d9,37,b9,37,b2,74,72,6f,64,a1,8a,ac,ad,\
93,a0,ce,e5,92,e1,1e,47,f1,27,f7,46,c2,4f,ee,8d,a4,9f,dc,1b,6a,3f,b9,37,f7,\
7e,72,6f,ca,fd,e4,de,b0,fb,c9,bd,47,f7,93,7b,a9,ee,27,f7,7b,dd,4f,ee,de,ba,\
9f,dc,97,75,3f,b9,04,eb,7e,72,24,d6,fd,e4,64,ac,fb,c9,e7,58,f7,93,e0,b1,ee,\
27,b4,26,90,00,d1,c7,ba,9f,91,8f,75,3f,11,1f,eb,7e,16,3e,d6,fd,18,7c,ac,fb,\
07,f8,58,f7,38,f0,b1,ee,01,85,1b,fd,fd,af,b5,d1,1c,e9,e0,05,e5,02,1f,eb,f7,\
05,3e,d6,d2,0b,7c,ac,9b,17,f8,58,09,2f,f0,b1,53,5e,e0,63,e6,bc,c0,c7,8d,79,\
81,8f,58,f3,02,1f,f4,e6,05,3e,8f,cd,0b,7c,72,fb,6b,b1,0b,56,53,b9,5b,e8,f4,\
a9,23,d9,bc,c0,0f,b2,f9,c1,54,64,f3,02,e4,c8,e6,05,85,91,cd,0b,44,23,9b,17,\
c7,46,36,2f,de,8d,6c,5e,ed,1b,d9,bc,89,37,b2,79,41,6f,64,f3,d7,de,c8,e6,fa,\
bd,91,cd,a3,7b,23,9b,10,f7,46,36,78,ee,8d,6c,a9,dc,1b,d9,09,b9,37,b2,48,72,\
6f,64,cc,e4,de,c8,c4,c9,bd,91,d7,93,7b,23,f1,27,f7,46,82,4f,ee,8d,64,9f,dc,\
1b,aa,3e,b9,37,37,7d,72,6f,0a,fa,e4,de,70,f4,c9,bd,87,e8,93,7b,69,d1,27,f7,\
bb,a2,4f,ee,1e,45,9f,dc,6a,b5,0b,56 [HKEY_LOCAL_MACHINE\SOFTWARE\BreakPoint\Licenses]
"Hex Workshop (2722-BE)"=hex:b9,ef,4d,d9,9f,0a,6c,6c,f7,d5,3b,34,67,0f,fd,e0,\
cb,1e,fa,c1,92,3d,f4,83,23,7b,e8,07,41,f6,d0,0f,df,82,d3,7a,7a,b0,30,4b,55,\
c0,e2,1a,6b,64,0f,fd,db,c8,1e,fa,ba,91,3d,f4,7b,23,7b,e8,f8,46,f6,d0,e1,8d,\
ec,a1,d2,1b,d9,43,b6,37,b2,87,7e,6f,64,0f,e8,de,c8,1e,c5,bd,91,3d,9c,7b,23,\
7b,2f,f7,46,f6,47,ee,8d,ec,96,dc,1b,d9,37,b9,37,b2,74,72,6f,64,a1,8a,ac,ad,\
93,a0,ce,e5,92,e1,1e,47,f1,27,f7,46,c2,4f,ee,8d,a4,9f,dc,1b,6a,3f,b9,37,f7,\
7e,72,6f,ca,fd,e4,de,b0,fb,c9,bd,47,f7,93,7b,a9,ee,27,f7,7b,dd,4f,ee,de,ba,\
9f,dc,97,75,3f,b9,04,eb,7e,72,24,d6,fd,e4,64,ac,fb,c9,e7,58,f7,93,e0,b1,ee,\
27,b4,26,90,00,d1,c7,ba,9f,91,8f,75,3f,11,1f,eb,7e,16,3e,d6,fd,18,7c,ac,fb,\
07,f8,58,f7,38,f0,b1,ee,01,85,1b,fd,fd,af,b5,d1,1c,e9,e0,05,e5,02,1f,eb,f7,\
05,3e,d6,d2,0b,7c,ac,9b,17,f8,58,09,2f,f0,b1,53,5e,e0,63,e6,bc,c0,c7,8d,79,\
81,8f,58,f3,02,1f,f4,e6,05,3e,8f,cd,0b,7c,72,fb,6b,b1,0b,56,53,b9,5b,e8,f4,\
a9,23,d9,bc,c0,0f,b2,f9,c1,54,64,f3,02,e4,c8,e6,05,85,91,cd,0b,44,23,9b,17,\
c7,46,36,2f,de,8d,6c,5e,ed,1b,d9,bc,89,37,b2,79,41,6f,64,f3,d7,de,c8,e6,fa,\
bd,91,cd,a3,7b,23,9b,10,f7,46,36,78,ee,8d,6c,a9,dc,1b,d9,09,b9,37,b2,48,72,\
6f,64,cc,e4,de,c8,c4,c9,bd,91,d7,93,7b,23,f1,27,f7,46,82,4f,ee,8d,64,9f,dc,\
1b,aa,3e,b9,37,37,7d,72,6f,0a,fa,e4,de,70,f4,c9,bd,87,e8,93,7b,69,d1,27,f7,\
bb,a2,4f,ee,1e,45,9f,dc,6a,b5,0b,56