逆向分析CrackMe系列——CrackMe002

逆向分析CrackMe系列——CrackMe002

这次进行CrackMe002的逆向分析 AfKayAs
(本系列的CrackMe资源均来自我爱破解网).

1. 运行程序,随机输入,进行弹窗:

在这里插入图片描述
2. 进行关键程序位置查找:

    两种思路:

  • 用相关工具进行源程序分析(如PEID),分析出其是否加壳以及其编程语言(此处未加壳,语言为VB);然后对VB中相关的窗口函数进行下断即可。
  • 利用字符串查找(本次分析采用的方式):
    1) 在OD中打开程序并且运行,进行弹窗后(不要进行暂停),在主窗口程序中搜索字符串:
    在这里插入图片描述
    2) 进入相关字符串的显示界面,找到关键词:
    在这里插入图片描述
    3) 进行跟踪,找到关键程序部分:
    在这里插入图片描述

3. 分析:发现字符串 “You Get Wrong”是由另一个地址进行跳转得到:

在这里插入图片描述
4. 进行溯源,发现跳转来自 je short 004025E5

在这里插入图片描述
5. 发现其中正确的字符串显示 “You Get it”;je前面的语句即是判断语句,序列号正确时继续往下执行,序列号错误时就跳转到 “You Get Wrong“字符串(地址为004025E5)处进行执行。

6. 破解程序,只需要用两个nop 指令替换je short 004025E5指令即可:

在这里插入图片描述
7. 继续执行程序,成功:

在这里插入图片描述
8. 第一部分任务结束,接下来进行序列号生成函数查找:

9. 从je short 004025E5处往前查看,它的前几条语句都没有能够改变ZF的值,继续往前发现有一个带有cmp的函数,那么下意识怀疑它是一个字符串比较函数,上网对该函数进行搜索,果然是一个字符串比较函数,那么它就极可能是进行序列号判断的函数,对它下断,:

在这里插入图片描述
10. 发现好多可疑信息,不要激动,一步一步来;入栈的eax应该是正确的序列号为 “AKA-1853138“ ,至于这个序列号怎么来的,我们从00402510开始分析,因为此处为有一个跳转,往往是一个新的逻辑开始的地方,下端后F7单步调试,查看堆栈,发现 [ebp-1C] 为序列号的数字 “1853138“[ebp-18] 为用户输入的序列号”333333333333333“

在这里插入图片描述
11. 继续进行分析,发现一个库函数调用 vbaStrCat,搜索后发现该函数为字符拼接函数,在 00402523处对该函数进行间接调用(利用edi),其中的参数有一个固定字符串(00401B70内存中)“AKA-“ecx (在00402513处进行了赋值,为序列号中间的数字”1853138“),此时该函数的返回值存放在eax中,其中 ”AKA-1853138“ 这就是我们的正确序列号。

在这里插入图片描述
12. 所以我们的序列号是由固定字符串“AKA-“和”1853138“拼接而来;那么”1833138“又是怎么得到的呢?我们继续往前看,刚刚说过,带有跳转的部分极有可能是新的逻辑开始的地方,这次我们从 004024DD开始分析,进行 F8调试;因为在上面的分析中我们发现字符串”1853138“字符串是保存在 [ebp-1C] 中的,我们在内存中查找 EBP-1C,在调试的时候需要对该内存进行观察。进行调试后发现,在执行到 004024FA处该内存内容发生了变化,变成了”1853138“,而次地址的前面正好是一个函数调用,那么真相只有一个:该字符串是由这个函数生成的

在这里插入图片描述
13. 然后我们需要对该函数进行分析,跟踪后会发现,完全迷失了自我;冷静一番后有了以下思路进行函数回溯:(大神如果知道别的更快的方法请一定要告诉我)

  • 1) 单步调试F7进入该函数
  • 2) 该函数中一直进行F8,一边查看堆栈中是否出现相关的字符串,如果在一个函数调用后出现,则在该处下断;
  • 3) 然后重复继续进行步骤2和步骤1;直到在最终发现目标字符串。

14. 序列号首次出现在栈中是在 00402456处:

在这里插入图片描述
15. 字符串保存在 eax中,则在前面找一处断点单步执行,继续观察 eax的值;发现在 0040243F处的函数调用返回值就算序列号的中间值(此处为“1853138“),也就是说该函数为序列号产生的最后一步,接下来我们需要理清整个序列号产生算法的逻辑。

在这里插入图片描述
16. 我们从 00402409开始分析,至于为什么从这里开始分析,一方面00402409是有一个跳转语句进行跳转的,那么从它开始很大程度上就是一个新的逻辑开始的地方;另一方面,在用F7进行单步调试时,在 0040240F处发现用户输入的用户名出现,而用户名在栈中的地址正好是 [ebp-1C]

17. 从 00402409开始分析:查看 [ebp-B0],并不知道它是什么,先不管他,继续往下:

[ebp-B0]内容
18. 在 00402415处有一处函数调用 MSVBVN50.__vbaLenBstr(),其中用户的输入(被传入eax)和[ebp-B0](被传入ebx)作为该函数的参数参与计算,上网搜索该函数为函数,该函数的作用是计算字符串的长度。

19. 继续往下执行,得到输入用户名的长度,被保存在eax中(此处为0x13,数值为19)

在这里插入图片描述
20. 继续往下执行,出现 [ebp-18],进行堆栈查看,还是存放的还是用户输入的用户名"1111111111111111111"

在这里插入图片描述
21. 继续执行,进行乘法运算:edi=edi*17CFB,刚刚 edi 存放的是字符串的长度(此处为0x13,数值为19),则此时的 edi 的数据为 ”001C46A1”

在这里插入图片描述
22. 继续执行,将ecx入栈(此时的ecx还是用户是输入用户名“1111111111111“)做下一个函数的参数,然后是一个溢出跳转指令 jo 004026BE,应该是针对刚刚的 edi 乘法进行检查;接下来是一个函数调用,该函数的作用的计算输入参数的 首字符ASCII值

在这里插入图片描述
23. 因为我们这里没有溢出,所以先不考虑溢出的部分;继续往下执行,用户名的首字符为“1“,ASCII值为”31“,所以eax的值是 0x00000031

在这里插入图片描述
24. 继续往下执行,edx=0x00000031,(只取了eax的ax), edi=edi+edx=001C46A1+00000031=001C46D2, 然后进行溢出检查(此处不存在,先不进行考虑),将 edi 入栈作为参数传递给 vabStrI4函数,该函数的作用是 将16进制转换成10进制

在这里插入图片描述
16进制转10进制:

在这里插入图片描述
25. 到此,整个序列号生成函数的逻辑就分析完了,整个序列号生成函数的逻辑如下:

  • 1) 先进行用户输入字符串的长度计算
  • 2) 然后用长度*0x17CFB (会进行溢出检查)得到M
  • 3) 然后取用户输入字符串首字符ASCII码值N
  • 4) 然后将上面计算的M+N得到S
  • 5) 再将S由16进制转换成10进制即可得到序列号中间的序号值

猜你喜欢

转载自blog.csdn.net/weixin_39561364/article/details/108116942