学破解第120天,《160个CrackerMe之003》学习
前言:
从小学到大专(计算机网络技术专业),玩过去的,所以学习成绩惨不忍睹,什么证书也没考,直到找不到工作才后悔,不知道怎么办才好。
2017年12月16日,通过19元注册码注册论坛账号,开始做伸手党,潜水一年多,上来就是找软件。(拿论坛高大上的软件出去装X)
2018年8月某一天,报名了华中科技大学网络教育本科(计算机科学与技术专业)2018级秋季。(开始提升学历)
2019年6月17日,不愿再做小菜鸟一枚,开始零基础学习破解。(感谢小糊涂虫大哥在我刚开始学习脱壳时,录制视频解答我的问题)
2020年7月7日,感谢H大对我的鼓励,拥有了第一篇获得优秀的文章。(接下来希望学习逆向,逆天改命)
坛友们,年轻就是资本,和我一起逆天改命吧,我的学习过程全部记录及学习资源:https://www.52pojie.cn/thread-1208234-1-1.html
立帖为证!--------记录学习的点点滴滴
0x1分析题目
1.打开软件,发现有弹窗,显示数秒钟
2.然后出现name/serial验证
3.也就是说,我们需要解决以上两个地方才能算破解成功
0x2寻找爆破点
1.看到弹窗,虽然是VB程序,还是想试试messageBOX行不行,显然又不行了,那么该从哪方面寻找突破口呢?
2.实现想不到怎么去这个弹窗了,那就先去看看name/serial,输入52pojie和123456,有一个弹窗告诉我输入错误,我很想messageBOX回溯,但是无奈不行啊,只能下GetDlgItemTextA断点跟踪,发现也不行。
3.算了算了,直接错误提示搜索字符串定位到了关键跳,爆破点
00408677 . /74 62 je short $ROI5LTX.004086DB
00408679 . |8B35 14B14000 mov esi,dword ptr ds:[<&MSVBVM50.__vbaSt>; msvbvm50.__vbaStrCat
0040867F . |68 C06F4000 push $ROI5LTX.00406FC0 ; You Get It
00408684 . |68 DC6F4000 push $ROI5LTX.00406FDC ; /\r\n
00408689 . |FFD6 call esi ; \__vbaStrCat
0040868B . |8BD0 mov edx,eax
0040868D . |8D4D E8 lea ecx,dword ptr ss:[ebp-0x18]
00408690 . |FF15 94B14000 call dword ptr ds:[<&MSVBVM50.__vbaStrMo>; msvbvm50.__vbaStrMove
00408696 . |50 push eax
00408697 . |68 E86F4000 push $ROI5LTX.00406FE8 ; KeyGen It Now
0x3分析算法
1.有了爆破点还是去段首004080F0 F2下断点,成功的断了下来,然后开始单步分析
004081F2 . 50 push eax ; /52pojie
004081F3 . 8B1A mov ebx,dword ptr ds:[edx] ; |计算长度
004081F5 . FF15 F8B04000 call dword ptr ds:[<&MSVBVM50.__vbaLenBstr>] ; \__vbaLenBstr
004081FB . 8BF8 mov edi,eax ; edi是52pojie的长度7
004081FD . 8B4D E8 mov ecx,dword ptr ss:[ebp-0x18] ; ecx是52pojie
00408200 . 69FF 385B0100 imul edi,edi,0x15B38 ; 7*15B38=97E88
00408206 . 51 push ecx ; /取第name一个字符5
00408207 . 0F80 B7050000 jo $ROI5LTX.004087C4 ; |
0040820D . FF15 0CB14000 call dword ptr ds:[<&MSVBVM50.#rtcAnsiValueBstr_516>] ; \rtcAnsiValueBstr
00408213 . 0FBFD0 movsx edx,ax ; 0x35给edx
00408216 . 03FA add edi,edx ; 97E88+0x35=97EBD
00408218 . 0F80 A6050000 jo $ROI5LTX.004087C4
0040821E . 57 push edi ; 转成十进制622269
0040821F . FF15 F4B04000 call dword ptr ds:[<&MSVBVM50.__vbaStrI4>] ; msvbvm50.__vbaStrI4
2.上面的计算还是和前面两个CM一样的套路,继续单步,发现622269变成了622271,换数据输入,经过多次不同的值作比较,可以发现就是加了2。
00408333 . 8BD0 mov edx,eax ; 622271比之前多加了2
00408335 . 8D4D E4 lea ecx,dword ptr ss:[ebp-0x1C]
3.接下来开始单步跟,发现又将622271*3了。
004083F3 . 8B19 mov ebx,dword ptr ds:[ecx] ; 622271
004083F5 . FF15 74B14000 call dword ptr ds:[<&MSVBVM50.__vbaR8Str>] ; msvbvm50.__vbaR8Str
004083FB . DC0D 10104000 fmul qword ptr ds:[0x401010] ; 622271*3=1866813
00408401 . 83EC 08 sub esp,0x8
00408404 . DC25 18104000 fsub qword ptr ds:[0x401018] ; 1866813-2=1866811
4.继续单步走,总之就是注意那一串字符串的变化,然后发现值又变了
004084DC . 52 push edx
004084DD . 8B19 mov ebx,dword ptr ds:[ecx] ; 1866811
004084DF . FF15 74B14000 call dword ptr ds:[<&MSVBVM50.__vbaR8Str>] ; msvbvm50.__vbaR8Str
004084E5 . DC25 20104000 fsub qword ptr ds:[0x401020] ; 1866811 - (-15)=1866826
5.虽然找到了真码,可是算法在哪呢?根据一路走过来的流程,可以看到真码由AKA-拼接682770构成,那么682770从哪来的?为什么没有看到获取52pojie的地方呢?是不是还是不能用Windows API断点?算了,不要紧,反正已经定位到了关键比较函数了,在往上回溯就行了,去段首F2下断点,然后单步开始跟,看看有没有线索
004085C8 . FF15 18B14000 call dword ptr ds:[<&MSVBVM50.__vbaHresultCheckObj>] ; msvbvm50.__vbaHresultCheckObj
004085CE > 8B45 E8 mov eax,dword ptr ss:[ebp-0x18] ; 取出serial 123456
004085D1 . 50 push eax
004085D2 . FF15 74B14000 call dword ptr ds:[<&MSVBVM50.__vbaR8Str>] ; msvbvm50.__vbaR8Str
004085D8 . 8B4D E4 mov ecx,dword ptr ss:[ebp-0x1C]
004085DB . DD9D 1CFFFFFF fstp qword ptr ss:[ebp-0xE4] ; 123456赋值给0012F3FC
004085E1 . 51 push ecx ; 1866826
004085E2 . FF15 74B14000 call dword ptr ds:[<&MSVBVM50.__vbaR8Str>] ; msvbvm50.__vbaR8Str
6.这个CM说实话,我没有找到后面比较的地方,只看到test ah,0x40结果为0,然后清空esi,如果esi为0就跳向失败。
0x4注册机的编写
1.算法部分:
name的长度*15B38+name的第一个字符,然后在加上2,接着乘以3,最后再-2,然后减去-15,得到真正的serial。
2.代码实现:
package cpyutil.xiao.cai.niao.com;
import java.util.Scanner;
public class Register {
public static void main(String[] args) {
String name;
int code;
String serial;
System.out.println("请输入name(不小于4个字符):");
Scanner sc = new Scanner(System.in);// 初始化一个输入流
name = sc.nextLine();// 从控制台读取输入的字符串
if (name == null || name.length() < 4)// 如果输入的长度小于4退出程序
System.exit(0);
sc.close();// 关闭输入流
code = name.length() * 0x15B38;//将字符串的长度乘以0x15B38
code += name.charAt(0);//加上第一个字符
code += 2;//加2
code *= 3;//乘3
code -= 2;//减2
code -= -15;//减-15
// 将数值转换成字符串
serial = String.valueOf(code);
// 输出正确的serial
System.out.println("生成的serial:");
System.out.println(serial);
}
}
输出结果:
请输入name(不小于4个字符):
xiaocainiao
生成的serial:
2933683
3.验证注册机的效果,输入xiaocainiao和2933683,提示注册成功。
0x5总结
1.这个程序有点小bug,点×之后,窗口关闭了,任务管理器中程序却并没有退出。
2.和前面的CM套路还是一样的,不过这个汇编代码大部分看不懂,出现了很多浮点数指令。
3.通过多组数据的输入输出能够确定注册码的计算方法。
4.不懂VB编程,用windows API对付起来还是有些困难啊,那个NAG弹窗搞不定,就这样吧。
PS:善于总结,善于发现,找到分析问题的思路和解决问题的办法。虽然我现在还是零基础的小菜鸟一枚,也许学习逆向逆天改命我会失败,但也有着成功的可能,只要还有希望,就决不放弃!