Jirairya

CrackMe2


熟悉VB语言编写的程序。

VB文件

VB专用引擎

VB文件使用名为MSVBVM60.dll的VB专用引擎。 例如,显示消息框时,VB代码中要调用MsgBox()函数。但VB编辑器真正调用的是MSVBVM60.dll里的rtcMsgBox()函数,在该函数内部通过调用user32.dll里的MessageBoxW()函数(Win32API)来工作。(也可在VB代码中直接调用user32.dll

本地代码和伪代码

根据使用的编译选项不同,VB文件可以通过编译为本地代码与伪代码。本地代码一般用于调试器解析的IA-32指令;而伪代码是一种解释器语言,它是由VB引擎实现虚拟机并可自解析的指令(字节码)。

事件处理程序

VB主要用于写GUI程序,IDE用户界面本身最适合于GUI编程。由于VB程序采用Windows操作系统的事件驱动方式工作,所以在main()或WinMain()中并不存在用户代码,用户代码存在于各个事件处理程序之中。

未文档化的结构体

VB中使用的各种信息(Dialog、Control、Form、Module、Function等)以结构体形式保存在文件内部。

###例子

EP.png 程序执行后,在EP代码中首先要做的是调用VB引擎的主函数(ThunRTMain())

00401232   FF25 A0104000 jmp dword ptr ds:[0x4010A0]  ;msvbvm60.ThunRTMain
00401238   68 141E4000   push 0x401E14                ;EP
0040123D   E8 F0FFFFFF   call 00401232                ;<jmp.&MSVBVM60.#100>

EP地址为00401238,401238地址处的PUSH 401E14命令用来把RT_MainStruct结构体的地址(401E14)压入栈。然后将40123D地址处的CALL 00401232命令调用401232地址处的JMP DWORD PTR DS:[4010A0]指令。该JMP指令会跳到VB引擎的主函数ThunRTMain()( 前面压入栈的401E14的值作为ThunRTMain()的参数)

40123D地址处的CALL 401232命令用于调用ThunRTMain()函数,这里使用了较为特别的技法。不是直接转到MSVBVM60.dll里的ThunRTMain()函数,而是通过中间401232地址处的JMP命令跳转。这是VC++和VB的编译器常用的间接调用法。

RT_MainStruct结构体是ThunRTMain()函数的参数。RT_MainStruct结构体的成员是其他结构体的地址。VB引擎通过参数传递过来的RT_MainStruct结构体获取程序运行所需的所有信息。

运行程序

0x01 先运行程序,输入测试字符串测试运行效果。然后OD载入程序

![CrackMe2运行画面.png/img/reversecore_assets/assets_CrackMe2/CrackMe2运行画面.png)

CrackMe2运行测试画面.png

用户代码在点击check按钮时触发的事件处理程序内。

分析CM

0x02 右键打开字符串查找,错误消息弹窗的字符串,然后点击地址进入反汇编代码处.

查找字符串.png

0x03 查看反汇编代码,及分析之前对话框的运行效果可知,该程序是通过某种算法生成字符串序列号,然后将用户输入的字符串序列号与算法生成的序列号作比较。

条件转移指令.png

调用403329地址处的__vbaVarTstEq()函数,比较(TEST命令)返回值(EAX),由403332地址处的条件转移指令(JE指令)决定执行“真”“假”。

0x04 403329地址处的__vbaVarTstEq()函数为字符串比较函数,其上方的2个PUSH指令为比较函数,比较字符串

栈内存.png

403321地址处的SS:[EBP-44]表达的是栈内地址,恰好又是函数中声明的局部对象的地址(局部对象存储在栈内。)

通过403329当前的EBP值,算出403327403328地址处EDX和EAX的内存地址为0012F4580012F468.

0x05 在OD的右下角的栈区,找到EAX和EDX的地址,看到实际的字符串(VB使用Unicode字符串),然后右键复制到记事本,粘贴到程序测试

运行成功.png

分析算法

通过以上分析可知,该程序是一个“以Name字符串为基础随时生成Serial”的算法。

生成序列号的方法

若是Win32API程序,有以下特点:

  • 读取Name字符串(使用GetWindowsText、GetDlgItemText等API)
  • 启动循环,对字符加密(XOR、ADD、SUB等)

VB引擎函数也有上述特点。程序事件处理程序的起始代码开始调试,查找到读取Name字符串的部分后,紧接着就会出现加密循环。

经分析该程序加密方法如下:

  1. 从给定的Name字符串前端逐一读取字符(共4次)
  2. 将字符串转换为数字(ASCII代码)
  3. 向变换后的数字加64
  4. 再次将数字转换为字符
  5. 连接变换后的字符

查看栈内存:在OD的Dump窗口使用移动命令(Ctrl+G)。或者在栈窗口,右键选择“Follow in dump”项。又或者在反汇编代码窗口的地址处右键“Follow in dump-Memory Address”


上一篇 栈帧

下一篇 Tureverseme1

Comments

Content