天天看点

buuoj刷题记录 - roarctf_2019_easy_pwn

检查一下保护:

buuoj刷题记录 - roarctf_2019_easy_pwn

拖进IDA分析程序:

问题处在write函数中,

buuoj刷题记录 - roarctf_2019_easy_pwn
buuoj刷题记录 - roarctf_2019_easy_pwn

最后可以溢出一个字节.

思路:溢出一个字节覆盖下一个chunk的prev in use标记位.然后向前合并,构造重叠chunk。

下面是我的构造方法:

  1. create三个这样的chunk
    buuoj刷题记录 - roarctf_2019_easy_pwn
  2. free掉0 ,然后利用chunk1 覆盖掉chunk2的prev in use 标记位.同时在chunk1内布置好prev size.(glibc-2.23不会通过prev size 找到chunk ,然后比较前一个chunk的size,所以我们只需要修改chunk2的prev size就可以了)
  3. 接着free掉chunk2,此时这个大chunk就都到了unsorted bin里面了.但是此时我们还是可以访问chunk1里面的内容.

    (注意在创建三个chunk的时候再往后面加一个,防止合并到top chunk)

  4. 在unsorted bin里面划分出几块内存(大小自己决定,保证之后能改掉chunk1的内容),使unsorted chunk向后移动,直到fd和bk指针落在chunk1内,这样我们就能通过chunk1把fd和bk打出来了.
  5. free掉chunk1,利用刚才划分的chunk改写chunk1的fd指针到malloc_hook附近.

6.连续malloc两次,分配到malloc_hook附近,写malloc_hook

最后比较坑的地方是one_gadget 一个也不能用.原因是rsp 不满足条件.

学习了一下大佬们的做法:

把malloc_hook改为realloc函数内sub rsp 的地址来调整rsp,

buuoj刷题记录 - roarctf_2019_easy_pwn

之后realloc会立刻检查realloc_hook,然后决定是否执行realloc_hook

只需要把realloc_hook改为one_gadget即可.

(realloc_hook就在malloc_hook的前面)

虽然sub rsp调整的rsp的位置,但是由于栈内的数据不会被置0,也就是说sub了之后,里面的数据还是随机的,并不一定能满足one_gadget的rsp 条件.

最后执行流程就是:

malloc_hook -> sub rsp -> realloc_hook -> one_gadget

成功getshell

buuoj刷题记录 - roarctf_2019_easy_pwn

继续阅读