漏洞是在输入密码那里有个buffer overflow,长度够长能够一直覆盖掉下面的一些vm里面执行的代码。get_pass里头有个函数,是读取bss上的部分伪代码,根据伪代码来进行一些写入操作。我们姑且把这个函数叫做vm。

难点一在于逆向vm函数,弄懂其中的逻辑。行为表如下。

  1. heap1 = 0x57010
  2. heap2 = 0x57030
  3. case: '1' : --*heap2;
  4. case: 'L' : ++*heap2;
  5. case: 'N' : *heap2 = *heap1
  6. case: 'a' : --*heap1;
  7. case: 'h' : ++input
  8. case: 'm' : ++*input
  9. case: 'o' : --input
  10. case: 'r' : ++*heap1
  11. case: 'u' : --*input
  12. case: [] : input ? execute: skip
  13. case: {} : heap2 ? execute: skip

还有一个地方卡了很久,因为开了PIE,一直找不到地址的泄露。后来发现remove那里也是有double free,heap上面有一个chunk是保存了可执行代码段的地址的。只要
remove(0);remove(2);remove(0)
就能够泄露出可执行段的地址,然后通过logout进入vm函数,overflow改掉vm操作的基地址,接下来就可以通过伪代码去网可执行段里面写shellcode了。

因为长度限制,这里分开了两次操作把shellcode写入段中,最后通过buy操作即可触发shellcode。

Run.py

  1. from pwn import *
  2. LSHIFT = 'o' # --i
  3. RSHIFT = 'h' # ++i
  4. INC = 'm' # ++ (*i)
  5. DEC = 'u' # -- (*i)
  6. context.arch='amd64'
  7. password = '\x86\x13\x81\tb\xffD\xd3?\xcd\x19\xb0\xfb\x88\xfd\xae \xdf' + '\x00'*85
  8. context.log_level = 'debug'
  9. # p = process('./beep