【总结笔记】pwn
参考
- ctfshow pwn入门 1-53
通用操作
chmod 777 pwn |
ida
快捷键
- “Segments”(段)窗口:Shift + F7
- 看got一系列表地址
函数
strcmp
| 返回值 | 含义 | 说明 |
|---|---|---|
| 0 | 相等 | 两个字符串完全相同 |
| > 0 | str1 > str2 | 第一个不匹配字符在 str1 中的值大于 str2 |
| < 0 | str1 < str2 | 第一个不匹配字符在 str1 中的值小于 str2 |
puts
- 输出数组直到遇到
\0 - 寻找方向是从内存低地址到高地址,在ida中显示为向下
gets(s)
- 从标准输入读取字符串到s
- 不检查边界:gets() 不管 s 指向的缓冲区有多大,都会一直读取直到遇到换行符 \n
- 如果输入超过缓冲区大小,会覆盖栈上的其他数据(包括返回地址)
动态/静态编译判断:
- ida
- shift+F11
- imports 超多 libc 函数 → 动态
- imports 几乎为空 → 静态
- file
- statically linked:静态
- dynamically linked + interpreter /lib/ld-linux.so.2:动态
- checksec(本质上是通过一些检测机制来判断是否存在某种保护,这个检测机制有些时候是会有误报的)
动态
RWX
- Has RWX segments
- 二进制文件中存在至少一个段(通常是代码段),它同时拥有读、写、执行权限
NX
NX enabled
- NX(或 DEP,Data Execution Prevention)将数据区域(如栈、堆)标记为不可执行,防止攻击者将 shellcode 写入栈/堆后直接跳转执行
- NX→一定找pop_rdi/ret:
ROPgadget --binary "pwn" --only "pop|ret" |
- 动态找写入点:
gdb pwn |
- 动态,开启NX保护,部分开启RELRO保护
ret2libc:例题1;例题2;例题3 - 动态 + 静态栈保护函数
爆破canary值绕过栈保护函数memcmp()
Stack
No canary found
- 没有栈溢出保护
- 后门函数
32位后门函数
32位后门函数指定参数 + NX + Partial RELRO
64位后门函数 - 有system()和/bin/sh
32位
64位 - 有system()和/sh:处理方式和/bin/sh一样
- 只有system()
32位
64位 - 无system()和/bin/sh
32位 + NX + Partial RELRO
64位
canary found
- 看下是不是伪保护
import subprocess |
RELRO
当RELRO为Partial RELRO时,表示.got不可写而.got.plt可写。 |
.got.plt
- 在同一次进程生命周期里,同一个共享库函数的加载地址是固定的;
- 进程一重启,地址就可能换地方——这就是 ASLR(地址空间布局随机化)在起作用
- .got.plt 里的值是绝对地址(64 位下 8 字节指针),不是相对偏移。它在运行过程中会变——从 0 → 第一次解析后变成真实函数地址。
- GOT专门为PLT准备的节
- .plt 本身代码段只读,只是无条件 jmp *.got.plt[n];
- 如果 .got.plt[n] 还没填好,那个 jmp 就会落到一段“解析”代码里,由动态链接器负责把地址填上。
PIE
- no pie:基址固定
静态
mprotect函数
- NX + Partial RELRO
- 找pop寄存器
ROPgadget --binary pwn --only "pop|ret" | grep "pop edi ; pop esi ; pop ebx ; ret" |
零碎知识点
shell
- 在大多数 Unix 或类 Unix 系统中,/bin/sh 是默认的 shell 解释器
重定向&&文件描述符
- 通过重定向符>&0可以将命令的输出从默认的 stdout(文件描述符 1)重定向到标准输入 0。
- 终端设备的双向性:
- 在终端环境中,文件描述符 0(标准输入)、1(标准输出)、2(标准错误)均指向同一个终端设备。虽然 stdout 被关闭,但终端设备本身支持读写,因此通过 >&0 将输出写入文件描述符 0 时,仍能显示在终端上。
- 此时输入ls >&0可以展开所有的目录文件
- cat c* >&0:匹配所有以 c 开头的文件(如 catflag),将其内容输出到终端,于是ctfshow答案直接被显示出来了
gcc
- 把各种文件编译成可执行文件
# .c |
ida操作
- 取消定义(Undefine) :
- 按下键盘上的 U 键。
- 这会把当前定义的数据“炸碎”,变成一堆原始的字节(通常显示为 db 且只有单个字节)。
- 重新定义为双字(Make Dword) :
- 确保光标还在 080490E8 这个起始位置。
- 按下键盘上的 D 键。
- 按第一次,它可能变成 db (byte)。
- 按第二次,变成 dw (word)。
- 按第三次 ,它就会变成 dd (dword) 。
此时,原本显示的 ‘Welc’ 就会变成十六进制数值 636C6557h
- 重新回到 ‘Welc’:A
汇编知识点
dd/db
- dd (Define Double-word):把 4 个字节当作“一个整体”
类型 :它定义的是一个 32位整数 (Integer) 。
受端序影响 :是。 - db (Define Byte):把数据当作“一串独立的字节”
类型 :它定义的是 字节数组 (Array of Bytes) 或 字符串 。
受端序影响 : 否 。
ptr
mov ecx, dword ptr aWelcomeToCtfsh |
- ai分析:
- ecx :这是 目的地。 ecx 是一个 32 位的通用寄存器(Counter Register),这里被用作存放数据的容器。
- dword ptr (Double Word Pointer) :这是 取多少数据 。
- ptr 是指针的意思,指向内存中的某个位置。
- dword (Double Word) 表示 4个字节 (32位)。
- 合起来的意思是: “请去内存里抓取 4 个字节的数据” 。
- aWelcomeToCtfsh :这是源地址 。
- 这只是 IDA Pro 给内存地址起的一个 名字(标签) ,为了让你好记。
- 它代表了字符串 “Welcome_to_CTFshow_PWN” 在内存中存放的 起始地址 。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 落殷回的博客!
评论




