【文章标题】: fornixcrackme1的破解和算法分析
【文章作者】: jdxyw
【软件名称】: fornixcrackme1
【下载地址】: 自己搜索下载
【加壳方式】: 无
【编写语言】: MASM
【使用工具】: od,peid
【操作平台】: xp
【作者声明】: 如果先前有高手已经破解过这个crack,请告知,我将把附件删了,省点空间,谢谢!
--------------------------------------------------------------------------------
【详细过程】
peid查壳,无壳
点击运行,在序列号的窗口会有个提示的字符串
运行od,将其载入,在函数参考中没有发现有getwindowmessage之类的函数,但是我们在代码处发现有senddlgitemmessagea
的函数,并且其中有个参数是wm_gettext,这个通过消息来获取字符串的,我们就将断点下到此处。
在这个消息下面不远处,我们发现了一个函数,GetVolumeInformation,由此可以猜想,这个crack是个与机器信息有关的,通过参数的查看,
我们知道,这是个返回c盘的名字,我的c盘取名是taroobaby,如果你的机子没有取,那么这个函数不起作用
00401187 |. 50 PUSH EAX ; /lParam => 406274
00401188 |. 6A 14 PUSH 14 ; |wParam = 14
0040118A |. 6A 0D PUSH 0D ; |Message = WM_GETTEXT
0040118C |. 6A 64 PUSH 64 ; |ControlID = 64 (100.)
0040118E |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
00401191 |. E8 C6010000 CALL <JMP.&user32.SendDlgItemMessageA> ; \SendDlgItemMessageA 这个是取用户名
00401196 |. B8 88624000 MOV EAX,fornixcr.00406288
0040119B |. 50 PUSH EAX ; /lParam => 406288
0040119C |. 6A 0A PUSH 0A ; |wParam = A
0040119E |. 6A 0D PUSH 0D ; |Message = WM_GETTEXT
004011A0 |. 6A 65 PUSH 65 ; |ControlID = 65 (101.)
004011A2 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004011A5 |. E8 B2010000 CALL <JMP.&user32.SendDlgItemMessageA> ; \SendDlgItemMessageA 这个是取序列号
004011AA |. 68 74624000 PUSH fornixcr.00406274 ; /String = ""
004011AF |. E8 84010000 CALL <JMP.&kernel32.lstrlenA> ; \lstrlenA
004011B4 |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
004011B7 |. 83F8 04 CMP EAX,4
004011BA |. 77 19 JA SHORT fornixcr.004011D5
004011BC |. 6A 10 PUSH 10 ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004011BE |. 68 53604000 PUSH fornixcr.00406053 ; |Title = "Fornix's first Crackme"
004011C3 |. 68 26604000 PUSH fornixcr.00406026 ; |Text = "The name should be atleast 4 characters long"
004011C8 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hOwner
004011CB |. E8 86010000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
004011D0 |. 61 POPAD
004011D1 |. C9 LEAVE
004011D2 |. C2 0400 RETN 4
004011D5 |> 6A 00 PUSH 0 ; /pFileSystemNameSize = NULL
004011D7 |. 6A 00 PUSH 0 ; |pFileSystemNameBuffer = NULL
004011D9 |. 6A 00 PUSH 0 ; |pFileSystemFlags = NULL
004011DB |. 6A 00 PUSH 0 ; |pMaxFilenameLength = NULL
004011DD |. 6A 00 PUSH 0 ; |pVolumeSerialNumber = NULL
004011DF |. 6A 14 PUSH 14 ; |MaxVolumeNameSize = 14 (20.)
004011E1 |. 68 AC624000 PUSH fornixcr.004062AC ; |VolumeNameBuffer = fornixcr.004062AC
004011E6 |. 68 00604000 PUSH fornixcr.00406000 ; |RootPathName = "C:\"
004011EB |. E8 1E010000 CALL <JMP.&kernel32.GetVolumeInformation>; \GetVolumeInformationA 这个是取c盘的标识符
004011F0 |. 68 AC624000 PUSH fornixcr.004062AC ; /String2 = ""
004011F5 |. 68 E8624000 PUSH fornixcr.004062E8 ; |String1 = fornixcr.004062E8
004011FA |. E8 33010000 CALL <JMP.&kernel32.lstrcpyA> ; \lstrcpyA
004011FF |. 68 74624000 PUSH fornixcr.00406274 ; /StringToAdd = ""
00401204 |. 68 E8624000 PUSH fornixcr.004062E8 ; |ConcatString = ""
00401209 |. E8 1E010000 CALL <JMP.&kernel32.lstrcatA> ; \lstrcatA 这个是将用户名复制到磁盘标识符后面
在复制之前,标识符的字母全部转为大写
0040120E |. E8 40000000 CALL fornixcr.00401253 以下三个call都是关键,要跟进
00401213 |. E8 6B000000 CALL fornixcr.00401283
00401218 |. E8 99000000 CALL fornixcr.004012B6
第一个call
00401253 /$ BE E8624000 MOV ESI,fornixcr.004062E8 ; ASCII "TAROOBABYyutou"
00401258 |. BF C0624000 MOV EDI,fornixcr.004062C0
0040125D |. BA 74624000 MOV EDX,fornixcr.00406274 ; ASCII "yutou"
00401262 |. B9 04000000 MOV ECX,4
00401267 |> 85C9 /TEST ECX,ECX
00401269 |. 74 14 |JE SHORT fornixcr.0040127F
0040126B |. 8A06 |MOV AL,BYTE PTR DS:[ESI] 依次取连接后的字符串的字节到AL
0040126D |. 8A22 |MOV AH,BYTE PTR DS:[EDX] 依次取用户的一个字节到AH
0040126F |. 32C4 |XOR AL,AH 以下是一些计算步骤
00401271 |. 24 5F |AND AL,5F
00401273 |. 0C 40 |OR AL,40
00401275 |. 34 09 |XOR AL,9
00401277 |. 8807 |MOV BYTE PTR DS:[EDI],AL 计算结果存到相应的内存处
00401279 |. 46 |INC ESI
0040127A |. 47 |INC EDI
0040127B |. 49 |DEC ECX
0040127C |. 42 |INC EDX
0040127D |.^ EB E8 \JMP SHORT fornixcr.00401267
0040127F |> C607 24 MOV BYTE PTR DS:[EDI],24 在最后处追加上一个字符
00401282 \. C3 RETN
第二个call
00401283 /$ BE 74624000 MOV ESI,fornixcr.00406274 ; ASCII "yutou"
00401288 |. BF C0624000 MOV EDI,fornixcr.004062C0 ; ASCII "D]OI$"
0040128D |. BA E8624000 MOV EDX,fornixcr.004062E8 ; ASCII "TAROOBABYyutou"
00401292 |. 83C7 05 ADD EDI,5
00401295 |. B9 04000000 MOV ECX,4
0040129A |> 85C9 /TEST ECX,ECX
0040129C |. 74 14 |JE SHORT fornixcr.004012B2
0040129E |. 8A06 |MOV AL,BYTE PTR DS:[ESI] 依次取用户名一个字节到AL
004012A0 |. 8A22 |MOV AH,BYTE PTR DS:[EDX] 依次取含有标识符字符串的一个字节到AH
004012A2 |. 32C4 |XOR AL,AH
004012A4 |. 24 3F |AND AL,3F
004012A6 |. 0C 30 |OR AL,30
004012A8 |. 34 09 |XOR AL,9
004012AA |. 8807 |MOV BYTE PTR DS:[EDI],AL 计算所得加到上步计算结果后面
004012AC |. 46 |INC ESI
004012AD |. 47 |INC EDI
004012AE |. 49 |DEC ECX
004012AF |. 42 |INC EDX
004012B0 |.^ EB E8 \JMP SHORT fornixcr.0040129A
004012B2 |> C607 00 MOV BYTE PTR DS:[EDI],0 结束字符串
004012B5 \. C3 RETN
第三个call
004012B6 /$ BE 88624000 MOV ESI,fornixcr.00406288 ; ASCII "123456"
004012BB |. BF C0624000 MOV EDI,fornixcr.004062C0 ; ASCII "D]OI$4=?9"
004012C0 |. BA 92624000 MOV EDX,fornixcr.00406292
004012C5 |. 56 PUSH ESI
004012C6 |. 52 PUSH EDX
004012C7 |. EB 08 JMP SHORT fornixcr.004012D1 这个循环是对序列进行一系列的运算
004012C9 |> 8A06 /MOV AL,BYTE PTR DS:[ESI] 依次取序列号的一个字节到AL
004012CB |. 34 09 |XOR AL,9
004012CD |. 8802 |MOV BYTE PTR DS:[EDX],AL 结果存到DS:[EDX]处
004012CF |. 46 |INC ESI
004012D0 |. 42 |INC EDX
004012D1 |> 803E 00 CMP BYTE PTR DS:[ESI],0
004012D4 |.^ 75 F3 \JNZ SHORT fornixcr.004012C9
004012D6 |. 5A POP EDX
004012D7 |. 5E POP ESI
004012D8 |> 803F 00 /CMP BYTE PTR DS:[EDI],0 这个循环是比较输入序列号算出的字符串和
用户名与机器信息算出的字符串
004012DB |. 75 07 |JNZ SHORT fornixcr.004012E4
004012DD |. 803A 00 |CMP BYTE PTR DS:[EDX],0
004012E0 |. 75 02 |JNZ SHORT fornixcr.004012E4
004012E2 |. EB 12 |JMP SHORT fornixcr.004012F6
004012E4 |> 8A27 |MOV AH,BYTE PTR DS:[EDI] 依次取用户名与机器信息算出的字符串
004012E6 |. 8A02 |MOV AL,BYTE PTR DS:[EDX] 依次取输入序列号算出的字符串
004012E8 |. 38E0 |CMP AL,AH
004012EA |. 75 04 |JNZ SHORT fornixcr.004012F0
004012EC |. 47 |INC EDI
004012ED |. 42 |INC EDX
004012EE |.^ EB E8 \JMP SHORT fornixcr.004012D8
004012F0 |> B8 00000000 MOV EAX,0
004012F5 |. C3 RETN
004012F6 |> B8 01000000 MOV EAX,1
004012FB \. C3 RETN
算法分析
取本机c盘的标识符,将字母转为大写,复制到用户名的前面,成为新的字符串A,设用户名为name,序列号为serial
循环四次,(((A[t] xor name[t]) and 5fh) or 40h) xor 9h,四次以后,在尾部添上一个24h
循环四次, (((name[t] xor A[t]) and 3fh) or 30h) xor 9h,所得结果追加到上步结果
以上两步算出来的就是真的序列号,长度为九
下面便是用户输入序列号的计算算法
serial[t] xor 9h 循环次数为输入序列号的长度
再就是两个计算结果的比较,从上可以看出,这是个与机器信息有关的crack,而且真实序列号不是与输入序列号直接比较,而是输入序列
号也要进行计算。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年08月22日 0:48:55
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课