house of pig plus

[TOC] 参考博客 当题目中限制了system函数的调用,可以使用此方法进行orw,但是这个方法的前提还是有hook可打

特别之处

  • IO_str_overflow中一个特别之处 mov rdx,QWORD PTR [rdi+0x28]这条汇编指令,此时的rdi恰好指向我们伪造的IO_FILE_plus的头部,使得可以进行rdx的设置,进而可以使用setcontent函数进行srop
  0x7ffff7e6eb20 <__GI__IO_str_overflow>:    repz nop edx
   0x7ffff7e6eb24 <__GI__IO_str_overflow+4>:    push   r15
   0x7ffff7e6eb26 <__GI__IO_str_overflow+6>:    push   r14
   0x7ffff7e6eb28 <__GI__IO_str_overflow+8>:    push   r13
   0x7ffff7e6eb2a <__GI__IO_str_overflow+10>:    push   r12
   0x7ffff7e6eb2c <__GI__IO_str_overflow+12>:    push   rbp
   0x7ffff7e6eb2d <__GI__IO_str_overflow+13>:    mov    ebp,esi
   0x7ffff7e6eb2f <__GI__IO_str_overflow+15>:    push   rbx
   0x7ffff7e6eb30 <__GI__IO_str_overflow+16>:    sub    rsp,0x28
   0x7ffff7e6eb34 <__GI__IO_str_overflow+20>:    mov    eax,DWORD PTR [rdi]
   0x7ffff7e6eb36 <__GI__IO_str_overflow+22>:    test   al,0x8
   0x7ffff7e6eb38 <__GI__IO_str_overflow+24>:    jne    0x7ffff7e6eca0 <__GI__IO_str_overflow+384>
   0x7ffff7e6eb3e <__GI__IO_str_overflow+30>:    mov    edx,eax
   0x7ffff7e6eb40 <__GI__IO_str_overflow+32>:    mov    rbx,rdi
   0x7ffff7e6eb43 <__GI__IO_str_overflow+35>:    and    edx,0xc00
   0x7ffff7e6eb49 <__GI__IO_str_overflow+41>:    cmp    edx,0x400
   0x7ffff7e6eb4f <__GI__IO_str_overflow+47>:    je     0x7ffff7e6ec80 <__GI__IO_str_overflow+352>
   0x7ffff7e6eb55 <__GI__IO_str_overflow+53>:    mov    rdx,QWORD PTR [rdi+0x28]  <----
   0x7ffff7e6eb59 <__GI__IO_str_overflow+57>:    mov    r14,QWORD PTR [rbx+0x38]
   0x7ffff7e6eb5d <__GI__IO_str_overflow+61>:    mov    r12,QWORD PTR [rbx+0x40]
   0x7ffff7e6eb61 <__GI__IO_str_overflow+65>:    xor    ecx,ecx
   0x7ffff7e6eb63 <__GI__IO_str_overflow+67>:    mov    rsi,rdx
   0x7ffff7e6eb66 <__GI__IO_str_overflow+70>:    sub    r12,r14
   0x7ffff7e6eb69 <__GI__IO_str_overflow+73>:    cmp    ebp,0xffffffff
   0x7ffff7e6eb6c <__GI__IO_str_overflow+76>:    sete   cl
   0x7ffff7e6eb6f <__GI__IO_str_overflow+79>:    sub    rsi,QWORD PTR [rbx+0x20]
   0x7ffff7e6eb73 <__GI__IO_str_overflow+83>:    add    rcx,r12
   0x7ffff7e6eb76 <__GI__IO_str_overflow+86>:    cmp    rcx,rsi
   0x7ffff7e6eb79 <__GI__IO_str_overflow+89>:    ja     0x7ffff7e6ec4a <__GI__IO_str_overflow+298>
   0x7ffff7e6eb7f <__GI__IO_str_overflow+95>:    test   al,0x1
   0x7ffff7e6eb81 <__GI__IO_str_overflow+97>:    jne    0x7ffff7e6ecc0 <__GI__IO_str_overflow+416>
   0x7ffff7e6eb87 <__GI__IO_str_overflow+103>:    lea    r15,[r12+r12*1+0x64]

具体做法

  1. 使用largebin attrack劫持stderr->_chain字段为一个堆地址ck0
  2. 使用largebin attrack劫持global_max_fast或者tls中管理tcache的部分为堆地址ck1,这是为了malloc从tcache中取得malloc_hook,以及随便取一个chunk触发malloc hook
  3. edit(ck1)使得0xa0 对应的tcache中为malloc_hook,0xb0对应的chunk为任意一个堆地址
  4. mov rdx,QWORD PTR [rdi+0x28],rdi=FAKE FILE头部(注意FAKE FILE前0x10无法管理,但是不影响)。edit(ck0)设置FAKE FILE+0x28的值为fake frame的底部;合理地设置fp->_IO_write_ptr,fp->_IO_write_base,fp->_IO_buf_base=一个堆地址(该堆地址的内容应该是setcontent+61),fp->_IO_buf_end;chain=ck2;vtable=IO_str_overflow;这样IO_str_overflow时malloc hook被设置为setcontent+61,rdx=fake frame底部,同时遍历下一个FILE ck2
  5. edit(ck2)使得其执行IO_str_overflow时可以malloc出一个0xb0的chunk
  6. edit(ck3)为一个orw
  7. 执行exit(0),第一个IO_str_overflow可以让malloc hook被设置为setcontent+61,rdx=fake frame底部,第二个IO_str_overflow调用了malloc函数执行srop,让rsp=ck3的mem,rip=ret,srop结束后执行orw