真的很 simple,我还做了很久,。。。


此题来自 : pwnable.kr

代码:
1

很简单的代码,接收一个长度 30 之内的字符串进行 base64decode ,再判断长度是否大于 0xC,然后进入 auth 函数。

这里可以注意一下第 21 行,将输入的字符串 base64解码后的字符串(v4)复制到全局变量 input 中。

看看 auth 函数:

2

也很简单,把 input 取出来,md5,然后输出 md5,然后和 f87cd... 比较是否相等。

最后回到 main 函数第 22 行,如果相等那么就进入 correct 函数。

3

这里判断了 input 是否为 -559038737,难道让我们输入的是这个吗?

怎么可能。。。把这个数字去 md5 加密一下就知道不对了。

过程

一开始没仔细看 correct 函数,以为进入就直接获得 shell 了,所以在纠结能否直接通过 auth,为此我还去尝试解密 f87cd601aa7fedca99018a8be88eda34 这个。。无果。。。

那么我就在想会不会是哪里溢出了呢。。但是 main 函数里字符限制的都很好,于是我再一次进入了 auth 函数。

然后很理所当然的注意到:

4

v4 长度是 8 ,但是 前面提到过 input 的长度是 0xC,即 12,所以刚好可以覆盖到上一层的 ebp

bingo,于是我们想到了:

1
2
3
4
5
6
7
8
1. 在 `auth` 函数覆盖上层函数 `ebp`,假设为 `fake_ebp`
2. `auth` 退出后 `ebp` 为 `fake_ebp`
3. 回到 `main` 函数也不会执行什么代码就退出了,此时执行:
`leave`
`ret`
这两行代码很熟悉了,说白了就是:
`leave = mov esp,ebp;pop ebp;`
`ret = pop eip`

但是不要忘了,在 auth 函数退出时也执行了 leave ; ret

所以是执行了两次,所以我们还要找一个可以控制的地方,那么这个地方很显然只有一个 input 了。于是:

1
paylaod = 'a'*4 + getshell_addr + input_addr

这里的 getshell_addrcorrect 函数里 system('/bin/sh') 那一行。

这样在第一次执行完 leave ; ret 后 ebp 就指向了 input 的地址(’aaaa’ 的地方),然后第二次执行的时候:

1
2
leave = mov esp,ebp(aaaa 的位置) ; pop ebp (此处可以无视 `ebp`,但是 `esp+4` 了,所以 `esp` 指向了 `getshell_addr` 的位置 )
ret = mov eip,esp(此时指向了 `getshell_addr` 的位置了。)

ok,到这里分析完了。。。

然而我第一次的 payload 尽然是:'a'*8 + getshell_addr-4

还久久的没反应过来,调试了才发现的。哎,打扰了。。