xiaoyu2032 发表于 2022-5-15 13:19

练习笔记之160Crackme-014

# 160CM-014

  今天才发现之前的帖子好像发错了版块,以后都发这里了。
  先运行看一下,这是一道序列号验证题,输入错误有弹窗提示。PE看一下,无壳,VB。


## 1.爆破

  这道题爆破比较简单,无论是字符串搜索,还是弹窗下断,都能找到关键函数和关键跳转位置,当然用VB Decompiler的话就更简单了,具体过程就不详述了。爆破代码如下:

``` asm
00403704   /0F85 1A030000 jnz bjanes_1.00403A24
                jnz修改为nop
00403787   /0F8F 17030000 jg bjanes_1.00403AA4
                jg修改为jl
```

## 2.算法

  先用VB Decompiler反编译一下,找到按钮事件响应函数,代码如下:

``` VB
Private Sub Command1_Click() '403620
loc_004036BB: var_1C = CrackmeV20a.Text1.Text
loc_00403704: If (Len(var_1C) <> 9) <> 0 Then GoTo loc_00403A24
loc_00403727: var_1C = CrackmeV20a.Text1.Text
loc_00403787: If var_18 > Len(var_1C) Then GoTo loc_00403AA4
loc_004037AA: var_1C = CrackmeV20a.Text1.Text
loc_004037E5: var_24 = CrackmeV20a.Text1.Text
loc_004038AD: If ((Asc(Mid$(var_24, vbNull, 1)) > 57) And (Asc(Mid$(var_1C, vbNull, 1)) < 48)) <> 0 Then GoTo loc_00403A22
loc_004038D3: var_1C = CrackmeV20a.Text1.Text
loc_00403909: var_58 = var_18 xor 0002h
loc_0040391B: var_28 = Str$(2)
loc_00403942: var_8028 = Asc(Mid$(var_1C, vbNull, 1))
loc_0040394B: var_48 = var_8028
loc_004039A5: var_80 = Right(0, 1)    'Right函数的第一个参数0识别错误
loc_00403A04: If ((Str$(var_8028) - 48) <> var_80) <> 0 Then GoTo loc_00403A22
loc_00403A18: var_18 = 1+var_18
loc_00403A1D: GoTo loc_0040377C
loc_00403A22: ' Referenced from: 004038AD
loc_00403A24: ' Referenced from: 00403704
loc_00403A8C: MsgBox("Sorry, try again!", 0, "Wrong serial!", 10, 10)
loc_00403AA2: GoTo loc_00403B22
loc_00403AA4: ' Referenced from: 00403787
loc_00403B0C: MsgBox("Good job, tell me how you do that!", 0, "Correct serial!", 10, 10)
loc_00403B22: ' Referenced from: 00403AA2
loc_00403B36: GoTo loc_00403B87
loc_00403B86: Exit Sub
loc_00403B87: ' Referenced from: 00403B36
End Sub
```

  初步分析上述代码,会发现`var_80 = Right(0, 1)`这行代码的第一个参数有问题,这个是软件反编译时参数识别不准确导致的。去掉“程序分析器和优化器”选项后重新编译,可以得到更详细一些的代码。根据前面了解的VB Variant(变量体数据类型)的特点,`var_28 = 0`这行代码实际上是更改变量表示的数据类型,而不是将其值赋零。而且还应该注意的是,如果`ebp-0x60`是变量体的指针地址,则`ebp-0x58`才是其实际数值,因此VB Decompiler反编译后的代码中var_60和var_58表示的实际上是同一个变量。因此从这些代码中,我们可以看出right函数的第一个参数实际上应该是`Str$(var_18 xor 02h)`。

  除了`Right()`函数的参数外,`Mid$()`函数的第二个参数实际上也识别错了,vbNull的执行效果相当于从第一个字符开始,按这个参数计算出来的注册码是通不过的。这个只能在OD中跟踪一下来确认了,通过跟踪我们发现在403803位置将var_18赋值给了edi,而edi是后续调用的`Mid$()`函数的第二个参数。

  将代码进行适当整理后,我们得到验证算法的过程如下:

``` VB
Private Sub Command1_Click() '403620
      code = CrackmeV20a.Text1.Text
      If (Len(code) <> 9) Then GoTo loc_00403A24 '长度不等于9跳转
loc_0040377C:'While循环
      If i > Len(code) Then GoTo loc_00403AA4 '循环退出条件
      If ((Asc(Mid$(code, i, 1)) > 57) And (Asc(Mid$(code, i, 1)) < 48)) Then GoTo loc_00403A22 '字符的ASCII码在48~57之间,即只能是数字0~9
      var_58 = i Xor 2      '异或运算
      code_i = Asc(Mid$(code, i, 1))   '取字符的ASCII码
      var_80 = Right(Str$(var_58), 1)       '取数字的个位数
      If ((Str$(code_i) - 48) <> var_80) Then GoTo loc_00403A22 '数字的ASCII码值-48(0的ASCII码值)和var_80比较,等于数字var_80
      i = 1 + i
      GoTo loc_0040377C
loc_00403A22:
loc_00403A24:
      MsgBox("Sorry, try again!", 0, "Wrong serial!")
      GoTo loc_00403B22
loc_00403AA4:
      MsgBox("Good job, tell me how you do that!", 0, "Correct serial!")
loc_00403B22:
      GoTo loc_00403B87
      Exit Sub
loc_00403B87:
End Sub
```

  根据代码我们可以看出,注册码需要满足的条件如下:

1. 注册码长度必须为9;
2. 注册码必须全不是数字;
3. 第一个注册码比零要大3(1 xor 2)……

  编写注册码计算程序如下:

``` Cpp
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>

int _tmain(int argc, _TCHAR* argv[])
{
    int i,j,m;
    printf("注册码为:");
    for (i=1;i<10;i++)
    {
      m=(i^2)%10;
      printf("%d",m);
    }
    printf("\n");
    system("pause");
    return 0;
}
```

  最终验证结果如下:


## 2.总结

- 前面已经多次提到过VB Decompiler反汇编的代码不准确的问题,这道题里面出现的错误更严重,只有查看汇编代码才能修正过来。
- 这道题在403783位置处的判断条件`var_18 > Len(var_1C)`分析汇编代码的时候比较容易被误导,因为后面有个往回跳的大跳转,没注意到的话很容易认为这个条件永远不会满足。而查看VB Decompiler的反汇编代码就很容易看出来。
- 注意Variant变量的特点,反汇编代码中var_58和var_60有时表示同一个意思,有时又不同,需要注意理解。

hebut022 发表于 2022-5-15 14:04

学习一下,,,,

wuyongkui 发表于 2022-5-15 17:24

感谢楼主分享,学习一下

hackerbob 发表于 2022-5-15 18:45

厉害厉害。。。。。{:301_997:}

sikuai 发表于 2022-5-15 18:54

感谢楼主分享,学习一下

戰龍在野 发表于 2022-5-15 19:26

谢谢你的坚持学习学习

montella 发表于 2022-5-15 19:41

谢谢up主,学习中

wskydfcu 发表于 2022-5-15 21:25

我来看看

ysysc 发表于 2022-5-16 01:26

感谢分享,谢谢谢谢谢谢。

zhuzaiyu 发表于 2022-5-16 01:52

感谢分享,不明觉厉
页: [1] 2 3 4
查看完整版本: 练习笔记之160Crackme-014