本帖最后由 fly1n 于 2017-1-14 05:14 编辑
更新一下,这两天偶尔又用到了Editplus,结果用了几下发现又提示无效了,发现自己有暗桩没有过掉,所以又研究了一下
这次用的1月5号才发布的最新的build 420
有些图没保存,所以前面的步骤就简单文字描述下
注册码又被无效之后,给 MessageBoxW 下断,断下后看到前面有个KillTimer函数,所以这个是个Timer事件
记下 TimerID = 6D,搜索 All Intermodular Calls,把 SetTimer 都打开看看,标记下ID为6D
发现有两处 SetTimer 的ID为6D,这两处就分别是 License 3 和 License 4 的校验,失败则 SetTimer
然后到 SetTimer 的代码处看一下,发现和我们上次分析的一样,这里还是在用CheckV4校验,不过Editplus在暗桩处就改了 License,所以会导致我们过不了校验
由于不知道暗桩的触发时机,所以动态调试就非常麻烦了
此时我们注意到我们已经发现的关闭前的一处暗桩,是下面这行代码更改了注册码
[Asm] 纯文本查看 复制代码 004D6029 . C701 01000000 mov dword ptr ds:[ecx],0x1
我们搜索 C701 01000000 这个特征码,并且注意一下这个暗桩的形式为
[Asm] 纯文本查看 复制代码 mov ax, xxx
cmp ax, xxx
je xxx
mov ecx, xxx
C701 01000000 mov dword ptr ds:[ecx],0x1
在找到的所有 mov dword ptr ds:[ecx],0x1 处过滤一下,就能找到所有的暗桩了
原来Editplus对注册码的前11位(不包括连接符 '-' )都有校验,囧,原来上回我才做了一半的工作啊
暗桩可以直接借助 IDA 分析
这里给出新的注册机源码片段和一组新码
[C] 纯文本查看 复制代码 int sum = 1;
for (int i = 0; i < wcslen(usr); ++i)
{
sum += usr[i];
}
int res = (sum * 3 + 39) % 16;
swprintf(unicode, 9, L"%x", res);
regcode[4] = unicode[0];
res = ((sum + 41) / 6 * 7) % 16;
swprintf(unicode, 9, L"%x", res);
regcode[6] = unicode[0];
res = ((3 * sum + 19) / 9) % 16;
swprintf(unicode, 9, L"%x", res);
regcode[7] = unicode[0];
res = (sum + 2) % 16;
swprintf(unicode, 9, L"%x", res);
regcode[8] = unicode[0];
res = ((3 * sum + 43) / 8) % 16;
swprintf(unicode, 9, L"%x", res);
regcode[9] = unicode[0];
res = ((sum + 10) / 3 * 8) % 16;
swprintf(unicode, 9, L"%x", res);
regcode[10] = unicode[0];
新码:
fly1n
D3958-85DD8-12345-12345-12345
===================================================================================
Editplus的注册码网上还是挺多的,但是其实都是3的(在注册表HKEY_LOCAL_MACHINE/SOFTWARE/ES-Computing/Editplus/Install里可以发现存的都是License,如果是4的key存的会是License 4),虽然3的key其实4也能用,但是由于本人有强迫症,key不用新版的心里不舒服- -,所以还是自己逆向了一下Editplus4的注册机制,采用的版本是build 395
首先PEID查下壳,发现是VC8的无壳程序
首先我们搜索VC8的按钮事件,Ctrl+G到00401000,Ctrl+B搜索33C05E5B5DC21C00,来到下面这里
[Asm] 纯文本查看 复制代码 00514E5A |> \33C0 xor eax,eax ; editplus.00595374; Default case of switch 00514D89
00514E5C |> 5E pop esi ; editplus.00514DA0
00514E5D |> 5B pop ebx ; editplus.00514DA0
00514E5E |. 5D pop ebp ; editplus.00514DA0
00514E5F \. C2 1C00 retn 0x1C
往上拉,找到 ja, jmp这里
[Asm] 纯文本查看 复制代码 00514D90 |. /0F87 C4000000 ja editplus.00514E5A
00514D96 |. |FF2485 634E51>jmp dword ptr ds:[eax*4+0x514E63]
00514D9D |> |FF55 14 call [arg.4] ; editplus.0053C26E; Case 39 ('9') of switch 00514D89
00514DA0 |. |E9 B1000000 jmp editplus.00514E56
在jmp这行下断,输入用户名和假码,点Register,单步走两步就到了下面这里,跟一下发现004D6CFF这行是错误提示,所以004D6CC3和004D6CD7这两个是关键call,由于网上已经有了很多3的真码,我用真码跟了一下,比较了一下和假码的流程的不同,很容易就知道004D6CC3这个函数是用V4的注册机制去测试注册码,我给他加了个标签_CheckV4,004D6CD7这个自然就是_CheckV3了,我们的任务就是第一个函数_CheckV4
[Asm] 纯文本查看 复制代码 004D6CB0 . 83EC 08 sub esp,0x8
004D6CB3 . 56 push esi ; editplus.0059B654
004D6CB4 . 8D4424 04 lea eax,dword ptr ss:[esp+0x4]
004D6CB8 . 50 push eax ; editplus.00595374
004D6CB9 . 8BF1 mov esi,ecx
004D6CBB . C74424 08 000>mov dword ptr ss:[esp+0x8],0x0
004D6CC3 . E8 58FDFFFF call <editplus._CheckV4>
004D6CC8 . 85C0 test eax,eax ; editplus.00595374
004D6CCA . 75 3D jnz short editplus.004D6D09
004D6CCC . 8D4C24 08 lea ecx,dword ptr ss:[esp+0x8]
004D6CD0 . 51 push ecx
004D6CD1 . 8BCE mov ecx,esi ; editplus.0059B654
004D6CD3 . 894424 0C mov dword ptr ss:[esp+0xC],eax ; editplus.00595374
004D6CD7 . E8 84FEFFFF call <editplus._CheckV3>
004D6CDC . 8B4C24 08 mov ecx,dword ptr ss:[esp+0x8]
004D6CE0 . 8B5424 04 mov edx,dword ptr ss:[esp+0x4] ; editplus.0059B654
004D6CE4 . 85C9 test ecx,ecx
004D6CE6 . 76 0A jbe short editplus.004D6CF2
004D6CE8 . 81FA 7F4E0000 cmp edx,0x4E7F
004D6CEE . 74 02 je short editplus.004D6CF2
004D6CF0 . 8BD1 mov edx,ecx
004D6CF2 > 85C0 test eax,eax ; editplus.00595374
004D6CF4 . 75 13 jnz short editplus.004D6D09
004D6CF6 . 85D2 test edx,edx
004D6CF8 . 74 0A je short editplus.004D6D04
004D6CFA . 6A FF push -0x1
004D6CFC . 6A 10 push 0x10
004D6CFE . 52 push edx
004D6CFF . E8 B33D0400 call <editplus.ShowError>
004D6D04 > 5E pop esi ; editplus.00514DA0
004D6D05 . 83C4 08 add esp,0x8
004D6D08 . C3 retn
跟进_CheckV4,004D6AF1这里有个跳,eax为0就直接跳出去了,所以上面的那个call是关键call,检查注册码的
[Asm] 纯文本查看 复制代码 004D6A20 >/$ 81EC 5C040000 sub esp,0x45C
004D6A26 |. A1 7C9D5C00 mov eax,dword ptr ds:[0x5C9D7C]
004D6A2B |. 33C4 xor eax,esp
004D6A2D |. 898424 580400>mov dword ptr ss:[esp+0x458],eax
004D6A34 |. 8B8424 600400>mov eax,dword ptr ss:[esp+0x460]
004D6A3B |. 53 push ebx
004D6A3C |. 55 push ebp
004D6A3D |. 8BE9 mov ebp,ecx
004D6A3F |. 8D4C24 08 lea ecx,dword ptr ss:[esp+0x8]
004D6A43 |. 51 push ecx
004D6A44 |. 68 F4010000 push 0x1F4
004D6A49 |. 8D9424 800000>lea edx,dword ptr ss:[esp+0x80]
004D6A50 |. 894424 14 mov dword ptr ss:[esp+0x14],eax
004D6A54 |. 52 push edx
004D6A55 |. 8D85 C8000000 lea eax,dword ptr ss:[ebp+0xC8]
004D6A5B |. 50 push eax
004D6A5C |. E8 4FFDFFFF call <editplus.GetDlgItemText> ; get username
004D6A61 |. 83C4 10 add esp,0x10
004D6A64 |. 837C24 08 00 cmp dword ptr ss:[esp+0x8],0x0
004D6A69 |. 8BD8 mov ebx,eax
004D6A6B |. 895C24 10 mov dword ptr ss:[esp+0x10],ebx
004D6A6F |. 75 07 jnz short editplus.004D6A78 ; username not null
004D6A71 |. 33C0 xor eax,eax
004D6A73 |. E9 CF000000 jmp editplus.004D6B47
004D6A78 |> 57 push edi
004D6A79 |. 8D4C24 0C lea ecx,dword ptr ss:[esp+0xC]
004D6A7D |. 51 push ecx
004D6A7E |. 6A 32 push 0x32
004D6A80 |. 8D5424 20 lea edx,dword ptr ss:[esp+0x20]
004D6A84 |. 52 push edx
004D6A85 |. 8D45 74 lea eax,[arg.28]
004D6A88 |. 50 push eax
004D6A89 |. E8 22FDFFFF call <editplus.GetDlgItemText> ; get password
004D6A8E |. 8BF8 mov edi,eax
004D6A90 |. 8B4424 1C mov eax,dword ptr ss:[esp+0x1C]
004D6A94 |. 83C4 10 add esp,0x10
004D6A97 |. 85C0 test eax,eax
004D6A99 |. 74 7E je short editplus.004D6B19 ; password not null
004D6A9B |. 56 push esi
004D6A9C |. 33F6 xor esi,esi
004D6A9E |. 85C0 test eax,eax
004D6AA0 |. 7E 44 jle short editplus.004D6AE6
004D6AA2 |> 0FB71C77 /movzx ebx,word ptr ds:[edi+esi*2] ; ******** non sense ********
004D6AA6 |. B9 00010000 |mov ecx,0x100
004D6AAB |. 66:3BD9 |cmp bx,cx
004D6AAE |. 73 0D |jnb short editplus.004D6ABD
004D6AB0 |. 0FB6D3 |movzx edx,bl
004D6AB3 |. 0FB70455 30F7>|movzx eax,word ptr ds:[edx*2+0x5EF730]
004D6ABB |. EB 1A |jmp short editplus.004D6AD7
004D6ABD |> 0FB7C3 |movzx eax,bx
004D6AC0 |. 50 |push eax ; /StringOrChar = 0000
004D6AC1 |. FF15 5CD75700 |call dword ptr ds:[<&USER32.CharUpperW>] ; \CharUpperW
004D6AC7 |. 0FB7C0 |movzx eax,ax
004D6ACA |. 66:85C0 |test ax,ax
004D6ACD |. 75 05 |jnz short editplus.004D6AD4
004D6ACF |. 0FB7C3 |movzx eax,bx
004D6AD2 |. EB 03 |jmp short editplus.004D6AD7
004D6AD4 |> 0FB7C0 |movzx eax,ax
004D6AD7 |> 66:890477 |mov word ptr ds:[edi+esi*2],ax
004D6ADB |. 46 |inc esi
004D6ADC |. 3B7424 10 |cmp esi,dword ptr ss:[esp+0x10]
004D6AE0 |.^ 7C C0 \jl short editplus.004D6AA2 ; ***************************
004D6AE2 |. 8B5C24 18 mov ebx,dword ptr ss:[esp+0x18]
004D6AE6 |> 57 push edi
004D6AE7 |. 53 push ebx
004D6AE8 |. E8 93F6FFFF call <editplus.CheckV4>
004D6AED |. 83C4 08 add esp,0x8
004D6AF0 |. 5E pop esi ; 00CB9A10
004D6AF1 |. 85C0 test eax,eax
004D6AF3 |. 75 0C jnz short editplus.004D6B01
004D6AF5 |. 8B4C24 10 mov ecx,dword ptr ss:[esp+0x10]
004D6AF9 |. C701 815F0000 mov dword ptr ds:[ecx],0x5F81
004D6AFF |. EB 45 jmp short editplus.004D6B46
004D6B01 |> 57 push edi
004D6B02 |. 53 push ebx
004D6B03 |. E8 48F0FFFF call <editplus.WriteReg>
004D6B08 |. 83C4 08 add esp,0x8
004D6B0B |. 85C0 test eax,eax
004D6B0D |. 75 0E jnz short editplus.004D6B1D
004D6B0F |. 8B5424 10 mov edx,dword ptr ss:[esp+0x10]
004D6B13 |. C702 7F4E0000 mov dword ptr ds:[edx],0x4E7F
004D6B19 |> 33C0 xor eax,eax
004D6B1B |. EB 29 jmp short editplus.004D6B46
004D6B1D |> 8B85 20010000 mov eax,dword ptr ss:[ebp+0x120]
004D6B23 |. 53 push ebx
004D6B24 |. 68 F4010000 push 0x1F4
004D6B29 |. 50 push eax
004D6B2A |. E8 1D7B0700 call <editplus.wcscpy_s> ; store username
004D6B2F |. 8B8D 24010000 mov ecx,dword ptr ss:[ebp+0x124]
004D6B35 |. 57 push edi
004D6B36 |. 6A 32 push 0x32
004D6B38 |. 51 push ecx
004D6B39 |. E8 0E7B0700 call <editplus.wcscpy_s> ; store password
004D6B3E |. 83C4 18 add esp,0x18
004D6B41 |. B8 01000000 mov eax,0x1
004D6B46 |> 5F pop edi ; 00CB9A10
004D6B47 |> 8B8C24 600400>mov ecx,dword ptr ss:[esp+0x460]
004D6B4E |. 5D pop ebp ; 00CB9A10
004D6B4F |. 5B pop ebx ; 00CB9A10
004D6B50 |. 33CC xor ecx,esp
004D6B52 |. E8 7F740700 call editplus.0054DFD6
004D6B57 |. 81C4 5C040000 add esp,0x45C
004D6B5D \. C2 0400 retn 0x4
跟进CheckV4,关键函数我都加了标签,其实不知道004D61D7是建CRC的表,不知道后面004D61F5的是CRC都没关系,就把第一个函数当生成了一个替换表然后第二个函数当查表就行了
GetAsciiOfUnicode这个函数是生成一段Unicode字符串里每个字符的每个十六进制位对应的ascii码,比如用户名fly1n,对应的Uniode是0066h,006Ch,0079h,0031h,0061h,这个函数生成的Ascii字符串就是"0066006C007900310061",在内存里就是30h,30h,36h,36h, ......
其实本质上就是个sprintf,C代码也放在下面了,调用过GetAsciiOfUnicode之后,Editplus又对生成的字符串计算了CRC16(关于查表法计算CRC16,CRC32网上有很多资料,就不赘述了),计算出一个16位的CRC16校验码后,用swprintf转成unicode字符串(4位数)
然后下面有两个比较,就是把CRC的结果字符串的前两位和注册码的3,4位比较,所以我们知道了注册码的3,4位是怎么得来的
下面的部分又对注册码第三位以后的部分重复了以上步骤,与注册码的第1,2位比较
至此我们就知道了注册码的前4位怎么来,对用户名fly1n,一个符合以上条件的码是08955-12345-12345-12345-12345
输入后我们得到提示,重启验证的,而Editplus用到了很多unicode,所以我们可以猜测它用的函数应该是W版本(实际上上面004D6B03那里的写注册表的函数跟进去就会发现确实如此)
[Asm] 纯文本查看 复制代码 004D6180 >/$ 81EC D00B0000 sub esp,0xBD0
004D6186 |. A1 7C9D5C00 mov eax,dword ptr ds:[0x5C9D7C]
004D618B |. 33C4 xor eax,esp
004D618D |. 898424 CC0B00>mov dword ptr ss:[esp+0xBCC],eax
004D6194 |. 53 push ebx
004D6195 |. 55 push ebp
004D6196 |. 8BAC24 DC0B00>mov ebp,dword ptr ss:[esp+0xBDC]
004D619D |. 56 push esi
004D619E |. 8BB424 E40B00>mov esi,dword ptr ss:[esp+0xBE4] ; editplus.00575E08
004D61A5 |. 8BC5 mov eax,ebp
004D61A7 |. 57 push edi
004D61A8 |. 8D50 02 lea edx,dword ptr ds:[eax+0x2]
004D61AB |. EB 03 jmp short editplus.004D61B0
004D61AD | 8D49 00 lea ecx,dword ptr ds:[ecx]
004D61B0 |> 66:8B08 /mov cx,word ptr ds:[eax]
004D61B3 |. 83C0 02 |add eax,0x2
004D61B6 |. 66:85C9 |test cx,cx
004D61B9 |.^ 75 F5 \jnz short editplus.004D61B0
004D61BB |. 2BC2 sub eax,edx
004D61BD |. D1F8 sar eax,1
004D61BF |. 8BD8 mov ebx,eax ; ebx = username.length
004D61C1 |. 8BC6 mov eax,esi
004D61C3 |. 8D50 02 lea edx,dword ptr ds:[eax+0x2]
004D61C6 |> 66:8B08 /mov cx,word ptr ds:[eax]
004D61C9 |. 83C0 02 |add eax,0x2
004D61CC |. 66:85C9 |test cx,cx
004D61CF |.^ 75 F5 \jnz short editplus.004D61C6
004D61D1 |. 2BC2 sub eax,edx
004D61D3 |. D1F8 sar eax,1
004D61D5 |. 8BF8 mov edi,eax ; edi = password.length
004D61D7 |. E8 94F2FFFF call <editplus.BuildCRCTable>
004D61DC |. 68 B80B0000 push 0xBB8
004D61E1 |. 8D4424 28 lea eax,dword ptr ss:[esp+0x28]
004D61E5 |. 50 push eax
004D61E6 |. 53 push ebx
004D61E7 |. 55 push ebp
004D61E8 |. E8 23F3FFFF call <editplus.GetAsciiOfUnicode>
004D61ED |. 50 push eax
004D61EE |. 8D4C24 38 lea ecx,dword ptr ss:[esp+0x38]
004D61F2 |. 51 push ecx
004D61F3 |. 6A 00 push 0x0
004D61F5 |. E8 D6F2FFFF call <editplus.CRC16>
004D61FA |. 0FB7D0 movzx edx,ax
004D61FD |. 52 push edx
004D61FE |. 8D4424 30 lea eax,dword ptr ss:[esp+0x30]
004D6202 |. 68 80FC5800 push editplus.0058FC80 ; UNICODE "%04X"
004D6207 |. 50 push eax
004D6208 |. E8 D33AF3FF call <editplus.swprintf>
004D620D |. 66:8B4E 04 mov cx,word ptr ds:[esi+0x4]
004D6211 |. 8D46 04 lea eax,dword ptr ds:[esi+0x4]
004D6214 |. 83C4 28 add esp,0x28
004D6217 |. 66:3B4C24 10 cmp cx,word ptr ss:[esp+0x10]
004D621C |. 74 04 je short editplus.004D6222
004D621E |> 33C0 xor eax,eax
004D6220 |. EB 5A jmp short editplus.004D627C
004D6222 |> 66:8B56 06 mov dx,word ptr ds:[esi+0x6]
004D6226 |. 66:3B5424 12 cmp dx,word ptr ss:[esp+0x12]
004D622B |.^ 75 F1 jnz short editplus.004D621E
004D622D |. 68 B80B0000 push 0xBB8
004D6232 |. 8D4C24 28 lea ecx,dword ptr ss:[esp+0x28]
004D6236 |. 51 push ecx
004D6237 |. 83C7 FE add edi,-0x2
004D623A |. 57 push edi
004D623B |. 50 push eax
004D623C |. E8 CFF2FFFF call <editplus.GetAsciiOfUnicode>
004D6241 |. 50 push eax
004D6242 |. 8D5424 38 lea edx,dword ptr ss:[esp+0x38]
004D6246 |. 52 push edx
004D6247 |. 6A 00 push 0x0
004D6249 |. E8 82F2FFFF call <editplus.CRC16>
004D624E |. 0FB7C0 movzx eax,ax
004D6251 |. 50 push eax
004D6252 |. 8D4C24 30 lea ecx,dword ptr ss:[esp+0x30]
004D6256 |. 68 80FC5800 push editplus.0058FC80 ; UNICODE "%04X"
004D625B |. 51 push ecx
004D625C |. E8 7F3AF3FF call <editplus.swprintf>
004D6261 |. 66:8B16 mov dx,word ptr ds:[esi]
004D6264 |. 83C4 28 add esp,0x28
004D6267 |. 33C0 xor eax,eax
004D6269 |. 66:3B5424 10 cmp dx,word ptr ss:[esp+0x10]
004D626E |. 75 0C jnz short editplus.004D627C
004D6270 |. 66:8B4E 02 mov cx,word ptr ds:[esi+0x2]
004D6274 |. 66:3B4C24 12 cmp cx,word ptr ss:[esp+0x12]
004D6279 |. 0F94C0 sete al
004D627C |> 8B8C24 DC0B00>mov ecx,dword ptr ss:[esp+0xBDC]
004D6283 |. 5F pop edi ; 0012F130
004D6284 |. 5E pop esi ; 0012F130
004D6285 |. 5D pop ebp ; 0012F130
004D6286 |. 5B pop ebx ; 0012F130
004D6287 |. 33CC xor ecx,esp
004D6289 |. E8 487D0700 call editplus.0054DFD6
004D628E |. 81C4 D00B0000 add esp,0xBD0
004D6294 \. C3 retn
[C] 纯文本查看 复制代码 void GetAsciiOfUnicode(wchar_t *words, char *ascii){
for (size_t i = 0, j = 0; i < wcslen(words); ++i, j += 4)
{
sprintf(ascii + j, "%04x", words[i]);[/i]
[i] }[/i]
}
对RegQueryValueW下断,重启程序,跟一下,发现我们的注册码还原出来和原来不一样了,第一位变成了1,同时发现写入还原后的注册码是在0050DAC4这一行,跟一下可以发现这里程序并不是先还原出我们原来的key再更改,而是直接就还原出了一个错误的key,所以我怀疑是这个所谓的重启验证其实是个误导,程序在关闭前还有个验证
[Asm] 纯文本查看 复制代码 0050DA99 |> 8A1E |/mov bl,byte ptr ds:[esi]
0050DA9B |. |8B7C24 28 ||mov edi,dword ptr ss:[esp+0x28]
0050DA9F |. |8819 ||mov byte ptr ds:[ecx],bl
0050DAA1 |. |41 ||inc ecx
0050DAA2 |. |46 ||inc esi
0050DAA3 |. |4F ||dec edi
0050DAA4 |. |897C24 28 ||mov dword ptr ss:[esp+0x28],edi
0050DAA8 |.^\75 EF |\jnz short editplus.0050DA99
0050DAAA |. 8B7C24 3C |mov edi,dword ptr ss:[esp+0x3C]
0050DAAE |. 894C24 14 |mov dword ptr ss:[esp+0x14],ecx
0050DAB2 |. EB 20 |jmp short editplus.0050DAD4
0050DAB4 |> 33C9 |xor ecx,ecx
0050DAB6 |. 8A4E 01 |mov cl,byte ptr ds:[esi+0x1]
0050DAB9 |. D3EA |shr edx,cl
0050DABB |. 2BC1 |sub eax,ecx
0050DABD |. 8A4E 04 |mov cl,byte ptr ds:[esi+0x4]
0050DAC0 |. 8B7424 14 |mov esi,dword ptr ss:[esp+0x14]
0050DAC4 |. 880E |mov byte ptr ds:[esi],cl ; !!!!
0050DAC6 |. 8B4C24 18 |mov ecx,dword ptr ss:[esp+0x18]
0050DACA |. 46 |inc esi
程序重启验证的部分如下,可以发现其实在算出我们的用户名和注册码以后,用的还是我们的CheckV4函数,所以这也验证了我们了以上猜想,我们只要找到程序关闭前的另一处校验,pass掉保证程序不更改我们的注册码,重启后就能注册成功
[Asm] 纯文本查看 复制代码 004603D0 $ 83EC 10 sub esp,0x10
004603D3 . 55 push ebp
004603D4 . 8D4424 0C lea eax,dword ptr ss:[esp+0xC]
004603D8 . 50 push eax
004603D9 . 68 74B65800 push editplus.0058B674 ; UNICODE "License 4"
004603DE . 894C24 0C mov dword ptr ss:[esp+0xC],ecx
004603E2 . C74424 18 000>mov dword ptr ss:[esp+0x18],0x0
004603EA . E8 11FDFFFF call <editplus.ReadKey> ; read key
004603EF . 8BE8 mov ebp,eax
004603F1 . 85ED test ebp,ebp
004603F3 . 75 05 jnz short editplus.004603FA
004603F5 . 5D pop ebp ; 00CB9A10
004603F6 . 83C4 10 add esp,0x10
004603F9 . C3 retn
004603FA > 53 push ebx
004603FB . 0FB65D 00 movzx ebx,byte ptr ss:[ebp]
004603FF . 33C9 xor ecx,ecx
00460401 . 8D43 01 lea eax,dword ptr ds:[ebx+0x1]
00460404 . BA 02000000 mov edx,0x2
00460409 . F7E2 mul edx
0046040B . 0F90C1 seto cl
0046040E . 56 push esi
0046040F . 57 push edi
00460410 . F7D9 neg ecx
00460412 . 0BC8 or ecx,eax
00460414 . 51 push ecx
00460415 . E8 2BDB0A00 call <editplus.new>
0046041A . 8BF0 mov esi,eax
0046041C . 8D3C1B lea edi,dword ptr ds:[ebx+ebx]
0046041F . 57 push edi
00460420 . 8D45 01 lea eax,dword ptr ss:[ebp+0x1]
00460423 . 50 push eax
00460424 . 8D4F 02 lea ecx,dword ptr ds:[edi+0x2]
00460427 . 51 push ecx
00460428 . 56 push esi
00460429 . 897424 28 mov dword ptr ss:[esp+0x28],esi
0046042D . 897C24 2C mov dword ptr ss:[esp+0x2C],edi
00460431 . E8 AFDB0E00 call <editplus.memcpy_s> ; username
00460436 . 83C4 14 add esp,0x14
00460439 . 33D2 xor edx,edx
0046043B . 66:891437 mov word ptr ds:[edi+esi],dx
0046043F . 90 nop
00460440 > 0FB706 movzx eax,word ptr ds:[esi]
00460443 . B9 20000000 mov ecx,0x20 ; skip space
00460448 . 66:3BC8 cmp cx,ax
0046044B . 74 0A je short editplus.00460457
0046044D . BA 09000000 mov edx,0x9 ; skip tab
00460452 . 66:3BD0 cmp dx,ax
00460455 . 75 05 jnz short editplus.0046045C
00460457 > 83C6 02 add esi,0x2
0046045A .^ EB E4 jmp short editplus.00460440
0046045C > 8BC3 mov eax,ebx
0046045E . 85DB test ebx,ebx
00460460 . 7E 2D jle short editplus.0046048F
00460462 . 8D4C37 FE lea ecx,dword ptr ds:[edi+esi-0x2]
00460466 . EB 08 jmp short editplus.00460470
00460468 . 8DA424 000000>lea esp,dword ptr ss:[esp]
0046046F . 90 nop
00460470 > 0FB711 movzx edx,word ptr ds:[ecx]
00460473 . BB 20000000 mov ebx,0x20
00460478 . 66:3BDA cmp bx,dx
0046047B . 74 0A je short editplus.00460487
0046047D . BB 09000000 mov ebx,0x9
00460482 . 66:3BDA cmp bx,dx
00460485 . 75 08 jnz short editplus.0046048F
00460487 > 48 dec eax
00460488 . 83E9 02 sub ecx,0x2
0046048B . 85C0 test eax,eax
0046048D .^ 7F E1 jg short editplus.00460470
0046048F > 8B5C24 10 mov ebx,dword ptr ss:[esp+0x10] ; editplus.00465210
00460493 . 56 push esi
00460494 . 33C9 xor ecx,ecx
00460496 . 81C3 68180000 add ebx,0x1868
0046049C . 68 F4010000 push 0x1F4
004604A1 . 53 push ebx
004604A2 . 66:890C46 mov word ptr ds:[esi+eax*2],cx
004604A6 . E8 A1E10E00 call <editplus.wcscpy_s> ; copy username
004604AB . 8B5424 20 mov edx,dword ptr ss:[esp+0x20]
004604AF . 52 push edx
004604B0 . E8 9BDA0A00 call editplus.0050DF50
004604B5 . 0FB67C2F 01 movzx edi,byte ptr ds:[edi+ebp+0x1]
004604BA . 33C9 xor ecx,ecx
004604BC . 8D47 01 lea eax,dword ptr ds:[edi+0x1]
004604BF . BA 02000000 mov edx,0x2
004604C4 . F7E2 mul edx
004604C6 . 0F90C1 seto cl
004604C9 . F7D9 neg ecx
004604CB . 0BC8 or ecx,eax
004604CD . 51 push ecx
004604CE . E8 72DA0A00 call <editplus.new>
004604D3 . 8BF0 mov esi,eax
004604D5 . 8B4424 2C mov eax,dword ptr ss:[esp+0x2C]
004604D9 . 03FF add edi,edi
004604DB . 57 push edi
004604DC . 8D4C28 02 lea ecx,dword ptr ds:[eax+ebp+0x2]
004604E0 . 51 push ecx
004604E1 . 8D57 02 lea edx,dword ptr ds:[edi+0x2]
004604E4 . 52 push edx
004604E5 . 56 push esi
004604E6 . E8 FADA0E00 call <editplus.memcpy_s>
004604EB . 33C0 xor eax,eax
004604ED . 66:890437 mov word ptr ds:[edi+esi],ax
004604F1 . 8B7C24 34 mov edi,dword ptr ss:[esp+0x34]
004604F5 . 56 push esi
004604F6 . 81C7 501C0000 add edi,0x1C50
004604FC . 6A 32 push 0x32
004604FE . 57 push edi
004604FF . E8 48E10E00 call <editplus.wcscpy_s>
00460504 . 56 push esi
00460505 . E8 46DA0A00 call editplus.0050DF50
0046050A . 55 push ebp
0046050B . E8 40DA0A00 call editplus.0050DF50
00460510 . 8BC3 mov eax,ebx
00460512 . 83C4 38 add esp,0x38
00460515 . 8D50 02 lea edx,dword ptr ds:[eax+0x2]
00460518 . EB 06 jmp short editplus.00460520
0046051A 8D9B 00000000 lea ebx,dword ptr ds:[ebx]
00460520 > 66:8B08 mov cx,word ptr ds:[eax]
00460523 . 83C0 02 add eax,0x2
00460526 . 66:85C9 test cx,cx
00460529 .^ 75 F5 jnz short editplus.00460520
0046052B . 2BC2 sub eax,edx
0046052D . D1F8 sar eax,1
0046052F . 74 53 je short editplus.00460584
00460531 . 8BC7 mov eax,edi
00460533 . 8D50 02 lea edx,dword ptr ds:[eax+0x2]
00460536 > 66:8B08 mov cx,word ptr ds:[eax]
00460539 . 83C0 02 add eax,0x2
0046053C . 66:85C9 test cx,cx
0046053F .^ 75 F5 jnz short editplus.00460536
00460541 . 2BC2 sub eax,edx
00460543 . D1F8 sar eax,1
00460545 . 74 3D je short editplus.00460584
00460547 . 57 push edi
00460548 . 53 push ebx
00460549 . BE 01000000 mov esi,0x1
0046054E . E8 2D5C0700 call <editplus.CheckV4>
有了这样的怀疑以后,这次我们在过了004D6B03 call <editplus.WriteReg>这行后,留心一下注册表,关闭程序后,注册码果然变了,那我们就找一下是哪里改变了这个注册码,先看看CheckV4,WriteReg那里,过了验证以后004D6B2A 和004D6B39 这里有两个wcscpy_s将堆栈中的数据拷贝了出来,于是我猜测这里存的两个字符串就是用作之后读取和更改的。对其中存注册码的那段地址下内存写入断点,关闭程序。果然!关闭程序的时候断点触发了,我们停在了下面这里,如果注册码第一位是0,就改为1,否则改为0,而注册码改了一位以后,同样的校验函数,我们是无论如何都不可能校验成功的,所以我们不能跳到更改注册码那里,所以上面00468A4D的那个跳转应该实现,00468A3E这行ds:[esi+0x1EEC]应该为0,而实际我们这里现在是1,那我们就对这里下内存写入断点,看看这里的这个1是什么时候被写入的
[Asm] 纯文本查看 复制代码 00468A10 >/$ 6A FF push -0x1
00468A12 |. 68 C20E5700 push editplus.00570EC2
00468A17 |. 64:A1 0000000>mov eax,dword ptr fs:[0]
00468A1D |. 50 push eax
00468A1E |. 51 push ecx
00468A1F |. 56 push esi
00468A20 |. A1 7C9D5C00 mov eax,dword ptr ds:[0x5C9D7C]
00468A25 |. 33C4 xor eax,esp
00468A27 |. 50 push eax
00468A28 |. 8D4424 0C lea eax,dword ptr ss:[esp+0xC]
00468A2C |. 64:A3 0000000>mov dword ptr fs:[0],eax
00468A32 |. 8BF1 mov esi,ecx
00468A34 |. 897424 08 mov dword ptr ss:[esp+0x8],esi
00468A38 |. C706 D4C15800 mov dword ptr ds:[esi],editplus.0058C1D4 ; ASCII "朗E"
00468A3E |. 83BE EC1E0000>cmp dword ptr ds:[esi+0x1EEC],0x0
00468A45 |. C74424 14 0B0>mov dword ptr ss:[esp+0x14],0xB
00468A4D |. 74 52 je short editplus.00468AA1
00468A4F |. 80BE A81E0000>cmp byte ptr ds:[esi+0x1EA8],0x30
00468A56 |. 8D86 A81E0000 lea eax,dword ptr ds:[esi+0x1EA8]
00468A5C |. 0F94C1 sete cl
00468A5F |. 50 push eax
00468A60 |. 8D96 B41C0000 lea edx,dword ptr ds:[esi+0x1CB4]
00468A66 |. 80C1 30 add cl,0x30
00468A69 |. 52 push edx
00468A6A |. 8808 mov byte ptr ds:[eax],cl
00468A6C |. E8 2FCE0600 call editplus.004D58A0
00468A71 |. 8D86 501C0000 lea eax,dword ptr ds:[esi+0x1C50] ; Get regcode
00468A77 |. B9 30000000 mov ecx,0x30
00468A7C |. 83C4 08 add esp,0x8
00468A7F |. 66:3B08 cmp cx,word ptr ds:[eax]
00468A82 |. 75 0A jnz short editplus.00468A8E ; regcode[0] != 0
00468A84 |. BA 31000000 mov edx,0x31
00468A89 |. 66:8910 mov word ptr ds:[eax],dx ; !!!Change Key!!!
00468A8C |. EB 03 jmp short editplus.00468A91
00468A8E |> 66:8908 mov word ptr ds:[eax],cx
00468A91 |> 50 push eax
00468A92 |. 8D96 68180000 lea edx,dword ptr ds:[esi+0x1868]
00468A98 |. 52 push edx
00468A99 |. E8 B2D00600 call <editplus.WriteReg>
00468A9E |. 83C4 08 add esp,0x8
00468AA1 |> 8B86 441F0000 mov eax,dword ptr ds:[esi+0x1F44]
00468AA7 |. C64424 14 0A mov byte ptr ss:[esp+0x14],0xA
00468AAC |. 85C0 test eax,eax
00468AAE |. 74 08 je short editplus.00468AB8
00468AB0 |. 8B08 mov ecx,dword ptr ds:[eax]
00468AB2 |. 8B51 08 mov edx,dword ptr ds:[ecx+0x8]
00468AB5 |. 50 push eax
00468AB6 |. FFD2 call edx
00468AB8 |> 8B86 64180000 mov eax,dword ptr ds:[esi+0x1864] ; editplus.005F3F40
00468ABE |. 83E8 10 sub eax,0x10
00468AC1 |. C64424 14 09 mov byte ptr ss:[esp+0x14],0x9
00468AC6 |. 8D48 0C lea ecx,dword ptr ds:[eax+0xC]
00468AC9 |. 83CA FF or edx,-0x1
00468ACC |. F0:0FC111 lock xadd dword ptr ds:[ecx],edx
00468AD0 |. 4A dec edx
00468AD1 |. 85D2 test edx,edx
00468AD3 |. 7F 0A jg short editplus.00468ADF
00468AD5 |. 8B08 mov ecx,dword ptr ds:[eax]
00468AD7 |. 8B11 mov edx,dword ptr ds:[ecx]
00468AD9 |. 50 push eax
00468ADA |. 8B42 04 mov eax,dword ptr ds:[edx+0x4]
00468ADD |. FFD0 call eax
00468ADF |> 8D8E 94170000 lea ecx,dword ptr ds:[esi+0x1794]
00468AE5 |. C64424 14 08 mov byte ptr ss:[esp+0x14],0x8
00468AEA |. E8 7163FAFF call editplus.0040EE60
00468AEF |. 8B86 6C170000 mov eax,dword ptr ds:[esi+0x176C]
00468AF5 |. C786 68170000>mov dword ptr ds:[esi+0x1768],editplus.0>
00468AFF |. 85C0 test eax,eax
00468B01 |. 74 09 je short editplus.00468B0C
00468B03 |. 50 push eax
00468B04 |. E8 47540A00 call editplus.0050DF50
00468B09 |. 83C4 04 add esp,0x4
00468B0C |> 8D8E DC150000 lea ecx,dword ptr ds:[esi+0x15DC]
00468B12 |. C64424 14 06 mov byte ptr ss:[esp+0x14],0x6
00468B17 |. E8 64FEFFFF call editplus.00468980
00468B1C |. 8D8E 2C0C0000 lea ecx,dword ptr ds:[esi+0xC2C]
00468B22 |. C64424 14 05 mov byte ptr ss:[esp+0x14],0x5
00468B27 |. E8 F4FB0700 call editplus.004E8720
00468B2C |. 8D8E FC050000 lea ecx,dword ptr ds:[esi+0x5FC]
00468B32 |. C64424 14 04 mov byte ptr ss:[esp+0x14],0x4
00468B37 |. E8 74630500 call editplus.004BEEB0
00468B3C |. 8D8E 80040000 lea ecx,dword ptr ds:[esi+0x480]
00468B42 |. C64424 14 03 mov byte ptr ss:[esp+0x14],0x3
00468B47 |. E8 84FDFFFF call editplus.004688D0
00468B4C |. 8D8E 04030000 lea ecx,dword ptr ds:[esi+0x304]
00468B52 |. C64424 14 02 mov byte ptr ss:[esp+0x14],0x2
00468B57 |. E8 74FDFFFF call editplus.004688D0
00468B5C |. 8D8E 88010000 lea ecx,dword ptr ds:[esi+0x188]
00468B62 |. C64424 14 01 mov byte ptr ss:[esp+0x14],0x1
00468B67 |. E8 64FDFFFF call editplus.004688D0
00468B6C |. 8D8E EC000000 lea ecx,dword ptr ds:[esi+0xEC]
00468B72 |. C64424 14 00 mov byte ptr ss:[esp+0x14],0x0
00468B77 |. E8 5D0F0C00 call editplus.00529AD9
00468B7C |. 8BCE mov ecx,esi
00468B7E |. C74424 14 FFF>mov dword ptr ss:[esp+0x14],-0x1
00468B86 |. E8 CF5A0B00 call editplus.0051E65A
00468B8B |. 8B4C24 0C mov ecx,dword ptr ss:[esp+0xC]
00468B8F |. 64:890D 00000>mov dword ptr fs:[0],ecx
00468B96 |. 59 pop ecx
00468B97 |. 5E pop esi
00468B98 |. 83C4 10 add esp,0x10
00468B9B \. C3 retn
然后我们就到了下面这里,这段代码计算了用户名unicode的和然后+1存在ecx里,然后ecx=9*ecx+10,后面是个最简单的除法,除以3,之后计算了一下结果的绝对值,用swprintf将16进制的结果转为unicode字符串,然后将第一个位与我们的注册码的第5位做了一下比较,需要相等,至此我们就逆向出了Editplus4的整个注册码验证过程
[Asm] 纯文本查看 复制代码 004D5F10 $ 6A FF push -0x1
004D5F12 . 68 834F5700 push editplus.00574F83
004D5F17 . 64:A1 0000000>mov eax,dword ptr fs:[0]
004D5F1D . 50 push eax
004D5F1E . 83EC 20 sub esp,0x20
004D5F21 . A1 7C9D5C00 mov eax,dword ptr ds:[0x5C9D7C]
004D5F26 . 33C4 xor eax,esp
004D5F28 . 894424 1C mov dword ptr ss:[esp+0x1C],eax
004D5F2C . 53 push ebx
004D5F2D . 55 push ebp
004D5F2E . 56 push esi
004D5F2F . 57 push edi
004D5F30 . A1 7C9D5C00 mov eax,dword ptr ds:[0x5C9D7C]
004D5F35 . 33C4 xor eax,esp
004D5F37 . 50 push eax
004D5F38 . 8D4424 34 lea eax,dword ptr ss:[esp+0x34]
004D5F3C . 64:A3 0000000>mov dword ptr fs:[0],eax
004D5F42 . 8BE9 mov ebp,ecx
004D5F44 . 896C24 18 mov dword ptr ss:[esp+0x18],ebp
004D5F48 . C745 00 74535>mov dword ptr ss:[ebp],editplus.00595374
004D5F4F . 8B95 20010000 mov edx,dword ptr ss:[ebp+0x120]
004D5F55 . 8BC2 mov eax,edx
004D5F57 . C74424 3C 010>mov dword ptr ss:[esp+0x3C],0x1
004D5F5F . 8D70 02 lea esi,dword ptr ds:[eax+0x2]
004D5F62 > 66:8B08 mov cx,word ptr ds:[eax]
004D5F65 . 83C0 02 add eax,0x2
004D5F68 . 66:85C9 test cx,cx
004D5F6B .^ 75 F5 jnz short editplus.004D5F62
004D5F6D . 2BC6 sub eax,esi
004D5F6F . D1F8 sar eax,1
004D5F71 . 8BD8 mov ebx,eax
004D5F73 . 895C24 14 mov dword ptr ss:[esp+0x14],ebx
004D5F77 . 85DB test ebx,ebx
004D5F79 . 0F8E B5000000 jle editplus.004D6034 ; usrlen != 0
004D5F7F . 33F6 xor esi,esi
004D5F81 . 33FF xor edi,edi
004D5F83 . 33C0 xor eax,eax
004D5F85 . 83FB 02 cmp ebx,0x2
004D5F88 . 8D4E 01 lea ecx,dword ptr ds:[esi+0x1] ; ecx = 1
004D5F8B . 7C 1F jl short editplus.004D5FAC
004D5F8D . 4B dec ebx
004D5F8E . 8BFF mov edi,edi
004D5F90 > 0FB72C42 movzx ebp,word ptr ds:[edx+eax*2]
004D5F94 . 03F5 add esi,ebp ; esi += usr
004D5F96 . 0FB76C42 02 movzx ebp,word ptr ds:[edx+eax*2+0x2]
004D5F9B . 83C0 02 add eax,0x2
004D5F9E . 03FD add edi,ebp ; edi += usr[i+1]
004D5FA0 . 3BC3 cmp eax,ebx
004D5FA2 .^ 7C EC jl short editplus.004D5F90
004D5FA4 . 8B5C24 14 mov ebx,dword ptr ss:[esp+0x14]
004D5FA8 . 8B6C24 18 mov ebp,dword ptr ss:[esp+0x18]
004D5FAC > 3BC3 cmp eax,ebx
004D5FAE . 7D 05 jge short editplus.004D5FB5
004D5FB0 . 0FB70C42 movzx ecx,word ptr ds:[edx+eax*2] ; unicode of username last char
004D5FB4 . 41 inc ecx
004D5FB5 > 03F7 add esi,edi ; esi = username 2x位 unicode sum, 2x是小于用户名长度的最大偶数
004D5FB7 . 03CE add ecx,esi ; ecx = username unicode sum + 1
004D5FB9 . 8D4CC9 0A lea ecx,dword ptr ds:[ecx+ecx*8+0xA] ; ecx=9*ecx+10
004D5FBD . B8 56555555 mov eax,0x55555556
004D5FC2 . F7E9 imul ecx
004D5FC4 . 8BC2 mov eax,edx
004D5FC6 . C1E8 1F shr eax,0x1F
004D5FC9 . 8D4C02 24 lea ecx,dword ptr ds:[edx+eax+0x24] ; ecx/3+0x24
004D5FCD . 81E1 0F000080 and ecx,0x8000000F ; 带符号的最低位
004D5FD3 . 79 05 jns short editplus.004D5FDA
004D5FD5 . 49 dec ecx
004D5FD6 . 83C9 F0 or ecx,-0x10
004D5FD9 . 41 inc ecx
004D5FDA > 51 push ecx ; take ABS
004D5FDB . 8D5424 20 lea edx,dword ptr ss:[esp+0x20]
004D5FDF . 68 1C685800 push editplus.0058681C ; UNICODE "%1X"
004D5FE4 . 52 push edx
004D5FE5 . E8 F63CF3FF call <editplus.swprintf>
004D5FEA . 8B95 24010000 mov edx,dword ptr ss:[ebp+0x124]
004D5FF0 . 8BC2 mov eax,edx
004D5FF2 . 83C4 0C add esp,0xC
004D5FF5 . 8D70 02 lea esi,dword ptr ds:[eax+0x2]
004D5FF8 . EB 06 jmp short editplus.004D6000
004D5FFA 8D9B 00000000 lea ebx,dword ptr ds:[ebx]
004D6000 > 66:8B08 mov cx,word ptr ds:[eax]
004D6003 . 83C0 02 add eax,0x2
004D6006 . 66:85C9 test cx,cx
004D6009 .^ 75 F5 jnz short editplus.004D6000 ; pwdlen != 0
004D600B . 2BC6 sub eax,esi
004D600D . D1F8 sar eax,1
004D600F . 83F8 05 cmp eax,0x5
004D6012 . 72 0F jb short editplus.004D6023
004D6014 . 66:8B42 08 mov ax,word ptr ds:[edx+0x8] ; ax = pwd[4]
004D6018 . 66:3B4424 1C cmp ax,word ptr ss:[esp+0x1C] ; pwd[4] = 计算结果第一位
004D601D . 0F84 DC000000 je editplus.004D60FF
004D6023 > 8B8D 34010000 mov ecx,dword ptr ss:[ebp+0x134]
004D6029 . C701 01000000 mov dword ptr ds:[ecx],0x1 ; Checkpoint2!
算法的总结看注册机就好了,还挺简单易懂的,这里其实(tmp*9+10)/3直接用tmp*3+3作为结果应该也没事
[C] 纯文本查看 复制代码 UINT16 table[256];
void BuildCRCTable(UINT16 *table)
{
int i, j, ax;
for (i = 0; i < 0x100; ++i)
{
ax = 0xc0c1;
for (j = 1; j < 0x100; j <<= 1)
{
if (i & j)
table ^= ax;
ax <<= 1;
ax ^= 0x4003;
}
}
}
void GetAsciiOfUnicode(wchar_t *words, char *ascii)
{
for (size_t i = 0, j = 0; i < wcslen(words); ++i, j += 4)
{
sprintf(ascii + j, "%04x", words);
}
}
UINT16 CRC16(char *ascii)
{
UINT16 res = 0;
byte tmp;
for (size_t i = 0; i < strlen(ascii); ++i)
{
tmp = res & 0xFF;
res >>= 8;
tmp ^= ascii;
res ^= table[tmp];
}
return res;
}
void CEditplusKeygenDlg::OnBnClickedOk()
{
wchar_t usr[20], unicode[9], regcode[30] = L"12345-12345-12345-12345-12345";
GetDlgItemText(IDC_EDIT1, usr, 19);
int tmp = 1;
for (int i = 0; i < wcslen(usr); ++i)
{
tmp += usr;
}
tmp = (tmp * 9 + 10) / 3 + 0x24;
int res = tmp % 16;
swprintf(unicode, 9, L"%x", res);
regcode[4] = unicode[0];
char ascii[200];
GetAsciiOfUnicode(usr, ascii);
swprintf(unicode, 5, L"%04x", CRC16(strupr(ascii)));
regcode[2] = unicode[0];
regcode[3] = unicode[1];
wcsupr(regcode);
GetAsciiOfUnicode(regcode + 2, ascii);
swprintf(unicode, 5, L"%04x", CRC16(strupr(ascii)));
regcode[0] = unicode[0];
regcode[1] = unicode[1];
SetDlgItemText(IDC_EDIT2, CString(regcode));
}
最后放上一组key
Username: fly1n
Regcode: 79958-12345-12345-12345-12345
在注册表里可以看到这个是4的key
有说的不对或者不清楚的地方欢迎大家指正! |