SmartUndelete 2.6注册算法分析(有点不敢置信)
顺手搞的结果,所以没有按照一贯的正规格式写
最近我用替换SAM文件的方法获得了某台机器的管理员权限,但却不小心把
原来的SAM文件删掉了,眼看大事不妙,心想在DOS时代都有个UNDELETE实用程
序,现在到了Windows时代这类程序应该只会更多吧!于是搜了个这程序,用了
一下,被删的文件找到了,但必须注册程序才能恢复文件。(官网:
hxxp://www.smartundelete.com/,自行改正)
现在鄙人都已经养成了个习惯,凡是碰到程序要求注册的,首先想到的第
一件事便是PEID,呵呵,拿来一看,显示是VC++ 6.0写的程序,不错嘛,好象
又有软柿子了,运行注册,只有一个输入框,要求在其中输入序列号。随便输
入几个字符,出现提示信息:
Wrong Registration Key
然后OD加载,查找这个字串,来到:
////////////////// 以下是代码 ///////////////////
004045E4 . 6A 01 push 1
004045E6 . E8 FDC70200 call 00430DE8
004045EB . 8B0D 24834600 mov ecx, [468324] ; SmartUnd.004680EC
004045F1 . 8B46 5C mov eax, [esi+5C]
004045F4 . 51 push ecx ; 参数2:真码指针
004045F5 . 50 push eax ; 参数1:假码指针
004045F6 . E8 35F40100 call 00423A30
004045FB . 83C4 08 add esp, 8
004045FE . 85C0 test eax, eax ; 返回0为注册成功,非0为失败
00404600 . 6A 00 push 0
00404602 . 74 14 je short 00404618
00404604 . 68 F0834600 push 004683F0 ; ASCII "Message"
00404609 . 68 D8834600 push 004683D8 ; ASCII "Wrong Registration Key"
0040460E . 8BCE mov ecx, esi
00404610 . E8 5CBB0200 call 00430171
////////////////// 以上是代码 ///////////////////
还真是标准的C语言格式的函数调用,关键跳转一目了然,那么004045F6这个
call应该就是比较注册码的地方了吧!刚打算在004045EB这里下断点,鼠标一
点上去,下方状态框中竟然出现:
ds:[00468324]=004680EC (SmartUnd.004680EC), ASCII "4K5TY-UT3C2-KWP54-71MN2"
不是吧,自从调试器加载以来我还没输入过任何信息,怎么会自己出现注册
码?一开始我也觉得它可能是用来与输入的注册码实行某种运算的测试数据,
但这起码提示了注册码的格式,于是输入假码:
AAAAA-BBBBB-CCCCC-DDDDD
再跟进00423A30一看:
////////////////// 以下是代码 ///////////////////
00423A30 /$ 55 push ebp
00423A31 |. 8BEC mov ebp, esp
00423A33 |. 57 push edi
00423A34 |. 56 push esi
00423A35 |. 53 push ebx ; uses ebx esi edi
00423A36 |. 8B75 0C mov esi, [ebp+C] ; 真码
00423A39 |. 8B7D 08 mov edi, [ebp+8] ; 假码
00423A3C |. 8D05 6C304700 lea eax, [47306C]
00423A42 |. 8378 08 00 cmp dword ptr [eax+8], 0
00423A46 |. 75 3B jnz short 00423A83
00423A48 |. B0 FF mov al, 0FF
00423A4A |. 8BFF mov edi, edi
00423A4C |> 0AC0 /or al, al ; 到达串尾?
00423A4E |. 74 2E |je short 00423A7E ; 成功
00423A50 |. 8A06 |mov al, [esi]
00423A52 |. 46 |inc esi ; 下个字符
00423A53 |. 8A27 |mov ah, [edi]
00423A55 |. 47 |inc edi
00423A56 |. 38C4 |cmp ah, al
00423A58 |.^ 74 F2 |je short 00423A4C
00423A5A |. 2C 41 |sub al, 41 ; al -= 'A'
00423A5C |. 3C 1A |cmp al, 1A
00423A5E |. 1AC9 |sbb cl, cl
00423A60 |. 80E1 20 |and cl, 20 ; cl=(al<'A' || al>'Z')?0:32;
00423A63 |. 02C1 |add al, cl
00423A65 |. 04 41 |add al, 41 ; 若是大写字母则转为小写,其余不变
00423A67 |. 86E0 |xchg al, ah ; 下对ah实行相同手续
00423A69 |. 2C 41 |sub al, 41
00423A6B |. 3C 1A |cmp al, 1A
00423A6D |. 1AC9 |sbb cl, cl
00423A6F |. 80E1 20 |and cl, 20
00423A72 |. 02C1 |add al, cl
00423A74 |. 04 41 |add al, 41
00423A76 |. 38E0 |cmp al, ah ; 比较是否相等
00423A78 |.^ 74 D2 \je short 00423A4C ; 不等,失败
00423A7A |. 1AC0 sbb al, al
00423A7C |. 1C FF sbb al, 0FF
00423A7E |> 0FBEC0 movsx eax, al
00423A81 |. EB 78 jmp short 00423AFB ; 跳至返回
00423A83 |> F0:FF05 68444>lock inc dword ptr [474468]
00423A8A |. 833D 64444700>cmp dword ptr [474464], 0
00423A91 |. 7F 04 jg short 00423A97
00423A93 |. 6A 00 push 0
00423A95 |. EB 15 jmp short 00423AAC
00423A97 |> F0:FF0D 68444>lock dec dword ptr [474468]
00423A9E |. 6A 13 push 13
00423AA0 |. E8 B4E9FFFF call 00422459
00423AA5 |. C70424 010000>mov dword ptr [esp], 1
00423AAC |> B8 FF000000 mov eax, 0FF
00423AB1 |. 33DB xor ebx, ebx
00423AB3 |. 90 nop
00423AB4 |> 0AC0 /or al, al
00423AB6 |. 74 27 |je short 00423ADF
00423AB8 |. 8A06 |mov al, [esi]
00423ABA |. 46 |inc esi
00423ABB |. 8A1F |mov bl, [edi]
00423ABD |. 47 |inc edi
00423ABE |. 38D8 |cmp al, bl
00423AC0 |.^ 74 F2 |je short 00423AB4
00423AC2 |. 50 |push eax
00423AC3 |. 53 |push ebx
00423AC4 |. E8 64B4FFFF |call 0041EF2D
00423AC9 |. 8BD8 |mov ebx, eax
00423ACB |. 83C4 04 |add esp, 4
00423ACE |. E8 5AB4FFFF |call 0041EF2D
00423AD3 |. 83C4 04 |add esp, 4
00423AD6 |. 38C3 |cmp bl, al
00423AD8 |.^ 74 DA \je short 00423AB4
00423ADA |. 1BC0 sbb eax, eax
00423ADC |. 83D8 FF sbb eax, -1
00423ADF |> 8BD8 mov ebx, eax
00423AE1 |. 58 pop eax
00423AE2 |. 0BC0 or eax, eax
00423AE4 |. 75 09 jnz short 00423AEF
00423AE6 |. F0:FF0D 68444>lock dec dword ptr [474468]
00423AED |. EB 0A jmp short 00423AF9
00423AEF |> 6A 13 push 13 ; /Arg1 = 00000013
00423AF1 |. E8 C4E9FFFF call 004224BA ; \SmartUnd.004224BA
00423AF6 |. 83C4 04 add esp, 4
00423AF9 |> 8BC3 mov eax, ebx
00423AFB |> 5B pop ebx
00423AFC |. 5E pop esi
00423AFD |. 5F pop edi
00423AFE |. C9 leave
00423AFF \. C3 retn
////////////////// 以上是代码 ///////////////////
有意思了,从00423A4C到00423A78这段程序就是在逐字符比较两个串是否
相等,虽然其中有一段把大写字母变小写的例程,但不影响实质,如果串
比较成功,最后必定从00423A4E跳出,eax中返回0;一旦比较失败,则经
过00423A7A以下的指令后,eax中返回1或-1。于是注册码为常字符串:
4K5TY-UT3C2-KWP54-71MN2
(当然,其中的某些字母也可改为其小写形式。)也许还有其他注册码,
但从00423A83到返回,其间还有一大段代码,却没有机会执行,也就不好
推断它是完成什么功能。因为这段代码只有当全局变量[473074]不等于0
时才有机会被执行,而我反复运行无数次,这个变量的值却始终是0!
鄙人还是奇怪为什么会出现常值注册码,如果有人也对其注册算法有
兴趣研究一下,还望指教一二。