今天取国外网站 转转,下来N个CRACKME,这些CRACKME太难了,不单加壳,而且有很强的ANTI-DEBUG,受不了。。。
发现一个CRACKME(NC1),还没人提交Solution,于是DOWN了下来。。分析了一下。虽是#1的,但我感觉挺难的。。
1.PEID查壳发现未加壳,使用Borland Delphi 6.0 - 7.0编写
3.OD载入NC1
4.右击超级字符串查找 -> ASCII码查找 -> 找到Mission Accomplished!,双击进入
5.进入后向上找,在00453C04处下断点(F2),F9运行程序,输入ABC
点CHECK后,0D产生中断
6.单步向下F8,算法分析。
00453C04 55 PUSH EBP
00453C05 8BEC MOV EBP,ESP
00453C07 6A 00 PUSH 0
00453C09 6A 00 PUSH 0
00453C0B 53 PUSH EBX
00453C0C 8BD8 MOV EBX,EAX
00453C0E 33C0 XOR EAX,EAX
00453C10 55 PUSH EBP
00453C11 68 553D4500 PUSH NC1.00453D55
00453C16 64:FF30 PUSH DWORD PTR FS:[EAX]
00453C19 64:8920 MOV DWORD PTR FS:[EAX],ESP
00453C1C 8D55 F8 LEA EDX,DWORD PTR SS:[EBP-8]
00453C1F 8B83 F8020000 MOV EAX,DWORD PTR DS:[EBX+2F8]
00453C25 E8 DAEFFDFF CALL NC1.00432C04
00453C2A 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8] ; EAX=原serial
00453C2D 8D55 FC LEA EDX,DWORD PTR SS:[EBP-4]
00453C30 E8 93FEFFFF CALL NC1.00453AC8 ; serial的转化
//F7步入 00453C30后,发现算法大概是这样的:
1.内存中存在两张表,一张是大写字母转化表,一张是小写字母的。
大写的表: "qwertyuiopasdfghjklzxcvbnm" 表1
小写的表: "mnbvcxzlkjhgfdsapoiuytrewq" 表2
2.转化方式:正常字母表 "abcdefghijklmnopqrstuvwxyz"
FOR EXAMPLE: A -> W, B -> E
a -> n, b -> b
也就是先找到输入字符在正常字母表中的位置X,若是大写字母则到表1中找,转化后的字符为位置值X的后一个字符
若是小写字母则到表2中找,转化后的字符为位置值X的后一个字符
00453C35 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; EAX=新serial
00453C38 E8 FB04FBFF CALL NC1.00404138 ; 计算新serial长度
00453C3D 83F8 03 CMP EAX,3
00453C40 0F85 E7000000 JNZ NC1.00453D2D ; jmp if eax != 3
//求第一个字符的算法部分
//需要逆推求第一个字符
1. EAX = 0x39AB XOR 0x12 = 0x39B9
2. 逆向 AND EAX,7FFF 为 AX最高位+8,即0x39B9 -> 0xB9B9
问:为什么为什么是AX最高位+8呢?
答:比如 AND EAX,7FFF
EAX: 0011 1001 1011 1001
AND 0111 1111 1111 1111
0011 1001 1011 1001(39B9)
要得到0011 1001 1011 1001(39B9),EAX(AX)最高位可能为0或1,但是根据输入任意字符后在右边寄存器窗口EAX变化可知为1
即为B9B9
3. EAX=B900
EDX=00B9
so EAX = EAX + EDX = B9B9
4. AL = B9 XOR 0xFF = 46(F)
5. 再逆向表1,"F"对应的是正常字符表中的"M"
得到第一个字符为 "M"
00453C46 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; EAX=新serial
00453C49 8A00 MOV AL,BYTE PTR DS:[EAX] ; AL=新serial第一位字符的ASCII码
00453C4B 34 FF XOR AL,0FF ; AL = AL XOR 0xFF
00453C4D 25 FF000000 AND EAX,0FF ; EAX = EAX && 0xFF
00453C52 8BD0 MOV EDX,EAX ; EDX=EAX
00453C54 C1E0 08 SHL EAX,8 ; EAX 逻辑左移8位
00453C57 03C2 ADD EAX,EDX ; EAX = EAX + EDX
00453C59 25 FFFF0000 AND EAX,0FFFF ; EAX = EAX && 0xFFFF
00453C5E 25 FF7F0000 AND EAX,7FFF ; EAX = EAX && 0x7FFF
00453C63 83F0 12 XOR EAX,12 ; EAX = EAX XOR 0x12
00453C66 3D AB390000 CMP EAX,39AB
00453C6B 0F85 B0000000 JNZ NC1.00453D21
//求第二个字符的算法部分
00453C71 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; EAX=新serial
00453C74 0FB640 01 MOVZX EAX,BYTE PTR DS:[EAX+1] ; EAX=新serial第二位字符的ASCII码
00453C78 BA 05000000 MOV EDX,5 ; EDX = 5
//算法1不太懂,有好几种可能的,希望高手帮助
00453C7D E8 F2FDFFFF CALL NC1.00453A74 ; 算法1
00453C82 83E8 02 SUB EAX,2 ; EAX = EAX - 2
00453C85 0F85 8A000000 JNZ NC1.00453D15
//求第三个字符的算法部分
逆向第三个字符方法
1. EBX = BF89
EBX - 0x53 = BF36
X(字符的ASCII码值) * X * 4 + 5 * X = BF36
--> X = 6E(n)
再逆向表2,"n"对应的是正常字符表中的"a"
2. 得到第三个字符为 "a"
00453C8B 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; EAX = 新serial
00453C8E 0FB640 02 MOVZX EAX,BYTE PTR DS:[EAX+2] ; EAX = 新serial第三位字符的ASCII码
00453C92 BA 02000000 MOV EDX,2 ; EDX = 2
00453C97 E8 F8FDFFFF CALL NC1.00453A94 ; 算法2(EAX = 第三个字符的ASCII码 * ASCII码)
00453C9C BA 04000000 MOV EDX,4 ; EDX = 4
00453CA1 E8 AEFDFFFF CALL NC1.00453A54 ; EAX=算法2得出的值*4
00453CA6 8BD8 MOV EBX,EAX ; EBX=EAX
00453CA8 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; EAX=新serial
00453CAB 0FB640 02 MOVZX EAX,BYTE PTR DS:[EAX+2] ; EAX = 新serial第三位字符的ASCII码
00453CAF BA 05000000 MOV EDX,5 ; EDX = 5
00453CB4 E8 9BFDFFFF CALL NC1.00453A54 ; EAX=第三位字符的ASCII码*5
00453CB9 03D8 ADD EBX,EAX ; EBX=EBX+EAX=算法2 + 第三位字符的ASCII码*5
00453CBB 83C3 53 ADD EBX,53 ; EBX = EBX + 0x53
00453CBE 81FB 89BF0000 CMP EBX,0BF89
00453CC4 75 43 JNZ SHORT NC1.00453D09
//CheckSum算法
我就是通过逆向这里得出第二个字符的。菜啊!!
1. EAX = 0x1027
2. 第一位字符的ASCII码 * 2 + X(第二位字符的ASCII码) * 5 + 第三位字符的ASCII码 逻辑左移5位 = 0x1027
46 * 2 + X * 5 + D52 = 1027
X = 75(u)
3. 再逆向表2,"u"对应的是正常字符表中的"s"
得到第二个字符为 "s"
00453CC6 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; EAX=新serial
00453CC9 0FB600 MOVZX EAX,BYTE PTR DS:[EAX] ; EAX=新serial第一位字符的ASCII码
00453CCC 03C0 ADD EAX,EAX ; EAX * 2
00453CCE 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4] ; EDX = 新serial
00453CD1 0FB652 01 MOVZX EDX,BYTE PTR DS:[EDX+1] ; EDX = 新serial第二位字符的ASCII码
00453CD5 8D1492 LEA EDX,DWORD PTR DS:[EDX+EDX*4] ; EDX=第二位字符的ASCII码*5
00453CD8 03C2 ADD EAX,EDX ; EAX=EAX+EDX
00453CDA 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]
00453CDD 0FB652 02 MOVZX EDX,BYTE PTR DS:[EDX+2] ; EDX = 新serial第三位字符的ASCII码
00453CE1 8BCA MOV ECX,EDX ; ECX=EDX
00453CE3 C1E2 05 SHL EDX,5 ; EDX逻辑左移5位
00453CE6 2BD1 SUB EDX,ECX ; EDX=EDX-ECX
00453CE8 03C2 ADD EAX,EDX ; EAX=EAX+EDX
00453CEA 3D 27100000 CMP EAX,1027
00453CEF 75 0C JNZ SHORT NC1.00453CFD
00453CF1 B8 6C3D4500 MOV EAX,NC1.00453D6C ; Mission Accomplished! ;任务完成
00453CF6 E8 2938FDFF CALL NC1.00427524
00453CFB EB 3A JMP SHORT NC1.00453D37
00453CFD B8 8C3D4500 MOV EAX,NC1.00453D8C ; Checksum failed!
00453D02 E8 1D38FDFF CALL NC1.00427524
00453D07 EB 2E JMP SHORT NC1.00453D37
00453D09 B8 A83D4500 MOV EAX,NC1.00453DA8 ; Third check fail! ;第三个字符错误
00453D0E E8 1138FDFF CALL NC1.00427524
00453D13 EB 22 JMP SHORT NC1.00453D37
00453D15 B8 C43D4500 MOV EAX,NC1.00453DC4 ; Second check fail! ;第二个字符错误
00453D1A E8 0538FDFF CALL NC1.00427524
00453D1F EB 16 JMP SHORT NC1.00453D37
00453D21 B8 E03D4500 MOV EAX,NC1.00453DE0 ; First check fail! ;第一个字符错误
00453D26 E8 F937FDFF CALL NC1.00427524
00453D2B EB 0A JMP SHORT NC1.00453D37
00453D2D B8 FC3D4500 MOV EAX,NC1.00453DFC ; Incorrect length!
00453D32 E8 ED37FDFF CALL NC1.00427524
最终得出的Serial: Msa
OK,完成。。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!