【文章标题】: FosiX 2.3.10 注册算法分析
【文章作者】: WAKU
【作者邮箱】: wakuwakuwawaku@163.com
【软件名称】: FosiX
【软件大小】: 2.72MB
【下载地址】: http://www.hushpage.com/FoSi/Fosi_setup.zip
【加壳方式】: 无
【保护方式】: 无
【编写语言】: Delphi
【使用工具】: OD
【操作平台】: XP SP2
【软件介绍】: FosiX是一个磁盘清理工具,最大的特点是可以把磁盘
【作者声明】: 只是研究技术,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
说明:此文中有一些我习惯使用的符号,先写出来以免大家误解
注册码长度 > CL 其中>是赋值给的意思,即注册码的长度赋给CL
运行原程序,未注册的版本有30天的试用限制,点击Help>Register,弹出注册窗口.随便输入一组:
Name: WAKU
Key: 1234
点击Process Registration,等了一会标题栏显示FosiX.exe Key and username doesn't match.PEID查无壳,OD载入,搜索字符串Key and username doesn't match,找到地址00556145,双击后,往上翻翻,看到这些:
005560AE |. E8 498DFEFF call 0053EDFC
005560B3 |. 84C0 test al, al
005560B5 |. 74 45 je short 005560FC
005560B7 |. 8D95 D8FDFFFF lea edx, [ebp-228]
005560BD |. A1 78925700 mov eax, [579278]
005560C2 |. 8B00 mov eax, [eax]
005560C4 |. E8 F785F4FF call 0049E6C0
005560C9 |. 8B85 D8FDFFFF mov eax, [ebp-228]
005560CF |. 8D95 DCFDFFFF lea edx, [ebp-224]
005560D5 |. E8 3643EBFF call 0040A410
005560DA |. 8D85 DCFDFFFF lea eax, [ebp-224]
005560E0 |. BA 30625500 mov edx, 00556230 ; Key and username valid
005560E5 |. E8 7EEDEAFF call 00404E68
005560EA |. 8B95 DCFDFFFF mov edx, [ebp-224]
005560F0 |. A1 98AE5700 mov eax, [57AE98]
005560F5 |. E8 1E76F2FF call 0047D718
005560FA |. EB 63 jmp short 0055615F
005560FC |> BA 50625500 mov edx, 00556250 ; Demo
00556101 |. 8B83 00030000 mov eax, [ebx+300]
00556107 |. E8 0C76F2FF call 0047D718
0055610C |. BA 60625500 mov edx, 00556260 ; $2C926BA0
00556111 |. 8B83 08030000 mov eax, [ebx+308]
00556117 |. E8 FC75F2FF call 0047D718
0055611C |. 8D95 D0FDFFFF lea edx, [ebp-230]
00556122 |. A1 78925700 mov eax, [579278]
00556127 |. 8B00 mov eax, [eax]
00556129 |. E8 9285F4FF call 0049E6C0
0055612E |. 8B85 D0FDFFFF mov eax, [ebp-230]
00556134 |. 8D95 D4FDFFFF lea edx, [ebp-22C]
0055613A |. E8 D142EBFF call 0040A410
0055613F |. 8D85 D4FDFFFF lea eax, [ebp-22C]
00556145 |. BA 74625500 mov edx, 00556274 ; Key and username doesn't match
跳转很明显,只要005560AE处的CALL返回非0即可"Key and username valid"了,好我们在005560AE处下断,然后跟进CALL,看到这些:
0053EDFC /$ 53 push ebx
0053EDFD |. 56 push esi
0053EDFE |. 57 push edi
0053EDFF |. 83C4 B4 add esp, -4C
0053EE02 |. 8BF1 mov esi, ecx
0053EE04 |. 8D3C24 lea edi, [esp] ; ESP > EDI
0053EE07 |. 33C9 xor ecx, ecx
0053EE09 |. 8A0E mov cl, [esi] ; 注册码长度 > CL
0053EE0B |. 80F9 09 cmp cl, 9 ; 长度和9比
0053EE0E |. 72 02 jb short 0053EE12
0053EE10 |. B1 09 mov cl, 9 ; 如长度大于9,则截断为9位
0053EE12 |> 880F mov [edi], cl
0053EE14 |. 46 inc esi
0053EE15 |. 47 inc edi
0053EE16 |. F3:A4 rep movs byte ptr es:[edi], byte ptr>; 把注册码长度和注册码COPY到EDI指向的内存
0053EE18 |. 8BF2 mov esi, edx
0053EE1A |. 8D7C24 0A lea edi, [esp+A]
0053EE1E |. 33C9 xor ecx, ecx
0053EE20 |. 8A0E mov cl, [esi] ; 用户名长度 > CL
0053EE22 |. 80F9 32 cmp cl, 32 ; 长度和32H比
0053EE25 |. 72 02 jb short 0053EE29
0053EE27 |. B1 32 mov cl, 32 ; 如长度大于32H,则截断为32H位
0053EE29 |> 880F mov [edi], cl
0053EE2B |. 46 inc esi
0053EE2C |. 47 inc edi
0053EE2D |. F3:A4 rep movs byte ptr es:[edi], byte ptr>; 把用户名长度和用户名COPY到EDI指向的内存
0053EE2F |. 8BF0 mov esi, eax
0053EE31 |. 33DB xor ebx, ebx
0053EE33 |. 889E 55030000 mov [esi+355], bl
0053EE39 |. 8D4424 40 lea eax, [esp+40]
0053EE3D |. 50 push eax ; /Arg1
0053EE3E |. 8BCB mov ecx, ebx ; |
0053EE40 |. 8D5424 0E lea edx, [esp+E] ; |
0053EE44 |. 8BC6 mov eax, esi ; |
0053EE46 |. E8 05FEFFFF call 0053EC50 ; \跟进
0053EE4B |. 8D4424 40 lea eax, [esp+40]
0053EE4F |. 8BD4 mov edx, esp
0053EE51 |. 33C9 xor ecx, ecx
0053EE53 |. 8A08 mov cl, [eax]
0053EE55 |. 41 inc ecx
0053EE56 |. E8 A544ECFF call <比较真码和假码>
0053EE5B |. 0F94C0 sete al
0053EE5E |. 84C0 test al, al
0053EE60 |. 75 38 jnz short 0053EE9A
0053EE62 |. B3 01 mov bl, 1
0053EE64 |. 889E 55030000 mov [esi+355], bl
0053EE6A |. 8D4424 40 lea eax, [esp+40]
0053EE6E |. 50 push eax ; /Arg1
0053EE6F |. 8BCB mov ecx, ebx ; |
0053EE71 |. 8D5424 0E lea edx, [esp+E] ; |
0053EE75 |. 8BC6 mov eax, esi ; |
0053EE77 |. E8 D4FDFFFF call 0053EC50 ; \和0053EE46处的CALL一样,不过计算出的注册码不可用
0053EE7C |. 8D4424 40 lea eax, [esp+40]
0053EE80 |. 8BD4 mov edx, esp
0053EE82 |. 33C9 xor ecx, ecx
0053EE84 |. 8A08 mov cl, [eax]
0053EE86 |. 41 inc ecx
0053EE87 |. E8 7444ECFF call <比较真码和假码>
0053EE8C |. 0F94C0 sete al
0053EE8F |. 3C 01 cmp al, 1
0053EE91 |. 75 07 jnz short 0053EE9A
0053EE93 |. C686 55030000>mov byte ptr [esi+355], 1
0053EE9A |> 83C4 4C add esp, 4C
0053EE9D |. 5F pop edi
0053EE9E |. 5E pop esi
0053EE9F |. 5B pop ebx
0053EEA0 \. C3 retn
可见用户名最长32H位,即50位,注册码最长9位,超出的部分都将忽略.
另外,0053EE46和0053EE77的CALL都是call 0053EC50,也都会计算出一个注册码,不过经过测试,只有前一个CALL的注册码才是正确的,后一个虽然也提示valid,不过关掉注册窗口后还是未注册的.实际上如果前一个CALL的产生的真码和假码经过0053EE56处的CALL比较相等,后面的CALL根本不会执行.作者这样做的用意可能是迷惑cracker.好,让我们跟进0053EE46处的CALL,看到这些:
0053EC50 /$ 55 push ebp
0053EC51 |. 8BEC mov ebp, esp
0053EC53 |. 81C4 6CFFFFFF add esp, -94
0053EC59 |. 53 push ebx
0053EC5A |. 56 push esi
0053EC5B |. 57 push edi
0053EC5C |. 8BF2 mov esi, edx
0053EC5E |. 8D7D C2 lea edi, [ebp-3E]
0053EC61 |. 51 push ecx
0053EC62 |. 33C9 xor ecx, ecx
0053EC64 |. 8A0E mov cl, [esi]
0053EC66 |. 80F9 32 cmp cl, 32
0053EC69 |. 72 02 jb short 0053EC6D
0053EC6B |. B1 32 mov cl, 32
0053EC6D |> 880F mov [edi], cl
0053EC6F |. 46 inc esi
0053EC70 |. 47 inc edi
0053EC71 |. F3:A4 rep movs byte ptr es:[edi], byte ptr>; 如果你仔细的看过前面的注释,上面这段代码就不会陌生了
0053EC73 |. 59 pop ecx
0053EC74 |. 884D FF mov [ebp-1], cl
0053EC77 |. 8BD8 mov ebx, eax
0053EC79 |. 33C0 xor eax, eax
0053EC7B |. 8A45 C2 mov al, [ebp-3E]
0053EC7E |. 40 inc eax
0053EC7F |. 83F8 32 cmp eax, 32
0053EC82 |. 7F 0E jg short 0053EC92
0053EC84 |. 8D5405 C2 lea edx, [ebp+eax-3E]
0053EC88 |> C602 2C /mov byte ptr [edx], 2C
0053EC8B |. 40 |inc eax
0053EC8C |. 42 |inc edx
0053EC8D |. 83F8 33 |cmp eax, 33
0053EC90 |.^ 75 F6 \jnz short 0053EC88 ; 此循环在用户名后面补2CH,补齐为32H个字节
0053EC92 |> 8D8D 6CFFFFFF lea ecx, [ebp-94]
0053EC98 |. 8B93 04020000 mov edx, [ebx+204] ; [EBX+204]固定为0D04E23E
0053EC9E |. 8BC3 mov eax, ebx
0053ECA0 |. E8 53FEFFFF call <16进制转换为字符串> ; 把EDX中的数值转换为字符串,前面加上$符号,然后放到ECX所指向的内存中
0053ECA5 |. 8D95 6CFFFFFF lea edx, [ebp-94] ; [EBP-94]中的内容为$0D04E23E
0053ECAB |. 8D45 F5 lea eax, [ebp-B]
0053ECAE |. B1 09 mov cl, 9
0053ECB0 |. E8 AB45ECFF call 00403260
0053ECB5 |. B8 0A000000 mov eax, 0A
0053ECBA |. 8D55 F5 lea edx, [ebp-B]
0053ECBD |. 8DB5 7BFFFFFF lea esi, [ebp-85]
0053ECC3 |> 8A0A /mov cl, [edx]
0053ECC5 |. 880E |mov [esi], cl
0053ECC7 |. 46 |inc esi
0053ECC8 |. 42 |inc edx
0053ECC9 |. 48 |dec eax
0053ECCA |.^ 75 F7 \jnz short 0053ECC3 ; 此循环把$0D04323E复制到ESI指向的内存
0053ECCC |. B8 33000000 mov eax, 33
0053ECD1 |. 8D55 C2 lea edx, [ebp-3E]
0053ECD4 |. 8D75 85 lea esi, [ebp-7B]
0053ECD7 |> 8A0A /mov cl, [edx]
0053ECD9 |. 880E |mov [esi], cl
0053ECDB |. 46 |inc esi
0053ECDC |. 42 |inc edx
0053ECDD |. 48 |dec eax
0053ECDE |.^ 75 F7 \jnz short 0053ECD7 ; 此循环把用户名和补完2CH后的字符串复制到ESI指向的内存
0053ECE0 |. 8D8D 6CFFFFFF lea ecx, [ebp-94]
0053ECE6 |. 8B93 08020000 mov edx, [ebx+208] ; [EBX+208]固定为9014FB17
0053ECEC |. 8BC3 mov eax, ebx
0053ECEE |. E8 05FEFFFF call <16进制转换为字符串> ; 转换为$9014FB17
0053ECF3 |. 8D95 6CFFFFFF lea edx, [ebp-94]
0053ECF9 |. 8D45 F5 lea eax, [ebp-B]
0053ECFC |. B1 09 mov cl, 9
0053ECFE |. E8 5D45ECFF call 00403260
0053ED03 |. 807D FF 00 cmp byte ptr [ebp-1], 0
0053ED07 |. 74 17 je short 0053ED20 ; 必跳
0053ED09 |. B8 0A000000 mov eax, 0A
0053ED0E |. 8D55 F5 lea edx, [ebp-B]
0053ED11 |. 8D75 B8 lea esi, [ebp-48]
0053ED14 |> 8A0A /mov cl, [edx]
0053ED16 |. 49 |dec ecx
0053ED17 |. 880E |mov [esi], cl
0053ED19 |. 46 |inc esi
0053ED1A |. 42 |inc edx
0053ED1B |. 48 |dec eax
0053ED1C |.^ 75 F6 \jnz short 0053ED14
0053ED1E |. EB 14 jmp short 0053ED34
0053ED20 |> B8 0A000000 mov eax, 0A
0053ED25 |. 8D55 F5 lea edx, [ebp-B]
0053ED28 |. 8D75 B8 lea esi, [ebp-48]
0053ED2B |> 8A0A /mov cl, [edx]
0053ED2D |. 880E |mov [esi], cl
0053ED2F |. 46 |inc esi
0053ED30 |. 42 |inc edx
0053ED31 |. 48 |dec eax
0053ED32 |.^ 75 F7 \jnz short 0053ED2B ; 此循环把$9014FB17复制到ESI指向的内存
0053ED34 |> 8B93 14030000 mov edx, [ebx+314]
0053ED3A |. 8D8D 7BFFFFFF lea ecx, [ebp-85]
0053ED40 |. 8BC3 mov eax, ebx
0053ED42 |. E8 69FDFFFF call 0053EAB0 ; 进
0053ED47 |. 8BD0 mov edx, eax
0053ED49 |. 8D8D 6CFFFFFF lea ecx, [ebp-94]
0053ED4F |. 8BC3 mov eax, ebx
0053ED51 |. E8 A2FDFFFF call <16进制转换为字符串>
0053ED56 |. 8D95 6CFFFFFF lea edx, [ebp-94]
0053ED5C |. 8B45 08 mov eax, [ebp+8]
0053ED5F |. B1 09 mov cl, 9
0053ED61 |. E8 FA44ECFF call 00403260
0053ED66 |. 5F pop edi
0053ED67 |. 5E pop esi
0053ED68 |. 5B pop ebx
0053ED69 |. 8BE5 mov esp, ebp
0053ED6B |. 5D pop ebp
0053ED6C \. C2 0400 retn 4
到此,整理一下思路.首先把用户名用2CH(2CH就是逗号)补齐为32H长,比如用户名WAKU,就在后面补32H-4个逗号,设为字符串B.然后用了两个常量,0D04323E和9014FB17,分别把它们转换成$0D0432E3和$9014FB17的字符串形式,设为字符串A和C,然后把A、B和C连接起来成为ABC.
要注意的是Delphi的字符串有一个特点,就是在字符串前面会用一个字节表示字符串的长度,向上面的WAKU前面就有一个04,$0D04323E和$9014FB17前面分别有一个09.这样ABC的全貌就是这样的:
(09)$0D04323E(04)WAKU,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,(09)$9014FB17
括号内是由于ASCII表示不出来,所以我用数字表示了.
好,0053ED42处的CALL就是真码的计算过程了,让我们跟进看看:
0053EAB0 /$ 53 push ebx
0053EAB1 |. 56 push esi
0053EAB2 |. 57 push edi
0053EAB3 |. 83C4 B8 add esp, -48
0053EAB6 |. 8BF1 mov esi, ecx
0053EAB8 |. 8D3C24 lea edi, [esp]
0053EABB |. B9 11000000 mov ecx, 11
0053EAC0 |. F3:A5 rep movs dword ptr es:[edi], dword ptr [esi] ; 复制ABC到EDI
0053EAC2 |. 66:A5 movs word ptr es:[edi], word ptr [esi]
0053EAC4 |. A4 movs byte ptr es:[edi], byte ptr [esi]
0053EAC5 |. B1 47 mov cl, 47 ; CL计数为47H
0053EAC7 |. 8BC4 mov eax, esp
0053EAC9 |> 8BDA /mov ebx, edx ; EDX初始为00ABCDEF
0053EACB |. C1EB 08 |shr ebx, 8
0053EACE |. 81E3 FFFFFF00 |and ebx, 0FFFFFF
0053EAD4 |. 0FB630 |movzx esi, byte ptr [eax] ; ABC依次 > ESI
0053EAD7 |. 33D6 |xor edx, esi
0053EAD9 |. 81E2 FF000000 |and edx, 0FF
0053EADF |. 8B1495 085657>|mov edx, [edx*4+575608] ; 从575608处开始查表
0053EAE6 |. 33DA |xor ebx, edx
0053EAE8 |. 8BD3 |mov edx, ebx
0053EAEA |. 40 |inc eax
0053EAEB |. FEC9 |dec cl
0053EAED |.^ 75 DA \jnz short 0053EAC9
0053EAEF |. 8BC2 mov eax, edx ; 计算的结果 > EAX(EAX就离真码不远了^_^)
0053EAF1 |. 83C4 48 add esp, 48
0053EAF4 |. 5F pop edi
0053EAF5 |. 5E pop esi
0053EAF6 |. 5B pop ebx
0053EAF7 \. C3 retn
主要的计算过程就在那一个循环里,代码很简单,都是一些基本的运算,就不详细讲了.
在0053EAD9的AND EDX, 0FF后,EDX的范围只能为0~FFH,所以575608处的表有256个双字的值.弄清这点对做注册机有帮助.最后把计算结果放到EAX中返回.
从CALL中返回后,还是把EAX中的值转换为字符串,前面再加上$符号就是最终的注册码了.
Name: WAKU
Key: $D53AE353
完.
--------------------------------------------------------------------------------
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)