【文章标题】: CrackMe by Skirby 算法分析
【文章作者】: petnt
【作者邮箱】: petnt@sohu.com
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
这个CrackMe我很早就down下来了,而且也发到了这个版块(就是这里),放了很久也没人对它感兴趣。经过10个多月的昼夜研究,终于有了点眉目,现拿来与大家分享一下,大虾们就不要在此浪费时间来发笑了。
这个CrackMe有颇多的anti,代码拿出来能有1斤重,所以我也懒得将他拿出来了。本着学习的目的,我的OD的anti-anti都是取消了的,你可以利用插件忽略他的存在(但他并不一定会忽略你),下面仅将它的anti做个大概地说明。
1. 在重要的算法处,他都会利用时间函数(如GetTickCount\time)进行时间差的检测。
2. 他会检查搜索窗口类名为“llydbg”和“pediy”的窗口,并且会检查每个窗口是否含有类名为“CPUASM”“CPUREG”的子窗口,如果发现,OD就废了。
3. 他会搜寻每个进程并试图发现含有如下模块的程序ollyscript.dll\ollydbg.exe\ollydump.dll\CmdBar.dll\HideDebugger.dll\IsDebug.dll\windbg.exe\dbgeng.dll\idag.exe\idag64.exe\ida64.wll,如果发现,则结束进程。
4. 他会利用FindWindow去寻找OLLYDBG\PLLYDBG\pediy06\TIdaWindow,发现则干掉他。(有一个timer专门干这个)
5. 他会用OpenProcess打开每个进程,如果打不开则检查这个文件前100000H个字节中是否含有“ollydbg”。(猜测)
6. 在进行图片码验证的时候,他会专开一个线程来测试主线程是否被暂停,超时返回则进行自残动作。
7. 试图用OutputDebugString来废掉OD。
另外,他还利用如下小伎俩来干扰我们的正常分析:
1. 重要代码都是在验证时动态读入的,这使得我们下断很麻烦,我们不得不重复修改代码来去掉anti,因为我们的修改仅在一次验证中起作用。
2. 用作anti的api都是手动载入的,并且会把载入的api地址作下小改动(如 dec)再保存,使用的时候改回去再用。这样我们无法一目了然的看清他在用那些api。
3. 上面提到的时间检测中,有时候他会故意把差值设得很大,一杯茶喝完后回来改跳转的时候,会发现你被他骗到了陷阱里。
4. 在算法中夹杂一些无用运算,考验我们的忍耐力。
这些足以烦的人发疯的东西是对我们的意志的一个考验,当然我们也有对付他的利器,那就是脚本。附件里有我准备好的脚本,虽然我被他蹂躏了,但你可以拿脚本去蹂躏他。
好了,下面我们来看看算法吧。
激活码部分
100014F0 55 push ebp
100014F1 BA 0C000000 mov edx, 0C
100014F6 89E5 mov ebp, esp
100014F8 57 push edi
100014F9 FC cld
100014FA 31C0 xor eax, eax
100014FC 56 push esi
100014FD 89D1 mov ecx, edx
100014FF 53 push ebx
10001500 81EC EC010000 sub esp, 1EC
10001506 8D7D A8 lea edi, dword ptr [ebp-58]
10001509 F3:AB rep stos dword ptr es:[edi]
1000150B FF0D 40610010 dec dword ptr [10006140]
10001511 89D1 mov ecx, edx
10001513 8B15 00610010 mov edx, dword ptr [10006100]
10001519 66:C707 0000 mov word ptr [edi], 0
1000151E 8DB5 68FFFFFF lea esi, dword ptr [ebp-98]
10001524 31DB xor ebx, ebx
10001526 C647 02 00 mov byte ptr [edi+2], 0
1000152A D9EE fldz
1000152C 89F7 mov edi, esi
1000152E F3:AB rep stos dword ptr es:[edi]
10001530 66:C707 0000 mov word ptr [edi], 0
10001535 4A dec edx
10001536 C647 02 00 mov byte ptr [edi+2], 0
1000153A 8915 00610010 mov dword ptr [10006100], edx
10001540 D99D 48FEFFFF fstp dword ptr [ebp-1B8]
10001546 EB 06 jmp short 1000154E
10001548 8B15 00610010 mov edx, dword ptr [10006100]
1000154E 8D83 204E0000 lea eax, dword ptr [ebx+4E20]
10001554 43 inc ebx
10001555 894424 04 mov dword ptr [esp+4], eax
10001559 8B45 08 mov eax, dword ptr [ebp+8]
1000155C 890424 mov dword ptr [esp], eax
1000155F FFD2 call edx ; USER32.GetDlgItem
10001561 31D2 xor edx, edx
10001563 83EC 08 sub esp, 8
10001566 895424 04 mov dword ptr [esp+4], edx
1000156A 890424 mov dword ptr [esp], eax
1000156D FF15 40610010 call dword ptr [10006140] ; USER32.EnableWindow
10001573 83EC 08 sub esp, 8
10001576 83FB 0F cmp ebx, 0F
10001579 ^ 76 CD jbe short 10001548 ; 利用循环灰化图标按钮
10001589 FF15 40610010 call dword ptr [10006140] ; USER32.EnableWindow 灰化验证按钮
1000158F FF05 40610010 inc dword ptr [10006140] ; 传说中的小伎俩 下略
10001595 FF05 00610010 inc dword ptr [10006100]
1000159B 83EC 08 sub esp, 8
1000159E 89F6 mov esi, esi
100015A0 B0 30 mov al, 30
100015A2 88842B 68FFFFFF mov byte ptr [ebx+ebp-98], al
100015A9 43 inc ebx
100015AA 83FB 31 cmp ebx, 31
100015AF 8B15 20610010 mov edx, dword ptr [10006120]
100015B5 B8 0D000000 mov eax, 0D
100015BA 8D4D A8 lea ecx, dword ptr [ebp-58]
100015BD 894424 04 mov dword ptr [esp+4], eax
100015C1 8B45 0C mov eax, dword ptr [ebp+C]
100015C4 8D9D 58FEFFFF lea ebx, dword ptr [ebp-1A8]
100015CA 894C24 0C mov dword ptr [esp+C], ecx
100015CE 4A dec edx
100015CF B9 32000000 mov ecx, 32
100015D4 8915 20610010 mov dword ptr [10006120], edx
100015DA 894C24 08 mov dword ptr [esp+8], ecx
100015DE 890424 mov dword ptr [esp], eax
100015E1 FFD2 call edx ; USER32.SendMessageA 获取用户名
100015E3 83EC 10 sub esp, 10
100015E6 89C7 mov edi, eax
100015E8 B8 32000000 mov eax, 32
100015ED 894424 08 mov dword ptr [esp+8], eax
100015F1 B8 0D000000 mov eax, 0D
100015F6 894424 04 mov dword ptr [esp+4], eax
100015FA 8B45 10 mov eax, dword ptr [ebp+10]
100015FD 897424 0C mov dword ptr [esp+C], esi
10001601 890424 mov dword ptr [esp], eax
10001604 FF15 20610010 call dword ptr [10006120] ; USER32.SendMessageA 获取激活码
1000160A FF05 20610010 inc dword ptr [10006120]
10001610 83EC 10 sub esp, 10
10001613 897424 04 mov dword ptr [esp+4], esi
10001617 891C24 mov dword ptr [esp], ebx
1000161A E8 611B0000 call 10003180 ; jmp 到 msvcrt.strcpy 转移
1000161F 891C24 mov dword ptr [esp], ebx
10001622 B8 03000000 mov eax, 3
10001627 894424 08 mov dword ptr [esp+8], eax
1000162B B8 2D000000 mov eax, 2D
10001630 894424 04 mov dword ptr [esp+4], eax
10001634 E8 97FBFFFF call 100011D0 ; 分三段取注册码并保存,"-"为分段标志
10001639 83FF 05 cmp edi, 5
1000163C 89C6 mov esi, eax
1000163E 7E 1F jle short 1000165F ; 用户名小于等于5则跳走直接返回
10001640 31C0 xor eax, eax
10001642 31DB xor ebx, ebx
10001644 31C9 xor ecx, ecx
10001646 8985 44FEFFFF mov dword ptr [ebp-1BC], eax
1000164C 8B06 mov eax, dword ptr [esi] ; 激活码第一部分
1000164E 899D 40FEFFFF mov dword ptr [ebp-1C0], ebx
10001654 898D 3CFEFFFF mov dword ptr [ebp-1C4], ecx
1000165A 8038 00 cmp byte ptr [eax], 0 ; 为空?
1000165D 75 08 jnz short 10001667 ; 不空则跳向计算验证处
1000165F 8D65 F4 lea esp, dword ptr [ebp-C]
10001662 5B pop ebx
10001663 5E pop esi
10001664 5F pop edi
10001665 5D pop ebp
10001666 C3 retn
10001667 E8 34FDFFFF call 100013A0 ; 获取系统时间
1000166C 8985 38FEFFFF mov dword ptr [ebp-1C8], eax
10001672 31DB xor ebx, ebx ; 算法1开始
10001674 8B0E mov ecx, dword ptr [esi]
10001676 EB 29 jmp short 100016A1
10001678 8B0E mov ecx, dword ptr [esi]
1000167A 0FBE040B movsx eax, byte ptr [ebx+ecx]
1000167E 43 inc ebx
1000167F 89C2 mov edx, eax
10001681 81F2 1E7C0000 xor edx, 7C1E
10001687 35 8FA20000 xor eax, 0A28F
1000168C 0195 44FEFFFF add dword ptr [ebp-1BC], edx
10001692 8B95 44FEFFFF mov edx, dword ptr [ebp-1BC]
10001698 0FAFC2 imul eax, edx
1000169B 8985 44FEFFFF mov dword ptr [ebp-1BC], eax
100016A1 890C24 mov dword ptr [esp], ecx
100016A4 E8 B7FBFFFF call 10001260 ; 获取第一部分长度
100016A9 39D8 cmp eax, ebx
100016AB ^ 77 CB ja short 10001678 ; 算法1结束
100016AD 8B85 38FEFFFF mov eax, dword ptr [ebp-1C8]
100016B3 890424 mov dword ptr [esp], eax
100016B6 E8 15FDFFFF call 100013D0 ; 获取与上次的时间差(秒)
100016BB 3D D0070000 cmp eax, 7D0
100016C0 0F87 A1010000 ja 10001867 ; 大于2000秒则退出,去喝茶吧!
100016C6 8B46 04 mov eax, dword ptr [esi+4] ; 第二部分
100016C9 8038 00 cmp byte ptr [eax], 0
100016CC ^ 74 91 je short 1000165F ; 为空则返回
100016CE E8 ADFBFFFF call 10001280 ; GetTickCount
100016D3 8985 34FEFFFF mov dword ptr [ebp-1CC], eax
100016D9 85FF test edi, edi ; 用户名长度 ,算法2开始处
100016DB BB 01000000 mov ebx, 1
100016E0 7E 36 jle short 10001718
100016E2 8B85 3CFEFFFF mov eax, dword ptr [ebp-1C4]
100016E8 8D0C3B lea ecx, dword ptr [ebx+edi]
100016EB 31D2 xor edx, edx
100016ED 0FAFC8 imul ecx, eax
100016F0 8D43 FF lea eax, dword ptr [ebx-1]
100016F3 F7F7 div edi
100016F5 0FBE442A A8 movsx eax, byte ptr [edx+ebp-58]
100016FA 0FAFC3 imul eax, ebx
100016FD 43 inc ebx
100016FE 83FB 32 cmp ebx, 32
10001701 0F96C2 setbe dl
10001704 8D0401 lea eax, dword ptr [ecx+eax]
10001707 8985 3CFEFFFF mov dword ptr [ebp-1C4], eax
1000170D 31C0 xor eax, eax
1000170F 85FF test edi, edi
10001711 0F9FC0 setg al
10001714 85C2 test edx, eax
10001716 ^ 75 CA jnz short 100016E2 ; 算法2结束处
10001718 8B8D 34FEFFFF mov ecx, dword ptr [ebp-1CC]
1000171E 890C24 mov dword ptr [esp], ecx
10001721 E8 7AFBFFFF call 100012A0 ; GetTickCount并计算与上次差值
10001726 3D E8030000 cmp eax, 3E8
1000172B 0F87 36010000 ja 10001867 ; 小心,眨下眼都能被发现
10001731 E8 8AFBFFFF call 100012C0 ; GetSystemTime
10001736 8985 30FEFFFF mov dword ptr [ebp-1D0], eax
1000173C 31C9 xor ecx, ecx ; 算法3开始处
1000173E 31DB xor ebx, ebx
10001740 898D 4CFEFFFF mov dword ptr [ebp-1B4], ecx
10001746 8B7E 04 mov edi, dword ptr [esi+4]
10001749 EB 7D jmp short 100017C8
1000174B 8B85 24FEFFFF mov eax, dword ptr [ebp-1DC]
10001751 83C0 11 add eax, 11
10001754 31C8 xor eax, ecx
10001756 0185 40FEFFFF add dword ptr [ebp-1C0], eax
1000175C 0FBE441F 01 movsx eax, byte ptr [edi+ebx+1]
10001761 66:0FBED0 movsx dx, al
10001765 66:52 push dx
10001767 8B95 4CFEFFFF mov edx, dword ptr [ebp-1B4]
1000176D DF0424 fild word ptr [esp]
10001770 83C4 02 add esp, 2
10001773 0FAFC2 imul eax, edx
10001776 D885 48FEFFFF fadd dword ptr [ebp-1B8]
1000177C 31D2 xor edx, edx
1000177E 52 push edx
1000177F 50 push eax
10001780 D99D 48FEFFFF fstp dword ptr [ebp-1B8]
10001786 DF2C24 fild qword ptr [esp]
10001789 83C4 08 add esp, 8
1000178C D88D 48FEFFFF fmul dword ptr [ebp-1B8]
10001792 D99D 48FEFFFF fstp dword ptr [ebp-1B8]
10001798 D985 48FEFFFF fld dword ptr [ebp-1B8]
1000179E D905 10500010 fld dword ptr [10005010]
100017A4 D9C9 fxch st(1)
100017A6 DDE1 fucom st(1)
100017A8 DFE0 fstsw ax
100017AA DDD9 fstp st(1)
100017AC 9E sahf
100017AD 0F86 FB000000 jbe 100018AE
100017B3 D835 14500010 fdiv dword ptr [10005014]
100017B9 D99D 48FEFFFF fstp dword ptr [ebp-1B8]
100017BF FF85 4CFEFFFF inc dword ptr [ebp-1B4]
100017C5 83C3 02 add ebx, 2
100017C8 893C24 mov dword ptr [esp], edi
100017CB E8 90FAFFFF call 10001260 ; 第二部分长度
100017D0 39D8 cmp eax, ebx
100017D2 76 5C jbe short 10001830
100017D4 8B8D 40FEFFFF mov ecx, dword ptr [ebp-1C0]
100017DA 8B7E 04 mov edi, dword ptr [esi+4]
100017DD 8D0489 lea eax, dword ptr [ecx+ecx*4]
100017E0 01C0 add eax, eax
100017E2 8985 40FEFFFF mov dword ptr [ebp-1C0], eax
100017E8 0FBE043B movsx eax, byte ptr [ebx+edi]
100017EC F685 4CFEFFFF 0>test byte ptr [ebp-1B4], 1
100017F3 8985 24FEFFFF mov dword ptr [ebp-1DC], eax
100017F9 0FBE4C1F 01 movsx ecx, byte ptr [edi+ebx+1]
100017FE ^ 0F84 47FFFFFF je 1000174B
10001804 8B85 4CFEFFFF mov eax, dword ptr [ebp-1B4]
1000180A BA ABAAAAAA mov edx, AAAAAAAB
1000180F F7E2 mul edx
10001811 D1EA shr edx, 1
10001813 8D1452 lea edx, dword ptr [edx+edx*2]
10001816 3995 4CFEFFFF cmp dword ptr [ebp-1B4], edx
1000181C 0F85 93000000 jnz 100018B5
10001822 8B85 24FEFFFF mov eax, dword ptr [ebp-1DC]
10001828 83C0 31 add eax, 31
1000182B ^ E9 24FFFFFF jmp 10001754 ; 算法3结束处
10001830 8B85 30FEFFFF mov eax, dword ptr [ebp-1D0]
10001836 890424 mov dword ptr [esp], eax
10001839 E8 F2FAFFFF call 10001330 ; GetSystemTime并计算与上次差值
1000183E 3D B80B0000 cmp eax, 0BB8
10001843 77 22 ja short 10001867 ; 3秒,喝口水
10001845 E8 36FAFFFF call 10001280 ; GetTickCount
1000184A 89C7 mov edi, eax
1000184C 8B46 08 mov eax, dword ptr [esi+8] ; 激活码第三部分
1000184F 8038 00 cmp byte ptr [eax], 0
10001852 75 78 jnz short 100018CC ; 为空?
10001854 893C24 mov dword ptr [esp], edi
10001857 E8 44FAFFFF call 100012A0 ; GetTickCount并计算与上次差值
1000185C 3D B80B0000 cmp eax, 0BB8
10001861 ^ 0F86 F8FDFFFF jbe 1000165F ; 大于3秒则顺序执行退出程序
10001867 A1 B0610010 mov eax, dword ptr [100061B0]
1000186C 31C9 xor ecx, ecx
1000186E 8B55 08 mov edx, dword ptr [ebp+8]
10001871 894C24 04 mov dword ptr [esp+4], ecx
10001875 48 dec eax
10001876 891424 mov dword ptr [esp], edx
10001879 A3 B0610010 mov dword ptr [100061B0], eax
1000187E FFD0 call eax ; USER32.EndDialog
10001880 FF05 B0610010 inc dword ptr [100061B0]
10001886 A1 F0600010 mov eax, dword ptr [100060F0]
1000188B 83EC 08 sub esp, 8
1000188E C70424 00000000 mov dword ptr [esp], 0
10001895 83E8 02 sub eax, 2
10001898 A3 F0600010 mov dword ptr [100060F0], eax
1000189D FFD0 call eax ; Kernel32.ExitProcess
1000189F 8305 F0600010 0>add dword ptr [100060F0], 2
100018A6 83EC 04 sub esp, 4
100018A9 ^ E9 B1FDFFFF jmp 1000165F
100018AE DDD8 fstp st
100018B0 ^ E9 0AFFFFFF jmp 100017BF
100018B5 318D 24FEFFFF xor dword ptr [ebp-1DC], ecx
100018BB 8B95 24FEFFFF mov edx, dword ptr [ebp-1DC]
100018C1 0195 40FEFFFF add dword ptr [ebp-1C0], edx
100018C7 ^ E9 90FEFFFF jmp 1000175C
100018CC 8D9D 54FEFFFF lea ebx, dword ptr [ebp-1AC]
100018D2 895C24 04 mov dword ptr [esp+4], ebx
100018D6 8B46 08 mov eax, dword ptr [esi+8]
100018D9 890424 mov dword ptr [esp], eax ; 第三部分 算法4开始
100018DC E8 AF180000 call 10003190 ; jmp 到 msvcrt.strtod
100018E1 DDD8 fstp st
100018E3 895C24 04 mov dword ptr [esp+4], ebx
100018E7 B8 0A000000 mov eax, 0A
100018EC 894424 08 mov dword ptr [esp+8], eax
100018F0 8B46 08 mov eax, dword ptr [esi+8]
100018F3 890424 mov dword ptr [esp], eax
100018F6 E8 75180000 call 10003170 ; jmp 到 msvcrt.strtol
100018FB 50 push eax
100018FC 8B8D 40FEFFFF mov ecx, dword ptr [ebp-1C0]
10001902 DB0424 fild dword ptr [esp] ; 算法4结束
10001905 83C4 04 add esp, 4
10001908 81BD 44FEFFFF 3>cmp dword ptr [ebp-1BC], E72DFF36 ; 比较算法1结果
10001912 0F94C2 sete dl
10001915 31C0 xor eax, eax
10001917 398D 3CFEFFFF cmp dword ptr [ebp-1C4], ecx ; 比较算法2与算法3的结果
1000191D 0F94C0 sete al
10001920 85C2 test edx, eax
10001922 0F84 8E000000 je 100019B6 ; 两者都相符比较算法4结果
10001928 D985 48FEFFFF fld dword ptr [ebp-1B8] ; 与算法3的第二输出结果
1000192E D80D 18500010 fmul dword ptr [10005018]
10001934 D905 1C500010 fld dword ptr [1000501C]
1000193A D9C1 fld st(1)
1000193C D8E1 fsub st, st(1)
1000193E D9CB fxch st(3)
10001940 DDE3 fucom st(3)
10001942 DFE0 fstsw ax
10001944 DDDB fstp st(3)
10001946 9E sahf
10001947 72 69 jb short 100019B2
10001949 DEC1 faddp st(1), st
1000194B DAE9 fucompp
1000194D DFE0 fstsw ax
1000194F 9E sahf
10001950 ^ 0F82 FEFEFFFF jb 10001854
10001956 8B85 54FEFFFF mov eax, dword ptr [ebp-1AC] ; 第三部分是否是激活码的
1000195C 8038 00 cmp byte ptr [eax], 0 ; 最后一部分?
1000195F ^ 0F85 EFFEFFFF jnz 10001854 ; 不是则跳走根据时间差来结束或返回
10001965 FF0D 40610010 dec dword ptr [10006140]
1000196B 31DB xor ebx, ebx
1000196D 8B15 00610010 mov edx, dword ptr [10006100]
10001973 4A dec edx
10001974 8915 00610010 mov dword ptr [10006100], edx
1000197A 8B4D 08 mov ecx, dword ptr [ebp+8]
1000197D 8D83 204E0000 lea eax, dword ptr [ebx+4E20]
10001983 BE 01000000 mov esi, 1
10001988 894424 04 mov dword ptr [esp+4], eax
1000198C 43 inc ebx
1000198D 890C24 mov dword ptr [esp], ecx
10001990 FFD2 call edx ; USER32.GetDlgItem
10001992 83EC 08 sub esp, 8
10001995 897424 04 mov dword ptr [esp+4], esi
10001999 890424 mov dword ptr [esp], eax
1000199C FF15 40610010 call dword ptr [10006140] ; USER32.EnableWindow
100019A2 83EC 08 sub esp, 8
100019A5 83FB 0F cmp ebx, 0F ; 循环激活图标按钮
100019A8 77 13 ja short 100019BD
100019AA 8B15 00610010 mov edx, dword ptr [10006100] ; USER32.GetDlgItem
100019B0 ^ EB C8 jmp short 1000197A
100019B2 DDD8 fstp st
100019B4 DDD8 fstp st
100019B6 DDD8 fstp st
100019B8 ^ E9 97FEFFFF jmp 10001854
100019BD 8B45 14 mov eax, dword ptr [ebp+14]
100019C0 BB 01000000 mov ebx, 1
100019C5 895C24 04 mov dword ptr [esp+4], ebx
100019C9 890424 mov dword ptr [esp], eax
100019CC FF15 40610010 call dword ptr [10006140] ; USER32.EnableWindow
100019D2 FF05 40610010 inc dword ptr [10006140] ; 激活验证按钮
100019D8 FF05 00610010 inc dword ptr [10006100]
100019DE 83EC 08 sub esp, 8
100019E1 ^ E9 6EFEFFFF jmp 10001854 ; 根据时间差来结束或返回
算法1:
S=激活码第一部分、 S[i]=第I位的ASCII值、 L=第一部分长度、 SUM1=输出结果
for(int i = 0; i < L; i++)
{
SUM1 = ( SUM1 + (S[i] Xor 7c1eh)) * (S[i] Xor a28fh);
}
算法2:
S=用户名、 S[i]=第I位的ASCII值、 L=用户名长度、 SUM2=输出结果
for(int i = 1; i <= 32h; i++)
{
SUM2 = SUM2 * (i + L) + S[(i - 1) % L] * i
}
算法3:
S=激活码第二部分、 S[i]=第I位的ASCII值、 L=第二部分长度、 SUM3.1=输出结果1、SUM3.2=输出结果2、C=计数器、M=中间数
C=0
for(int i = 0; i < L; i+2)
{
SUM3.1 =SUM3.1*10;
M = 0;
if(C % 2 == 0)
{
M = 11H;
}
else
{
if(C % 3 == 0)
M = 031h;
}
SUM3.1=SUM3.1+ (S[i] + M) Xor S[i + 1];
SUM3.2=(SUM3.2 + S[i + 1]) * S[i + 1] * C;
if(SUM3.2> 1048575.0)
{
SUM3.2 = SUM3.2/65535.0;
}
C++;
}
算法4:
很简单,将第三部分字符转换成十进制,乘10取整。(SUM4)
成功激活条件:
一、SUM1=0E72DFF36H
二、SUM2=SUM3.1
三、SUM4=SUM3.2
一、分析了半天没发现逆算法,不过穷举非常简单,符合条件的很多,站起来活动活动手脚的功夫就可以看见结果,这里不多说了,给出一组纯数字的:2288433191
二、注册机中用户名已知,所以SUM2为已知数,但如何逆推第二部分激活码确实令我头疼了一段时间。仔细分析算法,我们可能还可以找到一些突破口,首先我们简化一下算法:
M=M*10+N
如果,我们把SUM2转换成十进制,我们可以根据这个十进制数的个位,来推测S[i] + M) Xor S[i + 1]中的结果中的1位,从而穷举2位来确定最后两位,进而一步一步向前推进。再者,我们发现N这个数不会很大,从而可以看出影响最后结果大小的关键在于字符串的前几位,也就是说,第二部分激活码的前几个字符对最后结果的影响最大,越靠后越次之,在长度很大的情况下,这种规律就会越发的明显。其实我们可以粗略的估计下第二部分激活码的长度,经观察发现一般情况下SUM2会在10000000H与0FFFFFFFFH之间,由此可以估计长度应该在15到20之间(可以通过除10估计),所以我们可以从这个规律下手来穷举他。
第一种方法我没试验过,第二种思路确实能穷举处大部分用户名的激活码。下面是这种方法的大体思路:
假设SUM2=ABCDEF12H,激活码长度为20
从前向后穷举字符串,如果发现结果符合ABXXXXXXH形式(如果发现不了,则增加字符串长度再进行穷举),则固定前几位,向后穷举,继续发现符合ABCXXXXXH形式的字符串,依次类推,直至发现等于ABCDEF12H的字符串。附件中给出了这种形式的注册机。
三、不多说了,天下人都知道怎么算。
图标码验证部分很简单,主要是anti多,大部分我都在脚本里标注了。算法也不复杂,把代码抄一遍就能写注册机了,在这里就不再浪费篇幅了。
用户名:0petnt0
激活码:2288433191-YTCBMBEABBBDAAAAJPIP-1064263
图标码:13F38FF5(从左至右,从上至下分别对应了16进制的0—F)
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2008年11月07日 18:53:01
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)