(reversingwithlena)Lena crackme tutorial 02笔记

相关链接:tutorial下载

一、本篇内容概要

  • 简单介绍了10进制、2进制、16进制
  • 介绍了 ASCII 码
  • 介绍了 CreateFileA() & ReadFile() API
  • 探索了 reverseMe.exe

主要的东西都写在第二页啦,别忘了看看 P2 aヾ(o・ω・)ノ

二、reverseMe.exe

1、在 OllyDbg 中打开 reverseMe.exe

按 F8 执行,先大致过一下

注意到 00401073 处的 CreatFileA() API,我们知道它需要打开一个“Keyfile.dat”的文件,如果打开失败就会返回 FFFFFFFF(即-1)。

下一条指令 cmp eax(存放返回值),-0x1 就会将 ZF 置为 1,之后的 jnz 跳转就不会执行,紧接着就会执行 badboy 窗口,最后关闭程序

所以我们需要创建一个“Keyfile.dat”文件

2、在同一个路径下新建“Keyfile.dat”文件

用记事本创建

不用关闭记事本,我们等会还要用到。既然有了这个文件,那么我们回到 reverseMe.exe 看看它要做什么吧

3、回到 reverseMe.exe

Ctrl+F2 重新打开 reverseMe.exe,在 CreatFileA() 设置断点,按 F9 执行

按 F8 ,我们看到 CreatFile() 成功返回了文件句柄(EAX==88, 每个环境打开文件的句柄可能不同,无所谓)

跳转实现,我们跳过了第一个 Badboy

继续 F8 执行,遇到 ReadFIle()

4、ReadFile()

可以看到 hFile(输入参数) = 88 (就是刚刚 CreateFile()返回的文件句柄)

Buffer (输入参数)的类型是 lpBuffer,指向读取文件数据存储的内存缓冲区。在这里,读取的数据会存放在 0040211A 起始的内存段中

BytesToRead (输入参数)指明需要从文件中读出的数据大小。在这里是 46h(70d)

pBytesRead (输出参数)指向存储实际读出的数据大小的 DOWRD 变量。在读文件时,可能由于已经达到文件结尾等原因,其值可能小于 BytesToRead。

pOverlapped(输入参数),指向 OVERLAPPED 结构体的指针,这里是 NULL,不用考虑

我们知道她要读少于 46h Bytes的内容,并将这些数据存储在 0040211A 中

不管数据是多少,只要 ReadFile() 读了,就会返回 1,然后跳转

在这之后我们遇到两个 xor , xor 两个相同的寄存器的作用是将这个寄存器清零,这么做是有目的的,说明之后的指令会用到 EBX 和 ESI 这两个寄存器。

我们继续按 F8 ,来到后面的 cmp 指令

我们看到她在拿 402173 处的 DOWRD 数据跟 10h 进行比较。

而这个 402173 正好是 ReadFile() 函数中的 pBytesRead 的地址,用于存放实际读出的数据大小

紧接着是 jl 指令,如果实际读出的数据大小 小于 10h,那么就会跳转到另一个 Badboy

我们知道了文件中需要至少 10h Bytes 的数据,但是我们还不知道这些数据应该是什么,我们可以通过直接修改 SF 中的值(将其改为0)来阻止跳转到 Badboy

5、循环

用这个红色的箭头我们看到这是一个循环语句,但是这是一个 jmp ,没有条件。所以怎么才能跳出这个循环呢?

我们看到这条 je 指令可以跳出循环,接着往上看

这个循环将 40211A 中的一个 byte mov 到 al 中,然后将 al 和 0 比较,如果 al == 0,那么就会跳出循环。

40211A 存放着刚刚用 ReadFile() 读出的数据,所以这个循环就是把之前文件中读出的数据一位一位地拿出来跟 0 比,如果不为 0 则进入循环体, 如果为 0 则退出循环。

我们先看看退出循环要干嘛:

先是 cmp esi,0x8

然后如果 esi 小于 8,就会执行 jl 指令,跳转(往下拉我们可以看到她跳转到又一个 Badboy)

我们再看一下这之后的 jmp 指令,她跳转到一个 Goodboy!

我们很明确这个循环要干什么了,我们需要将 esi 变成大于等于 8 的值,然后读一个 0 ,退出循环,然后跳转到 Goodboy, 最后退出程序

再来看一下循环体

循环体中先将 al 跟 47h 比较,如果相等 ZF 就会等于1

然后 jnz 就不会跳转

esi 和 ebx 都会加1

如果 al 和 47h 不相等就会跳转,esi 值不变, ebx+1

再看一眼循环之前的 mov 语句,知道为什么是每次读取下一个字符了吧XD

那么,47h 是什么呢,47h 就是 “G” 的 ASCII 码,嘻嘻

总结一下:我们需要读取 8 个以上的 “G”,总的长度应该 大于 10h(16)个字符,最后一个字符要是 ASCII 码为 0 字符,就是C语言中的 ‘\0’ ,其实就是文件的结尾啦。

6、创建key

我们按照刚刚的规则随意创建一段 key,用记事本保存

我随便敲了一串,这里面肯定有超过 8 个 G ,总共肯定有 16 个以上的字符

保存,然后运行!

成功!

建议在用 OllyDbg 跑一下,过一下过程

PS:以后坚持一个星期看 5 篇以上 Lena 的视频,然后当天写笔记。写辣么认真,希望以后有人看啦(/ω\)(/ω\)(/ω\)

说点什么

avatar

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

  Subscribe  
提醒