【文章标题】: Rapid PHP 2010 算法分析,注册机制作及简单网络验证
【文章作者】: ella
【软件名称】: Rapid PHP 2010 V10.0.2.118
【下载地址】: www.qarchive.org www.blumentals.net
【编写语言】: Delphi 6.0-7.0
【使用工具】: 没什么特别工具~^_^
【操作平台】: Windows XP Sp2
【作者声明】: 小菜鸟,凑热闹,学习而已,没有其他目的,失误之处敬请诸位牛牛赐教!~^_^
--------------------------------------------------------------------------------
【详细过程】
一,前期工作
查壳 PEID:不知道,Exeinfo PE:Program protector v2.1 ,走几步就脱了,略。
KANAL 2.9 等工具,显示N多算法,不管,我们开始。
未注册会出提示对话框,用30次,注册后提示框消失,功能上应该没什么限制。
二,主要部分算法分析
本来想用IDA复制代码,能识别显示函数,但看着好乱,OD里清楚点。
2.1, 算法主体部分及网络验证部分代码
00A4E344 55 push ebp ; 输入假码:RP0ABCDEFGHIJKL1234567890,来到关键地方。
00A4E345 8BEC mov ebp, esp
00A4E347 B9 06000000 mov ecx, 6
00A4E34C 6A 00 push 0
00A4E34E 6A 00 push 0
00A4E350 49 dec ecx
00A4E351 ^ 75 F9 jnz short 00A4E34C
00A4E353 53 push ebx
00A4E354 8BD8 mov ebx, eax
00A4E356 33C0 xor eax, eax
00A4E358 55 push ebp
00A4E359 68 73E5A400 push 00A4E573
00A4E35E 64:FF30 push dword ptr fs:[eax]
00A4E361 64:8920 mov dword ptr fs:[eax], esp
00A4E364 8D55 F4 lea edx, dword ptr [ebp-C]
00A4E367 8B83 FC020000 mov eax, dword ptr [ebx+2FC]
00A4E36D E8 6E76A8FF call 004D59E0 ; GetText
00A4E372 837D F4 00 cmp dword ptr [ebp-C], 0
00A4E376 75 1A jnz short 00A4E392
00A4E378 8B83 FC020000 mov eax, dword ptr [ebx+2FC]
00A4E37E 8B10 mov edx, dword ptr [eax]
00A4E380 FF92 C4000000 call dword ptr [edx+C4]
00A4E386 6A 00 push 0
00A4E388 E8 3FAB9BFF call <jmp.&user32.MessageBeep>
00A4E38D E9 91010000 jmp 00A4E523
00A4E392 8D55 EC lea edx, dword ptr [ebp-14]
00A4E395 8B83 FC020000 mov eax, dword ptr [ebx+2FC]
00A4E39B E8 4076A8FF call 004D59E0 ; GetText
00A4E3A0 8B45 EC mov eax, dword ptr [ebp-14]
00A4E3A3 8D55 F0 lea edx, dword ptr [ebp-10]
00A4E3A6 E8 1572A0FF call 004555C0 ; UpperCase 输入小写会自动改为大写
00A4E3AB 8B45 F0 mov eax, dword ptr [ebp-10]
00A4E3AE 8D55 F8 lea edx, dword ptr [ebp-8]
00A4E3B1 E8 DA76A0FF call 00455A90 ; Trim
00A4E3B6 8D55 E4 lea edx, dword ptr [ebp-1C]
00A4E3B9 8B83 FC020000 mov eax, dword ptr [ebx+2FC]
00A4E3BF E8 1C76A8FF call 004D59E0 ; GetText 重新取大写字串
00A4E3C4 8B45 E4 mov eax, dword ptr [ebp-1C]
00A4E3C7 8D55 E8 lea edx, dword ptr [ebp-18]
00A4E3CA E8 7DF4FFFF call 00A4D84C
00A4E3CF 8B45 E8 mov eax, dword ptr [ebp-18]
00A4E3D2 E8 21F5FFFF call 00A4D8F8 ; 关键算法CALL,我们进
关键算法CALL --------------
00A4D8F8 55 push ebp
00A4D8F9 8BEC mov ebp, esp
00A4D8FB 81C4 ECFEFFFF add esp, -114
00A4D901 53 push ebx
00A4D902 33D2 xor edx, edx
00A4D904 8995 2CFFFFFF mov dword ptr [ebp-D4], edx
00A4D90A 8955 F8 mov dword ptr [ebp-8], edx
00A4D90D 8955 F4 mov dword ptr [ebp-C], edx
00A4D910 8955 F0 mov dword ptr [ebp-10], edx
00A4D913 8945 FC mov dword ptr [ebp-4], eax
00A4D916 8B45 FC mov eax, dword ptr [ebp-4]
00A4D919 E8 127C9BFF call 00405530
00A4D91E 33C0 xor eax, eax
00A4D920 55 push ebp
00A4D921 68 3CDAA400 push 00A4DA3C
00A4D926 64:FF30 push dword ptr fs:[eax]
00A4D929 64:8920 mov dword ptr fs:[eax], esp
00A4D92C 33DB xor ebx, ebx
00A4D92E 8B45 FC mov eax, dword ptr [ebp-4]
00A4D931 E8 0A7A9BFF call 00405340
00A4D936 83F8 19 cmp eax, 19 ; 比较注册码长度是否为 25 位
00A4D939 0F85 D7000000 jnz 00A4DA16
00A4D93F 8B55 FC mov edx, dword ptr [ebp-4]
00A4D942 A1 B467AC00 mov eax, dword ptr [AC67B4]
00A4D947 E8 387D9BFF call 00405684 ; 注册码中是否含有 RP0
00A4D94C 48 dec eax
00A4D94D 0F85 C3000000 jnz 00A4DA16
00A4D953 8D85 2CFFFFFF lea eax, dword ptr [ebp-D4]
00A4D959 50 push eax
00A4D95A B9 0F000000 mov ecx, 0F
00A4D95F BA 01000000 mov edx, 1
00A4D964 8B45 FC mov eax, dword ptr [ebp-4]
00A4D967 E8 347C9BFF call 004055A0 ; 取注册码前15位,RP0ABCDEFGHIJKL
00A4D96C 8B85 2CFFFFFF mov eax, dword ptr [ebp-D4]
00A4D972 8D55 F8 lea edx, dword ptr [ebp-8]
00A4D975 E8 52F9FFFF call 00A4D2CC ; TIdEncoder.Encode 算法,实质是MD5,返回最后32位大小,1571902691
00A4D97A 8D45 F4 lea eax, dword ptr [ebp-C] ; TIdEncoder.Encode 是 indy 里的 ,官网在http://www.indyproject.org/
00A4D97D 50 push eax
00A4D97E B9 19000000 mov ecx, 19
00A4D983 BA 10000000 mov edx, 10
00A4D988 8B45 FC mov eax, dword ptr [ebp-4]
00A4D98B E8 107C9BFF call 004055A0 ; 取注册码后10位,1234567890
00A4D990 8D95 70FFFFFF lea edx, dword ptr [ebp-90]
00A4D996 33C0 xor eax, eax
00A4D998 E8 5BE1FFFF call 00A4BAF8
00A4D99D 8D95 30FFFFFF lea edx, dword ptr [ebp-D0]
00A4D9A3 33C0 xor eax, eax
00A4D9A5 E8 4EE1FFFF call 00A4BAF8
00A4D9AA 8D55 B0 lea edx, dword ptr [ebp-50]
00A4D9AD 33C0 xor eax, eax
00A4D9AF E8 44E1FFFF call 00A4BAF8
00A4D9B4 8D95 70FFFFFF lea edx, dword ptr [ebp-90]
00A4D9BA B8 54DAA400 mov eax, 00A4DA54 ; RSA e=17
00A4D9BF E8 80E0FFFF call 00A4BA44
00A4D9C4 8D95 30FFFFFF lea edx, dword ptr [ebp-D0]
00A4D9CA B8 60DAA400 mov eax, 00A4DA60 ; RSA n=4552764137
00A4D9CF E8 70E0FFFF call 00A4BA44
00A4D9D4 8D55 B0 lea edx, dword ptr [ebp-50]
00A4D9D7 8B45 F4 mov eax, dword ptr [ebp-C]
00A4D9DA E8 65E0FFFF call 00A4BA44 ; RSA m=123456780
00A4D9DF 8D85 ECFEFFFF lea eax, dword ptr [ebp-114]
00A4D9E5 50 push eax
00A4D9E6 8D8D 30FFFFFF lea ecx, dword ptr [ebp-D0]
00A4D9EC 8D95 70FFFFFF lea edx, dword ptr [ebp-90]
00A4D9F2 8D45 B0 lea eax, dword ptr [ebp-50]
00A4D9F5 E8 6EF9FFFF call 00A4D368 ; RSA c = m^e mod n
00A4D9FA 8D85 ECFEFFFF lea eax, dword ptr [ebp-114] ; 结果,c=2327427866
00A4DA00 8D55 F0 lea edx, dword ptr [ebp-10]
00A4DA03 E8 68DEFFFF call 00A4B870
00A4DA08 8B45 F0 mov eax, dword ptr [ebp-10] ; RSA密文,c=2327427866
00A4DA0B 8B55 F8 mov edx, dword ptr [ebp-8] ; encode结果,1571902691
00A4DA0E E8 797A9BFF call 0040548C ; c与 TIdEncoder.Encode 结果比较是否相同
00A4DA13 0F94C3 sete bl
00A4DA16 33C0 xor eax, eax
00A4DA18 5A pop edx
00A4DA19 59 pop ecx
00A4DA1A 59 pop ecx
00A4DA1B 64:8910 mov dword ptr fs:[eax], edx
00A4DA1E 68 43DAA400 push 00A4DA43
00A4DA23 8D85 2CFFFFFF lea eax, dword ptr [ebp-D4]
00A4DA29 E8 26769BFF call 00405054
00A4DA2E 8D45 F0 lea eax, dword ptr [ebp-10]
00A4DA31 BA 04000000 mov edx, 4
00A4DA36 E8 3D769BFF call 00405078
00A4DA3B C3 retn
-------------- 关键算法CALL
00A4E3D7 84C0 test al, al
00A4E3D9 0F84 09010000 je 00A4E4E8 ; 关键跳转
00A4E3DF 8D55 FC lea edx, dword ptr [ebp-4]
00A4E3E2 8B45 F8 mov eax, dword ptr [ebp-8]
00A4E3E5 E8 72FCFFFF call 00A4E05C ; 网络验证,取回数据,IDA能识别函数过程,他是用 indy 连接服务器。
00A4E3EA 8B45 FC mov eax, dword ptr [ebp-4] ; 网络验证只在注册是进行,软件重启后,不进行验证。
00A4E3ED BA 88E5A400 mov edx, 00A4E588
00A4E3F2 E8 95709BFF call 0040548C ; 是否为0
00A4E3F7 74 2D je short 00A4E426
00A4E3F9 8B45 FC mov eax, dword ptr [ebp-4]
00A4E3FC BA 94E5A400 mov edx, 00A4E594
00A4E401 E8 86709BFF call 0040548C ; 是否为3
00A4E406 74 1E je short 00A4E426
00A4E408 8B45 FC mov eax, dword ptr [ebp-4]
00A4E40B BA A0E5A400 mov edx, 00A4E5A0
00A4E410 E8 77709BFF call 0040548C ; 是否为4
00A4E415 74 0F je short 00A4E426
00A4E417 8B45 FC mov eax, dword ptr [ebp-4]
00A4E41A BA ACE5A400 mov edx, 00A4E5AC ; 是否为5
00A4E41F E8 68709BFF call 0040548C
00A4E424 75 4D jnz short 00A4E473
00A4E426 6A 30 push 30
00A4E428 8D55 E0 lea edx, dword ptr [ebp-20]
00A4E42B A1 FC87AC00 mov eax, dword ptr [AC87FC]
00A4E430 8B00 mov eax, dword ptr [eax]
00A4E432 E8 5D8CAAFF call 004F7094
00A4E437 8B45 E0 mov eax, dword ptr [ebp-20]
00A4E43A E8 01719BFF call 00405540
00A4E43F 50 push eax
00A4E440 A1 9C67AC00 mov eax, dword ptr [AC679C]
00A4E445 E8 F6709BFF call 00405540
00A4E44A 8BD0 mov edx, eax
00A4E44C A1 FC87AC00 mov eax, dword ptr [AC87FC]
00A4E451 8B00 mov eax, dword ptr [eax]
00A4E453 59 pop ecx
00A4E454 E8 B792AAFF call 004F7710
00A4E459 8D55 DC lea edx, dword ptr [ebp-24]
00A4E45C 8B45 F8 mov eax, dword ptr [ebp-8]
00A4E45F E8 30F8FFFF call 00A4DC94
00A4E464 C783 4C020000 0>mov dword ptr [ebx+24C], 2
00A4E46E E9 B0000000 jmp 00A4E523
00A4E473 8B45 FC mov eax, dword ptr [ebp-4]
00A4E476 BA B8E5A400 mov edx, 00A4E5B8
00A4E47B E8 0C709BFF call 0040548C ; 是否为2
00A4E480 75 52 jnz short 00A4E4D4
2.2,说明下 TIdEncoder.Encode 算法部分,好多层,很长,省略很多代码。
00A4D2CC 55 push ebp
00A4D2CD 8BEC mov ebp, esp
省略部分代码
00A4D308 64:8920 mov dword ptr fs:[eax], esp
00A4D30B 8D4D E8 lea ecx, dword ptr [ebp-18]
00A4D30E 8B55 FC mov edx, dword ptr [ebp-4] ; RP0ABCDEFGHIJKL
00A4D311 8B45 F8 mov eax, dword ptr [ebp-8]
00A4D314 E8 0BE9FFFF call 00A4BC24 ; InCoder.TIdEncoder.Encode(TIdEncoder;AnsiString):AnsiString;overload;
进 InCoder.TIdEncoder.Encode *********************************
00A4BC24 55 push ebp
00A4BC25 8BEC mov ebp, esp
00A4BC27 83C4 F8 add esp, -8
00A4BC2A 53 push ebx
省略部分代码
00A4BC69 8BC3 mov eax, ebx
00A4BC6B 8B18 mov ebx, dword ptr [eax]
00A4BC6D FF13 call dword ptr [ebx] ; MD5 算法
进 MD5 算法 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00A4C3DC 55 push ebp
00A4C3DD 8BEC mov ebp, esp
00A4C3DF 83C4 E0 add esp, -20
00A4C3E2 53 push ebx
00A4C3E3 56 push esi
00A4C3E4 57 push edi
00A4C3E5 33DB xor ebx, ebx
00A4C3E7 895D E4 mov dword ptr [ebp-1C], ebx
00A4C3EA 895D E0 mov dword ptr [ebp-20], ebx
00A4C3ED 894D FC mov dword ptr [ebp-4], ecx
00A4C3F0 8BF2 mov esi, edx
00A4C3F2 8BD8 mov ebx, eax
00A4C3F4 33C0 xor eax, eax
00A4C3F6 55 push ebp
00A4C3F7 68 F3C5A400 push 00A4C5F3
00A4C3FC 64:FF30 push dword ptr fs:[eax]
00A4C3FF 64:8920 mov dword ptr fs:[eax], esp
00A4C402 8BC6 mov eax, esi
00A4C404 E8 234AA2FF call 00470E2C
00A4C409 8BF8 mov edi, eax
00A4C40B 8BC6 mov eax, esi
00A4C40D 8B10 mov edx, dword ptr [eax]
00A4C40F FF12 call dword ptr [edx]
00A4C411 52 push edx
00A4C412 50 push eax
00A4C413 8BC7 mov eax, edi
00A4C415 99 cdq
00A4C416 290424 sub dword ptr [esp], eax
00A4C419 195424 04 sbb dword ptr [esp+4], edx
00A4C41D 58 pop eax
00A4C41E 5A pop edx
00A4C41F 8945 E8 mov dword ptr [ebp-18], eax
00A4C422 8955 EC mov dword ptr [ebp-14], edx
00A4C425 56 push esi
00A4C426 BE 8866AC00 mov esi, 00AC6688
00A4C42B 8D7B 04 lea edi, dword ptr [ebx+4]
00A4C42E A5 movs dword ptr es:[edi], dword ptr [esi] ; 01234567 MD5的 A B C D
00A4C42F A5 movs dword ptr es:[edi], dword ptr [esi] ; 89ABCDEF
00A4C430 A5 movs dword ptr es:[edi], dword ptr [esi] ; FEDCBA98
00A4C431 A5 movs dword ptr es:[edi], dword ptr [esi] ; 76543210
00A4C432 5E pop esi
00A4C433 EB 16 jmp short 00A4C44B
省略部分代码
00A4C5BB B9 40000000 mov ecx, 40
00A4C5C0 E8 43679BFF call 00402D08
00A4C5C5 8BC3 mov eax, ebx
00A4C5C7 8B10 mov edx, dword ptr [eax]
00A4C5C9 FF52 04 call dword ptr [edx+4] ; MD5 主体
进 MD5 主体............................
这个 CALL 长的怕人,都没用循环,省略大量代码,列出几个个关键地方。
第一轮,好长,16个CALL
00A4C6DA A1 9866AC00 mov eax, dword ptr [AC6698] ; 常数表 T 元素 D76AA478
00A4C6DF 50 push eax
00A4C6E0 6A 07 push 7
00A4C6E2 8B45 EC mov eax, dword ptr [ebp-14]
00A4C6E5 50 push eax
00A4C6E6 8B4D F0 mov ecx, dword ptr [ebp-10]
00A4C6E9 8BD6 mov edx, esi
00A4C6EB 8B45 F4 mov eax, dword ptr [ebp-C]
00A4C6EE 8B38 mov edi, dword ptr [eax]
00A4C6F0 FF57 08 call dword ptr [edi+8] ; F(X,Y,Z)=(X&Y)|((~X)&Z)
00A4C6F3 8BC8 mov ecx, eax
00A4C6F5 8BD3 mov edx, ebx
00A4C6F7 8BC6 mov eax, esi
00A4C6F9 E8 12FFFFFF call 00A4C610 ; a=b+((a+(F(b,c,d)+Mj+ti)<<<s)
第二轮
00A4C9DB FF57 0C call dword ptr [edi+C] ; G(X,Y,Z)=(X&Z)|(Y&(~Z))
00A4C9DE 8BC8 mov ecx, eax
00A4C9E0 8B55 EC mov edx, dword ptr [ebp-14]
00A4C9E3 8BC3 mov eax, ebx
00A4C9E5 E8 26FCFFFF call 00A4C610 ; a=b+((a+(G(b,c,d)+Mj+ti)<<<s)
第三轮
00A4CC70 FF57 10 call dword ptr [edi+10] ; H(X,Y,Z)=X^Y^Z
00A4CC73 8BC8 mov ecx, eax
00A4CC75 8BD3 mov edx, ebx
00A4CC77 8BC6 mov eax, esi
00A4CC79 E8 92F9FFFF call 00A4C610 ; a=b+((a+(H(b,c,d)+Mj+ti)<<<s)
第四轮
00A4CF30 FF57 14 call dword ptr [edi+14] ; I(X,Y,Z)=Y^(X|(~Z))
00A4CF33 8BC8 mov ecx, eax
00A4CF35 8BD3 mov edx, ebx
00A4CF37 8BC6 mov eax, esi
00A4CF39 E8 D2F6FFFF call 00A4C610 ; a=b+((a+(I(b,c,d)+Mj+ti)<<<s)
............................. MD5 主体 结束
00A4C5CC 8B45 FC mov eax, dword ptr [ebp-4]
00A4C5CF 8BF8 mov edi, eax
00A4C5D1 8D73 04 lea esi, dword ptr [ebx+4]
00A4C5D4 A5 movs dword ptr es:[edi], dword ptr [esi] ; 保存散列结果
00A4C5D5 A5 movs dword ptr es:[edi], dword ptr [esi]
00A4C5D6 A5 movs dword ptr es:[edi], dword ptr [esi]
00A4C5D7 A5 movs dword ptr es:[edi], dword ptr [esi]
00A4C5D8 33C0 xor eax, eax
00A4C5DA 5A pop edx
00A4C5DB 59 pop ecx
00A4C5DC 59 pop ecx
00A4C5DD 64:8910 mov dword ptr fs:[eax], edx
00A4C5E0 68 FAC5A400 push 00A4C5FA
00A4C5E5 8D45 E0 lea eax, dword ptr [ebp-20]
00A4C5E8 BA 02000000 mov edx, 2
00A4C5ED E8 868A9BFF call 00405078
00A4C5F2 C3 retn
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MD5 算法 结束
00A4BC6F 33C0 xor eax, eax
00A4BC71 5A pop edx
00A4BC72 59 pop ecx
00A4BC73 59 pop ecx
00A4BC74 64:8910 mov dword ptr fs:[eax], edx
00A4BC77 68 8CBCA400 push 00A4BC8C
00A4BC7C 8D45 F8 lea eax, dword ptr [ebp-8]
00A4BC7F E8 8C26A1FF call 0045E310
00A4BC84 C3 retn
************************************ InCoder.TIdEncoder.Encode 结束
00A4D319 8B45 F4 mov eax, dword ptr [ebp-C] ; 结果,1571902691 16进制,5DB154E3
00A4D31C 33D2 xor edx, edx ; RP0ABCDEFGHIJKL,MD5的散列结果,6815abdc1e84c43801107ffce354b15d
00A4D31E 52 push edx
00A4D31F 50 push eax
00A4D320 8BC3 mov eax, ebx
00A4D322 E8 498FA0FF call 00456270
省略部分代码
00A4D33C C3 retn
2.3 说明下网络验证部分。
网络验证,只在注册激活时进行,而且应该只是提醒,软件重启时,不进行网络验证,注册码正确的话,提示未注册框消失。
实际是 去 http://www.blumentals.net/support/keycheck.php 读取数据 。 keycheck.php 返回的数据和 0,2,3,4,5 比较。
用IE 打开 http://www.blumentals.net/support/keycheck.php 发现里面是 0
根据网络验证的几个比较发现:
返回 1:是对的,提示重启程序,其实是非 0,2,3,4,5就行
返回 2: 提示 There might be a problem with your license. Click OK for more info.并打开网页告诉你,注册码是伪造的。
返回 0,3,4,5:提示 Activation failed.Click OK for more info.并打开网页告诉你,注册码是伪造的。
用本地验证证实上面的判断:
1,可以把 hosts 文件里加 127.0.0.1 www.blumentals.net
2,用 APMServ 5.2.6 搭建服务器环境 ,在 APMServ5.2.6\www\htdocs\ 目录里创建 support\keycheck.php文件, keycheck.php里写入 0,1,2,3,4,5验证
三,注册机制作
3.1 我们回顾下,算法过程:
1,判断是否为25位
2,是否含有 RP0
3,取前15位,进行 MD5 散列, 取最后32位代表的大小, 6815abdc1e84c43801107ffce354b15d,也就是 5DB135E3。
4,取后10位,进行RSA加密,得到密文 c
5,c 和 MD5 结果最后32位代表大小 是否相同。
3.2 注册机注册思路,其实是 RSA 的注册机的制作过程:
1,随即生成注册码前15位字串,RP0XXXXXXXXXXXX ,MD5 散列得到 C
2,用 n 得到 d ,两个版本的 RSATOOL ,设置一样,竟然得到的 d 不一样,郁闷一下。
P:89669
Q:50773
N:4552764137
E:17
D:2410212545
3,注册码后10位 m =c^d mod n
4,RP0XXXXXXXXXXXX 和 m 放一起就OK了
3.3 注册机制作,只为验证是否正确,乱点别介意。
#include "stdafx.h"
#include <time.h>
#include <iostream.h>
#include <string>
#include <miracl.h>
#include"md5.h"
using namespace std;
#pragma comment (lib,"ms32.lib")
int main(int argc, char* argv[])
{
char sz_Rand[63]={"ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
char sz_rapid[16]={0};
char sz_reg[10]={0};
unsigned int sz_SN=0;
int temp=0,len=0,p=0,i=0;
big n,d,c,m;
miracl *mip=mirsys(500,16);
mip->IOBASE=16;
n=mirvar(0);
d=mirvar(0);
c=mirvar(0);
m=mirvar(0);
/// 初始化前15位 注册码
srand(int(time(0)));
for (p=0;p<15;p++)
{
sz_rapid
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!