aCaFeeL's CrackMe V5(前传版)算法分析 + 注册机(附件)
【破文标题】破解aCaFeeL's CrackMe V5(前传版)【破文作者】vecri
【作者邮箱】[email protected]
【作者主页】
【破解工具】OD
【破解平台】Windows XP
【软件名称】aCaFeeL's CrackMe V5(前传版) ->
【软件大小】
【原版下载】https://www.chinapyg.com/viewthread.php?tid=22489&extra=page%3D1
【保护方式】反调试+序列号
【软件简介】
【破解声明】菜鸟一个..偶有所得~
------------------------------------------------------------------------
【破解过程】一:首先是这个CrackMe的反调试分析: 包括窗口查找. 和 CRC
在打开这个CrackMe后, 再开OD, OD会自动关闭, 由此可以知道是WM_TIMER搞的鬼, bpx *看看有什么可疑的函数, 没有看到CreateToolHelpSnap32(),ProcessFirst32()以及ProcessNext32(), 就找到一个
FindWindow, 试试是不是这个.
下断: bp FindWindow
中断下, 返回用户领空, 看代码:
0040EAF2|.50 PUSH EAX ; |Class = "OllyDBG"
0040EAF3|.E8 8C57FFFF CALL <JMP.&user32.FindWindowA> ; \FindWindowA
0040EAF8|.8BF0 MOV ESI,EAX
0040EAFA|.85F6 TEST ESI,ESI
0040EAFC 74 2A JE SHORT keygenme.0040EB28
0040EAFE|>BB E01E0000 /MOV EBX,1EE0
0040EB03|>6A 00 |/PUSH 0 ; /lParam = 0
0040EB05|.6A 00 ||PUSH 0 ; |wParam = 0
0040EB07|.6A 10 ||PUSH 10 ; |Message = WM_CLOSE
0040EB09|.56 ||PUSH ESI ; |hWnd
0040EB0A|.E8 9558FFFF ||CALL <JMP.&user32.SendMessageA> ; \SendMessageA
0040EB0F|.4B ||DEC EBX
0040EB10|.^ 75 F1 |\JNZ SHORT keygenme.0040EB03
如果是窗口类是OllyDBG, 就发送WM_CLOSE消息, 于是把上面的判断JE SHORT keygenme.0040EB28
改成JNE SHORT keygenme.0040EB28, 另存为其他文件. 一运行发现文件被修改, 基本上判断是CRC校验的问题:
重新载入, 下断: CreateFileA, 断下, 返回用户领空:
0040EA60|.E8 4F3AFFFF CALL keygenme.004024B4
0040EA65|.837D F8 00 CMP DWORD PTR SS:,0
0040EA69|.74 04 JE SHORT keygenme.0040EA6F ;跳转就完蛋
0040EA6B|.33DB XOR EBX,EBX
0040EA6D|.EB 02 JMP SHORT keygenme.0040EA71
0040EA6F|>B3 01 MOV BL,1
0040EA71|>33C0 XOR EAX,EAX
将上面的跳转取反, JE改为JNE, 然后把FindWindow处的跳转也改掉, 另存后运行, 通过~~~
可惜现在Validate按键不能按, 还是灰色的..接下来分析.
二:将Validate改为正常
bp CreateWindowExA, 断下, 看看右下角是哪个窗口, 到Validate的时候看看:
00406D5D .8D4424 70 LEA EAX,DWORD PTR SS:
00406D61 .50 PUSH EAX ; /pWndClass
00406D62 .E8 1DD6FFFF CALL <JMP.&user32.RegisterClassA> ; \RegisterClassA
00406D67 .85C0 TEST EAX,EAX
00406D69 .0F84 81000000 JE keygenme.00406DF0
00406D6F >891D 14554100 MOV DWORD PTR DS:,EBX ; |
00406D75 .E8 B2D4FFFF CALL <JMP.&user32.CreateWindowExA> ; \CreateWindowExA
此时右下角是:
0012FEE8 00010000|ExtStyle = WS_EX_CONTROLPARENT
0012FEEC 0012FF18|Class = "obj_BUTTON"
0012FEF0 00D91FA8|WindowName = "&Validate"
0012FEF4 4E00400B|Style = WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_DISABLED|400B
0012FEF8 00000063|X = 63 (99.)
0012FEFC 000000CE|Y = CE (206.)
0012FF00 00000057|Width = 57 (87.)
0012FF04 00000014|Height = 14 (20.)
0012FF08 002A0236|hParent = 002A0236 ('keygenme',class='obj_Form')
将4E00400B改成正常的4600400B, 则按钮可按, 可是还是灰色~~真要命~
bpCallWindowProcA, bp SetColor, 右下角堆栈里注意看对应的消息, 在发给Validate按钮WM_PAINT后, 仔细看后面的SetColor调用,
都是为这个Button绘图的, 可以看到第二个SetColor参数为Gray, 所以我们只要写些补丁代码, 让颜色变为(8, 0, 0)就可以了
下面我把这两个地方的补丁代码给大家看一下, 补丁后的文件会传到附件里
在文件后的空白出添加两段补丁代码:
//第1段补丁代码
00410CB0 > \6A 08 PUSH 8 ;//这里是按钮上文字的颜色, (8, 0, 0)
00410CB2 .8B45 F8 MOV EAX,DWORD PTR SS: ;//原来的两句代码
00410CB5 .8B40 18 MOV EAX,DWORD PTR DS:
00410CB8 .^ E9 5157FFFF JMP keygenme.0040640E //跳回原来的地方执行
00410CBD 90 NOP
00410CBE 00 DB 00
00410CBF 00 DB 00
//第2段补丁代码
00410CC0 >817B 34 0B400>CMP DWORD PTR DS:,4E00400B //如果按钮风格为4E00400B(其中包含WS_DISABLED)
00410CC7 .75 07 JNZ SHORT keygenme.00410CD0
00410CC9 .C743 34 0B400>MOV DWORD PTR DS:,4600400B //就改为4600400B(去掉了WS_DISABLED标志)
00410CD0 >FF73 34 PUSH DWORD PTR DS: //原来的两句代码
00410CD3 .FFB3 89050000 PUSH DWORD PTR DS:
00410CD9 .^ E9 FB5FFFFF JMP keygenme.00406CD9 //跳回原处执行
原文代码修改如下, 跳到补丁代码出执行:
00406407 . /E9 A4A80000 JMP keygenme.00410CB0 //跳到补丁处
0040640C |90 NOP
0040640D |90 NOP
0040640E > |50 PUSH EAX ; |hDC
0040640F . |E8 D8DDFFFF CALL <JMP.&gdi32.SetTextColor> ; \SetTextColor
和
00406CCE > \52 PUSH EDX
00406CCF .50 PUSH EAX
00406CD0 .E9 EB9F0000 JMP keygenme.00410CC0 //跳到补丁处
00406CD5 90 NOP
00406CD6 90 NOP
00406CD7 90 NOP
00406CD8 90 NOP
三: 注册算法分析, 这里才是主题~
用RUN跟踪可以得到Validate按钮响应代码在40E7C4处(RUN跟踪如果不会,上看雪论坛去.~)
0040E7C4/.55 PUSH EBP
0040E7C5|.8BEC MOV EBP,ESP
0040E7C7|.B9 07000000 MOV ECX,7
0040E7CC|>6A 00 /PUSH 0
0040E7CE|.6A 00 |PUSH 0
0040E7D0|.49 |DEC ECX
0040E7D1|.^ 75 F9 \JNZ SHORT keygenme.0040E7CC
0040E7D3|.51 PUSH ECX
0040E7D4|.53 PUSH EBX
0040E7D5|.56 PUSH ESI
0040E7D6|.57 PUSH EDI
0040E7D7|.8BD8 MOV EBX,EAX
0040E7D9|.33C0 XOR EAX,EAX
0040E7DB|.55 PUSH EBP
0040E7DC|.68 88E94000 PUSH keygenme.0040E988
0040E7E1|.64:FF30 PUSH DWORD PTR FS:
0040E7E4|.64:8920 MOV DWORD PTR FS:,ESP
0040E7E7|.8B43 3C MOV EAX,DWORD PTR DS:
0040E7EA|.B2 01 MOV DL,1
0040E7EC|.E8 DBB4FFFF CALL keygenme.00409CCC
0040E7F1|.8D55 F4 LEA EDX,DWORD PTR SS:
0040E7F4|.8B43 3C MOV EAX,DWORD PTR DS:
0040E7F7|.E8 E48AFFFF CALL keygenme.004072E0 ;获取注册码
0040E7FC|.8B45 F4 MOV EAX,DWORD PTR SS:
0040E7FF|.E8 4848FFFF CALL keygenme.0040304C ;取注册码长度.
0040E804|.83F8 35 CMP EAX,35
0040E807|.0F85 56010000 JNZ keygenme.0040E963 ;长度必须等于35(10进制53)
0040E80D|.8D45 F8 LEA EAX,DWORD PTR SS:
0040E810|.50 PUSH EAX
0040E811|.8D55 F0 LEA EDX,DWORD PTR SS:
0040E814|.8B43 3C MOV EAX,DWORD PTR DS:
0040E817|.E8 C48AFFFF CALL keygenme.004072E0 ;再次获取注册码
0040E81C|.8B45 F0 MOV EAX,DWORD PTR SS:
0040E81F|.B9 08000000 MOV ECX,8
0040E824|.BA 2E000000 MOV EDX,2E
0040E829|.E8 264AFFFF CALL keygenme.00403254 ;获取注册码最后几位
0040E82E|.8D45 EC LEA EAX,DWORD PTR SS: ;参数为最后8位注册码的地址
0040E831|.E8 6AFAFFFF CALL keygenme.0040E2A0 ;获取ini文件code字段并进行xor
0040E836|.837D EC 00 CMP DWORD PTR SS:,0
0040E83A|.0F84 23010000 JE keygenme.0040E963
0040E840|.8D55 E8 LEA EDX,DWORD PTR SS:
0040E843|.8B43 38 MOV EAX,DWORD PTR DS:
0040E846|.E8 958AFFFF CALL keygenme.004072E0 ;获取用户名
0040E84B|.837D E8 00 CMP DWORD PTR SS:,0
0040E84F|.0F84 0E010000 JE keygenme.0040E963 ;比较用户名是否为空
0040E855|.8D45 E4 LEA EAX,DWORD PTR SS:
0040E858|.50 PUSH EAX
0040E859|.8D55 DC LEA EDX,DWORD PTR SS:
0040E85C|.8B43 38 MOV EAX,DWORD PTR DS:
0040E85F|.E8 7C8AFFFF CALL keygenme.004072E0 ;再次获取用户名
0040E864|.8B45 DC MOV EAX,DWORD PTR SS:
0040E867|.8D55 E0 LEA EDX,DWORD PTR SS:
0040E86A|.E8 85F3FFFF CALL keygenme.0040DBF4 ;对用户名进行处理..跟进
0040E86F|.8B45 E0 MOV EAX,DWORD PTR SS: ;处理结果
0040E872|.B9 08000000 MOV ECX,8
0040E877|.BA 09000000 MOV EDX,9
0040E87C|.E8 D349FFFF CALL keygenme.00403254 ;从第9为开始,取8个字母, 形成一子串1
0040E881|.8D45 E4 LEA EAX,DWORD PTR SS:
0040E884|.50 PUSH EAX ;刚取的子串1
0040E885|.8D45 D8 LEA EAX,DWORD PTR SS:
0040E888|.50 PUSH EAX
0040E889|.8D55 D4 LEA EDX,DWORD PTR SS:
0040E88C|.8B43 3C MOV EAX,DWORD PTR DS:
0040E88F|.E8 4C8AFFFF CALL keygenme.004072E0 ;再取注册码
0040E894|.8B45 D4 MOV EAX,DWORD PTR SS:
0040E897|.B9 01000000 MOV ECX,1
0040E89C|.BA 09000000 MOV EDX,9
0040E8A1|.E8 AE49FFFF CALL keygenme.00403254 ;取注册码的第9位
0040E8A6|.8B55 D8 MOV EDX,DWORD PTR SS: ;EDX放第9位的地址
0040E8A9|.58 POP EAX
0040E8AA|.E8 A547FFFF CALL keygenme.00403054 ;刚取的子串1连接上第9位
0040E8AF|.8B45 E4 MOV EAX,DWORD PTR SS: ;连接后的子串1
0040E8B2|.50 PUSH EAX
0040E8B3|.8D45 D0 LEA EAX,DWORD PTR SS:
0040E8B6|.50 PUSH EAX
0040E8B7|.8D55 CC LEA EDX,DWORD PTR SS:
0040E8BA|.8B43 3C MOV EAX,DWORD PTR DS:
0040E8BD|.E8 1E8AFFFF CALL keygenme.004072E0 ;取注册码
0040E8C2|.8B45 CC MOV EAX,DWORD PTR SS:
0040E8C5|.B9 09000000 MOV ECX,9
0040E8CA|.BA 25000000 MOV EDX,25
0040E8CF|.E8 8049FFFF CALL keygenme.00403254 ;从第37(10进制)位取9位, 形成子串2
0040E8D4|.8B55 D0 MOV EDX,DWORD PTR SS:
0040E8D7|.58 POP EAX
0040E8D8|.E8 7F48FFFF CALL keygenme.0040315C ;这里是字符串比较函数,子串1
0040E8DD|.0F85 80000000 JNZ keygenme.0040E963 ;和子串2必须相等,否则完蛋
0040E8E3|.8D45 FC LEA EAX,DWORD PTR SS: ;从ini文件取code字段并与0x1a异或,得
0040E8E6|.E8 B5F9FFFF CALL keygenme.0040E2A0 ;到子串3
0040E8EB|.8B45 F8 MOV EAX,DWORD PTR SS: ;注册码最后8位,作为子串4
0040E8EE|.E8 5947FFFF CALL keygenme.0040304C
0040E8F3|.8BF8 MOV EDI,EAX
0040E8F5|.85FF TEST EDI,EDI
0040E8F7|.7E 25 JLE SHORT keygenme.0040E91E
0040E8F9|.BE 01000000 MOV ESI,1
0040E8FE|>8D45 F8 /LEA EAX,DWORD PTR SS:
0040E901|.E8 1649FFFF |CALL <keygenme.字符串拷贝函数>
0040E906|.8B55 F8 |MOV EDX,DWORD PTR SS: ;依次取子串4的字母
0040E909|.8A5432 FF |MOV DL,BYTE PTR DS:
0040E90D|.8B4D FC |MOV ECX,DWORD PTR SS: ;依次取子串3的字母
0040E910|.8A4C31 FF |MOV CL,BYTE PTR DS:
0040E914|.0AD1 |OR DL,CL ;对应位进行或运算形成子串5
0040E916|.885430 FF |MOV BYTE PTR DS:,DL
0040E91A|.46 |INC ESI
0040E91B|.4F |DEC EDI
0040E91C|.^ 75 E0 \JNZ SHORT keygenme.0040E8FE
0040E91E|>8D45 C8 LEA EAX,DWORD PTR SS:
0040E921|.E8 4AF9FFFF CALL keygenme.0040E270
0040E926|.8B55 C8 MOV EDX,DWORD PTR SS:
0040E929|.8B45 F8 MOV EAX,DWORD PTR SS:
0040E92C|.E8 2B48FFFF CALL keygenme.0040315C ;经过转换的系统盘Serial串
0040E931|.75 30 JNZ SHORT keygenme.0040E963 ;必须和子串5相等
0040E933|.8D55 C4 LEA EDX,DWORD PTR SS:
0040E936|.8B43 38 MOV EAX,DWORD PTR DS:
0040E939|.E8 A289FFFF CALL keygenme.004072E0
0040E93E|.8D45 C4 LEA EAX,DWORD PTR SS:
0040E941|.BA A0E94000 MOV EDX,keygenme.0040E9A0 ;ASCII ", you are the best cracker!"
0040E946|.E8 0947FFFF CALL keygenme.00403054
0040E94B|.8B55 C4 MOV EDX,DWORD PTR SS:
0040E94E|.8B43 38 MOV EAX,DWORD PTR DS:
0040E951|.E8 D689FFFF CALL keygenme.0040732C
0040E956|.8B43 3C MOV EAX,DWORD PTR DS:
0040E959|.BA C4E94000 MOV EDX,keygenme.0040E9C4 ;ASCII "Registered!"
0040E95E|.E8 C989FFFF CALL keygenme.0040732C
0040E963|>8B43 48 MOV EAX,DWORD PTR DS:
0040E966|.B2 01 MOV DL,1
0040E968|.8B08 MOV ECX,DWORD PTR DS:
0040E96A|.FF51 08 CALL DWORD PTR DS:
0040E96D|.33C0 XOR EAX,EAX
0040E96F|.5A POP EDX
0040E970|.59 POP ECX
0040E971|.59 POP ECX
0040E972|.64:8910 MOV DWORD PTR FS:,EDX
0040E975|.68 8FE94000 PUSH keygenme.0040E98F
0040E97A|>8D45 C4 LEA EAX,DWORD PTR SS:
0040E97D|.BA 0F000000 MOV EDX,0F
0040E982|.E8 6D45FFFF CALL keygenme.00402EF4
0040E987\.C3 RETN
0040E988 .^ E9 1740FFFF JMP keygenme.004029A4
0040E98D .^ EB EB JMP SHORT keygenme.0040E97A
0040E98F .5F POP EDI
0040E990 .5E POP ESI
0040E991 .5B POP EBX
0040E992 .8BE5 MOV ESP,EBP
0040E994 .5D POP EBP
0040E995 .C3 RETN
从ini文件读code字段的函数:
0040E2A0/$55 PUSH EBP
0040E2A1|.8BEC MOV EBP,ESP
0040E2A3|.6A 00 PUSH 0
0040E2A5|.6A 00 PUSH 0
0040E2A7|.53 PUSH EBX
0040E2A8|.8BD8 MOV EBX,EAX
0040E2AA|.33C0 XOR EAX,EAX
0040E2AC|.55 PUSH EBP
0040E2AD|.68 4DE34000 PUSH keygenme.0040E34D
0040E2B2|.64:FF30 PUSH DWORD PTR FS:
0040E2B5|.64:8920 MOV DWORD PTR FS:,ESP
0040E2B8|.8D45 FC LEA EAX,DWORD PTR SS:
0040E2BB|.E8 6474FFFF CALL keygenme.00405724 ;获取当前路径
0040E2C0|.8D45 FC LEA EAX,DWORD PTR SS:
0040E2C3|.BA 64E34000 MOV EDX,keygenme.0040E364 ;ASCII "acafeel.ini"
0040E2C8|.E8 874DFFFF CALL keygenme.00403054 ;连接路径和ini文件名
0040E2CD|.8B45 FC MOV EAX,DWORD PTR SS:
0040E2D0|.E8 F777FFFF CALL keygenme.00405ACC
0040E2D5|.A3 7C554100 MOV DWORD PTR DS:,EAX
0040E2DA|.A1 7C554100 MOV EAX,DWORD PTR DS:
0040E2DF|.C640 18 00 MOV BYTE PTR DS:,0
0040E2E3|.A1 7C554100 MOV EAX,DWORD PTR DS:
0040E2E8|.83C0 1D ADD EAX,1D
0040E2EB|.BA 78E34000 MOV EDX,keygenme.0040E378 ;ASCII "RegInfo"
0040E2F0|.E8 2F4CFFFF CALL <keygenme.字符串转移函数>
0040E2F5|.8D45 F8 LEA EAX,DWORD PTR SS:
0040E2F8|.50 PUSH EAX ; /Arg1
0040E2F9|.A1 7C554100 MOV EAX,DWORD PTR DS: ; |
0040E2FE|.33C9 XOR ECX,ECX ; |
0040E300|.BA 88E34000 MOV EDX,keygenme.0040E388 ; |ASCII "code"
0040E305|.E8 1E77FFFF CALL keygenme.00405A28 ; \keygenme.00405A28
0040E30A|.8B55 F8 MOV EDX,DWORD PTR SS: ;获取code字段
0040E30D|.B8 80554100 MOV EAX,keygenme.00415580
0040E312|.E8 0D4CFFFF CALL <keygenme.字符串转移函数> ;字符串拷贝,从EDX到EAX
0040E317|.8BCB MOV ECX,EBX
0040E319|.BA 1A000000 MOV EDX,1A
0040E31E|.A1 80554100 MOV EAX,DWORD PTR DS: ;code字段
0040E323|.E8 24FEFFFF CALL keygenme.0040E14C ;字符串xor函数
0040E328|.A1 7C554100 MOV EAX,DWORD PTR DS:
0040E32D|.8B10 MOV EDX,DWORD PTR DS:
0040E32F|.FF52 04 CALL DWORD PTR DS:
0040E332|.33C0 XOR EAX,EAX
0040E334|.5A POP EDX
0040E335|.59 POP ECX
0040E336|.59 POP ECX
0040E337|.64:8910 MOV DWORD PTR FS:,EDX
0040E33A|.68 54E34000 PUSH keygenme.0040E354
0040E33F|>8D45 F8 LEA EAX,DWORD PTR SS:
0040E342|.BA 02000000 MOV EDX,2
0040E347|.E8 A84BFFFF CALL keygenme.00402EF4
从这里我们可以知道必须在当前路径出必须有acafeel.ini,内容至少有:
code=xxxxxx
这个函数从code字段读入字符串,并做点处理, 处理函数见下面的代码, 是个很简单的函数, 其中的关键代码:
0040E181|.BB 01000000 MOV EBX,1
0040E186|>8D45 FC /LEA EAX,DWORD PTR SS:
0040E189|.E8 8E50FFFF |CALL <keygenme.字符串拷贝函数>
0040E18E|.8B55 FC |MOV EDX,DWORD PTR SS:
0040E191|.0FB6541A FF |MOVZX EDX,BYTE PTR DS:
0040E196|.33D7 |XOR EDX,EDI //运算就只有这一步
0040E198|.885418 FF |MOV BYTE PTR DS:,DL
0040E19C|.43 |INC EBX
0040E19D|.4E |DEC ESI
0040E19E|.^ 75 E6 \JNZ SHORT keygenme.0040E186
0040E1A0|>8B45 F8 MOV EAX,DWORD PTR SS:
0040E1A3|.8B55 FC MOV EDX,DWORD PTR SS:
还有一个主要函数 ,就是对用户名进行处理, 有点复杂~~
0040DBF4/$55 PUSH EBP
0040DBF5|.8BEC MOV EBP,ESP
0040DBF7|.B9 0C000000 MOV ECX,0C
0040DBFC|>6A 00 /PUSH 0
0040DBFE|.6A 00 |PUSH 0
0040DC00|.49 |DEC ECX
0040DC01|.^ 75 F9 \JNZ SHORT keygenme.0040DBFC
0040DC03|.51 PUSH ECX
0040DC04|.53 PUSH EBX
0040DC05|.56 PUSH ESI
0040DC06|.57 PUSH EDI
0040DC07|.8955 F8 MOV DWORD PTR SS:,EDX
0040DC0A|.8945 FC MOV DWORD PTR SS:,EAX
0040DC0D|.8B45 FC MOV EAX,DWORD PTR SS:
0040DC10|.E8 EB55FFFF CALL <keygenme.申请空间>
0040DC15|.33C0 XOR EAX,EAX
0040DC17|.55 PUSH EBP
0040DC18|.68 25E04000 PUSH keygenme.0040E025
0040DC1D|.64:FF30 PUSH DWORD PTR FS:
0040DC20|.64:8920 MOV DWORD PTR FS:,ESP
0040DC23|.8B45 FC MOV EAX,DWORD PTR SS:
0040DC26|.E8 2154FFFF CALL keygenme.0040304C
0040DC2B|.25 01000080 AND EAX,80000001 ;用户名长度和80000001与
0040DC30|.79 05 JNS SHORT keygenme.0040DC37
0040DC32|.48 DEC EAX
0040DC33|.83C8 FE OR EAX,FFFFFFFE
0040DC36|.40 INC EAX
0040DC37|>85C0 TEST EAX,EAX
0040DC39|.0F85 DA010000 JNZ keygenme.0040DE19 ;用户名长度是偶数时
0040DC3F|.8D55 D8 LEA EDX,DWORD PTR SS:
0040DC42|.8B45 FC MOV EAX,DWORD PTR SS:
0040DC45|.E8 0AFFFFFF CALL keygenme.0040DB54 ;用户名反序
0040DC4A|.8B55 D8 MOV EDX,DWORD PTR SS:
0040DC4D|.8D45 FC LEA EAX,DWORD PTR SS:
0040DC50|.E8 1353FFFF CALL keygenme.00402F68 ;反序后的用户名放到
0040DC55|.BE 80000000 MOV ESI,80
0040DC5A|.8D45 E8 LEA EAX,DWORD PTR SS:
0040DC5D|.BA 3CE04000 MOV EDX,keygenme.0040E03C ;ASCII "WoAiZhangLiangYing!"
0040DC62|.E8 0153FFFF CALL keygenme.00402F68 ;"WoAiZhangLiangYing!"放到
0040DC67|.8B45 FC MOV EAX,DWORD PTR SS: ;反序后的用户名
0040DC6A|.E8 DD53FFFF CALL keygenme.0040304C ;取长度
0040DC6F|.85C0 TEST EAX,EAX
0040DC71|.0F8E AF000000 JLE keygenme.0040DD26
0040DC77|.8945 DC MOV DWORD PTR SS:,EAX ;用户名长度放到
0040DC7A|.BB 01000000 MOV EBX,1
0040DC7F|>8B45 FC /MOV EAX,DWORD PTR SS: ;循环开始,eax放反序后的用户名
0040DC82|.33C9 |XOR ECX,ECX
0040DC84|.8A4C18 FF |MOV CL,BYTE PTR DS: ;依次取用户名中的字母
0040DC88|.03CE |ADD ECX,ESI ;加上80
0040DC8A|.8BC1 |MOV EAX,ECX
0040DC8C|.B9 FF000000 |MOV ECX,0FF
0040DC91|.99 |CDQ
0040DC92|.F7F9 |IDIV ECX ;除以0ff
0040DC94|.8BF2 |MOV ESI,EDX ;余数到esi
0040DC96|.8B45 E8 |MOV EAX,DWORD PTR SS: ;"WoAiZhangLiangYing!"放到EAX
0040DC99|.33C9 |XOR ECX,ECX
0040DC9B|.8A4C18 FF |MOV CL,BYTE PTR DS: ;依次取"WoAiZhangLiangYing!"中的字母
0040DC9F|.33F1 |XOR ESI,ECX ;取出来的字母和esi xor
0040DCA1|.8BC3 |MOV EAX,EBX
0040DCA3|.25 01000080 |AND EAX,80000001
0040DCA8|.79 05 |JNS SHORT keygenme.0040DCAF ;ebx非负则跳
0040DCAA|.48 |DEC EAX
0040DCAB|.83C8 FE |OR EAX,FFFFFFFE
0040DCAE|.40 |INC EAX
0040DCAF|>85C0 |TEST EAX,EAX
0040DCB1|.75 1C |JNZ SHORT keygenme.0040DCCF ;ebx如果为偶数, 则跳
0040DCB3|.8D4D D4 |LEA ECX,DWORD PTR SS:
0040DCB6|.BA 02000000 |MOV EDX,2
0040DCBB|.8BC6 |MOV EAX,ESI
0040DCBD|.E8 AE76FFFF |CALL keygenme.00405370 ;如果ebx为偶数,则不经过下面的循环,直接转为字符串
0040DCC2|.8B55 D4 |MOV EDX,DWORD PTR SS:
0040DCC5|.8D45 F0 |LEA EAX,DWORD PTR SS:
0040DCC8|.E8 8753FFFF |CALL keygenme.00403054
0040DCCD|.EB 4D |JMP SHORT keygenme.0040DD1C
0040DCCF|>8D4D EC |LEA ECX,DWORD PTR SS:
0040DCD2|.BA 02000000 |MOV EDX,2
0040DCD7|.8BC6 |MOV EAX,ESI
0040DCD9|.E8 9276FFFF |CALL keygenme.00405370 ;将刚才得到ESI变为字符串, 16进制的
0040DCDE|.8B45 EC |MOV EAX,DWORD PTR SS:
0040DCE1|.E8 6653FFFF |CALL keygenme.0040304C
0040DCE6|.8BF8 |MOV EDI,EAX
0040DCE8|.85FF |TEST EDI,EDI
0040DCEA|.7E 30 |JLE SHORT keygenme.0040DD1C ;转换后字符串长度为零则跳
0040DCEC|.C745 F4 01000>|MOV DWORD PTR SS:,1 ;初始化索引
0040DCF3|>8B45 EC |/MOV EAX,DWORD PTR SS: ;EAX为刚才ESI转化为的字符串
0040DCF6|.8B55 F4 ||MOV EDX,DWORD PTR SS: ;索引
0040DCF9|.0FB64410 FF ||MOVZX EAX,BYTE PTR DS: ;依次取其中的字母
0040DCFE|.8D4D D0 ||LEA ECX,DWORD PTR SS:
0040DD01|.BA 02000000 ||MOV EDX,2
0040DD06|.E8 6576FFFF ||CALL keygenme.00405370 ;再将这个字母的16进制转为字符串
0040DD0B|.8B55 D0 ||MOV EDX,DWORD PTR SS:
0040DD0E|.8D45 F0 ||LEA EAX,DWORD PTR SS:
0040DD11|.E8 3E53FFFF ||CALL keygenme.00403054 ;连接转移最后的字符串
0040DD16|.FF45 F4 ||INC DWORD PTR SS:
0040DD19|.4F ||DEC EDI
0040DD1A|.^ 75 D7 |\JNZ SHORT keygenme.0040DCF3
0040DD1C|>43 |INC EBX
0040DD1D|.FF4D DC |DEC DWORD PTR SS:
0040DD20|.^ 0F85 59FFFFFF \JNZ keygenme.0040DC7F
0040DD26|>8D45 F0 LEA EAX,DWORD PTR SS:
0040DD29|.50 PUSH EAX
0040DD2A|.8D45 CC LEA EAX,DWORD PTR SS:
0040DD2D|.B9 58E04000 MOV ECX,keygenme.0040E058 ;ASCII "6143614665654C21"
0040DD32|.8B55 F0 MOV EDX,DWORD PTR SS:
0040DD35|.E8 5E53FFFF CALL keygenme.00403098 ;字符串连接
0040DD3A|.8B45 CC MOV EAX,DWORD PTR SS:
0040DD3D|.B9 10000000 MOV ECX,10
0040DD42|.BA 01000000 MOV EDX,1
0040DD47|.E8 0855FFFF CALL keygenme.00403254
0040DD4C|.8B45 F0 MOV EAX,DWORD PTR SS: ;上面生成的字符串
0040DD4F|.E8 F852FFFF CALL keygenme.0040304C
0040DD54|.85C0 TEST EAX,EAX
0040DD56|.7E 50 JLE SHORT keygenme.0040DDA8
0040DD58|.8945 DC MOV DWORD PTR SS:,EAX
0040DD5B|.BB 01000000 MOV EBX,1
0040DD60|>8BC3 /MOV EAX,EBX
0040DD62|.25 01000080 |AND EAX,80000001
0040DD67|.79 05 |JNS SHORT keygenme.0040DD6E
0040DD69|.48 |DEC EAX
0040DD6A|.83C8 FE |OR EAX,FFFFFFFE
0040DD6D|.40 |INC EAX
0040DD6E|>85C0 |TEST EAX,EAX
0040DD70|.74 30 |JE SHORT keygenme.0040DDA2 ;如果ebx为偶数,则跳
0040DD72|.8D45 C4 |LEA EAX,DWORD PTR SS:
0040DD75|.50 |PUSH EAX
0040DD76|.B9 02000000 |MOV ECX,2
0040DD7B|.8BD3 |MOV EDX,EBX
0040DD7D|.8B45 F0 |MOV EAX,DWORD PTR SS:
0040DD80|.E8 CF54FFFF |CALL keygenme.00403254 ;取子串
0040DD85|.8B45 C4 |MOV EAX,DWORD PTR SS:
0040DD88|.E8 1776FFFF |CALL keygenme.004053A4 ;字符串转为数字
0040DD8D|.8BD0 |MOV EDX,EAX
0040DD8F|.8D45 C8 |LEA EAX,DWORD PTR SS:
0040DD92|.E8 5152FFFF |CALL keygenme.00402FE8 ;数字拷贝到ebp-38
0040DD97|.8B55 C8 |MOV EDX,DWORD PTR SS:
0040DD9A|.8D45 E4 |LEA EAX,DWORD PTR SS:
0040DD9D|.E8 B252FFFF |CALL keygenme.00403054
0040DDA2|>43 |INC EBX
0040DDA3|.FF4D DC |DEC DWORD PTR SS:
0040DDA6|.^ 75 B8 \JNZ SHORT keygenme.0040DD60
0040DDA8|>8D55 C0 LEA EDX,DWORD PTR SS:
0040DDAB|.8B45 E4 MOV EAX,DWORD PTR SS:
0040DDAE|.E8 A1FDFFFF CALL keygenme.0040DB54 ;拷贝.
0040DDB3|.8B55 C0 MOV EDX,DWORD PTR SS:
0040DDB6|.8D45 E4 LEA EAX,DWORD PTR SS:
0040DDB9|.E8 AA51FFFF CALL keygenme.00402F68 ;取反序
0040DDBE|.8B45 E4 MOV EAX,DWORD PTR SS:
0040DDC1|.E8 8652FFFF CALL keygenme.0040304C
0040DDC6|.85C0 TEST EAX,EAX
0040DDC8|.0F8E 1C020000 JLE keygenme.0040DFEA
0040DDCE|.8945 DC MOV DWORD PTR SS:,EAX
0040DDD1|.BB 01000000 MOV EBX,1 ;ebx为索引
0040DDD6|>8B45 E4 /MOV EAX,DWORD PTR SS:
0040DDD9|.33C9 |XOR ECX,ECX
0040DDDB|.8A4C18 FF |MOV CL,BYTE PTR DS: ;依次取其中的字节
0040DDDF|.03CE |ADD ECX,ESI
0040DDE1|.8BC1 |MOV EAX,ECX
0040DDE3|.B9 FF000000 |MOV ECX,0FF
0040DDE8|.99 |CDQ
0040DDE9|.F7F9 |IDIV ECX
0040DDEB|.8BF2 |MOV ESI,EDX
0040DDED|.B9 2B000000 |MOV ECX,2B
0040DDF2|.33F1 |XOR ESI,ECX ;与2b xor
0040DDF4|.8D4D BC |LEA ECX,DWORD PTR SS:
0040DDF7|.BA 12000000 |MOV EDX,12
0040DDFC|.8BC6 |MOV EAX,ESI
0040DDFE|.E8 6D75FFFF |CALL keygenme.00405370 ;16进制转为字符串
0040DE03|.8B55 BC |MOV EDX,DWORD PTR SS:
0040DE06|.8D45 E0 |LEA EAX,DWORD PTR SS:
0040DE09|.E8 4652FFFF |CALL keygenme.00403054
0040DE0E|.43 |INC EBX
0040DE0F|.FF4D DC |DEC DWORD PTR SS:
0040DE12|.^ 75 C2 \JNZ SHORT keygenme.0040DDD6
0040DE14|.E9 D1010000 JMP keygenme.0040DFEA
上面是用户名长度为偶数的情况, 如果用户名长度为奇数, 也可以参考这个分析, 因为两种情况绝大部分的处理是相同的,这里的算法如果看不清楚, 可以看我写的注册机代码, 里面将这个函数实现了一下...
还有个函数要看..是对系统硬盘序列号进行处理, 生成一个字符串. 看代码
0040E270/$53 PUSH EBX
0040E271|.8BD8 MOV EBX,EAX
0040E273|.B0 43 MOV AL,43
0040E275|.E8 56FFFFFF CALL keygenme.0040E1D0 ;这个函数调用GetVolumeInformation获得
0040E27A|.69C0 27400000 IMUL EAX,EAX,4027 ;系统盘的Serial, EAX里是返回值
0040E280|.05 2724400B ADD EAX,0B402427
0040E285|.8BD3 MOV EDX,EBX
0040E287|.E8 8871FFFF CALL keygenme.00405414 ;转成字符串
0040E28C|.53 PUSH EBX
0040E28D|.8B03 MOV EAX,DWORD PTR DS:
0040E28F|.B9 08000000 MOV ECX,8
0040E294|.BA 01000000 MOV EDX,1
0040E299|.E8 B64FFFFF CALL keygenme.00403254 ;从第1位开始取8个字母,形成子串
0040E29E|.5B POP EBX
0040E29F\.C3 RETN
附注册机源码:
#include<iostream>
#include<cstring>
#include<sstream>
#include<windows.h>
#include<fstream>
usingnamespacestd;
#defineMAX_DST100
voidstrxor(char* dst, char* src, char ch) //关于ini文件code 异或的函数
{
intlen = strlen(src);
inti;
for(i=0; i<len; i++)
{
dst = src ^ ch;
}
dst = 0;
}
void HexToDec(char* shex, char* idec ) //十六进制转为整数..找不到合用的就自己写了一个函数..
{ //不过只能这个程序用..
int i, j, mid=0;
int len = strlen(shex);
for(i=0, j=0; i<len; i++)
{
if( shex>='0' && shex<='9' )
mid = shex - '0';
else if(shex>='a' && shex<='f')
mid = shex - 'a' + 10;
else if(shex>='A' && shex<='F')
mid = shex - 'A' + 10;
if (i%2 == 0)
{
mid <<= 4;
idec = mid;
}
else
{
idec |= mid;
j++;
}
}
idec = 0;
}
voidDealWithName(char *namedst, char *namesrc) //对用户名处理的函数,,最复杂的一个函数.
{
strrev(namesrc);
charszLove[] = "WoAiZhangLiangYing!";
charszTemp = {0};
charszTemp2 = {0};
int namelen = strlen(namesrc);
int i, j=0;
unsigned int temp= 0x80;//记录esi
if (namelen %2 ==0)
{
for (i=0; i<namelen; i++)
{
temp += namesrc;
temp %= 0xff;
temp ^= szLove;
if (i%2 == 1)
{
sprintf(szTemp, "%X", temp);
if (szTemp == ' ') szTemp2 = '0';
strcat(namedst, szTemp);
}
else
{
memset(szTemp, 0, sizeof(szTemp));
sprintf(szTemp, "%X", temp);
for (j=0; j<strlen(szTemp); j++)
{
sprintf(szTemp2, "%X", (int)szTemp);
if (szTemp2 == ' ') szTemp2 = '0';
strcat(namedst, szTemp2);
}
}
}
char*szToCat = "6143614665654C21";
strcat(namedst, szToCat);
namedst = 0; //取前16个字母
char szScan = {0};
strcpy(szScan, namedst);
HexToDec(szScan, namedst);
strrev(namedst);
strcpy(szTemp, namedst);
memset(namedst, 0, MAX_DST);
namelen = strlen(szTemp);
for (i=0; i<namelen; i++)
{
temp += szTemp;
temp %= 0xff;
temp ^= 0x2b;
sprintf(szTemp2, "%2X", temp);
if (szTemp2 == ' ') szTemp2 = '0';
strcat(namedst, szTemp2);
}
}
else
{
for (i=0; i<namelen; i++)
{
temp += namesrc;
temp %= 0xff;
temp ^= szLove;
if (i%2 == 0)
{
sprintf(szTemp, "%X", temp);
if (szTemp == ' ') szTemp2 = '0';
strcat(namedst, szTemp);
}
else
{
memset(szTemp, 0, sizeof(szTemp));
sprintf(szTemp, "%X", temp);
for (j=0; j<strlen(szTemp); j++)
{
sprintf(szTemp2, "%X", (int)szTemp);
if (szTemp2 == ' ') szTemp2 = '0';
strcat(namedst, szTemp2);
}
}
}
//cout << namedst << endl;
char*szToCat = "6143614665654C21";
strcat(namedst, szToCat);
namedst = 0; //取前16个字母
//cout << namedst << endl;
char szScan = {0};
strcpy(szScan, namedst);
HexToDec(szScan, namedst);
strrev(namedst);
//cout << namedst << endl;
strcpy(szTemp, namedst);
memset(namedst, 0, MAX_DST);
namelen = strlen(szTemp);
for (i=0; i<namelen; i++)
{
temp += szTemp;
temp %= 0xff;
temp ^= 0x2b;
sprintf(szTemp2, "%2X", temp);
if (szTemp2 == ' ') szTemp2 = '0';
strcat(namedst, szTemp2);
}
//cout << namedst << endl;
}
}
voidGetSystemSerial(char*serialdst) //获取系统Serial并做处理
{
char*path = "c:\\";
charbuffer;
DWORD dwSerial;
DWORD dwMaximumComponentLength;
DWORD dwFileSystemFlags;
::GetVolumeInformation(path, 0, 0, &dwSerial, &dwMaximumComponentLength, &dwFileSystemFlags, NULL, NULL);
dwSerial *= 0x4027;
dwSerial += 0xB402427;
sprintf(serialdst, "%u", dwSerial);
serialdst = 0;
}
voidmain()
{
charcode = {0}; //ini的code
charxorcode; //ini的code异或后的结果
charregcode = {0};
memset(regcode, 'A', 53); //注册码中有很多字母没用, 我就用'A'来填充吧..
charname = "vecri"; //用户名
charnamesrc;
strcpy(namesrc, name);
charnamedst = {0};
DealWithName(namedst, namesrc); //对用户名处理
charsub1 = {0};
strncpy(sub1, namedst+8, 8); //取子串1
strncpy(regcode+36, sub1, 8); //从子串1获取注册码的一部分, 要看分析~~
char*sub3 = xorcode;
char*sub4 = "asdfasdf"; //子串4, 注册码最后8位
char sysserial = {0};
GetSystemSerial(sysserial); //Serial转换的结果
strxor(code, sysserial, 0x1a); //得到ini的code
ofstreamfout("result.txt");
fout << code << endl;
strncpy(regcode+45, sysserial, 8);
fout << regcode << endl;
fout.close(); //结果文件, 其中有ini的code , 和注册码
/*大家自己在crackme的目录下新建个acafeel.ini, 其中内容为
code=我生成的code
*/
//呵呵...我懒得去写代码..~~
cout << "name: " << name << endl;
cout << "code: " << regcode << endl;
charch;
cin >> ch;
}
------------------------------------------------------------------------
【破解总结】看到正式版和前传版, 就慌忙拿前传版来破,,呵呵..感觉应该简单点吧....~接下来搞正式版的~
------------------------------------------------------------------------
【版权声明
[ 本帖最后由 vecri 于 2008-1-5 19:40 编辑 ] /:011 向楼主看齐 .........../:014 相当的彪悍呀/:001 前传版一只搞不定,今天总算看到了啊。 这里是不是不轻易给精华的啊。.~/:002
感觉还是算法分析版块好拿精华~ 收藏下来慢慢看了 原帖由 vecri 于 2007-12-26 11:23 发表 https://www.chinapyg.com/images/common/back.gif
这里是不是不轻易给精华的啊。.~/:002
感觉还是算法分析版块好拿精华~
精华不是那么容易骗的/:018
楼主忒彪悍了,膜拜
[ 本帖最后由 小子贼野 于 2008-1-5 16:41 编辑 ] 确实不好骗~~~努力学习中,争取拿到精华。。。 学了汇编后才知其然啊,原来aCaFeeL大虾在创建窗口的时候使用了WS_DISABLED风格属性,让窗口初始化状态是被禁止的,然后又在设置文本按钮颜色的参数为Gray,LZ那两个补丁打的很漂亮,不过应该可以在代码段直接修改属性达到目的的,可难的就是在茫茫代码量中找到需要修改属性的值啊,就想petnt大虾过后飞笨鸟之CrackMe一样在易语言代码段中修改属性值来达到去掉只读属性。 好长的代码。。没有图???
页:
[1]
2