diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index 1f11e10..1f4b024 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -5,6 +5,8 @@ 此书本着开源之精神,以分享他人提高自己为目的,将是一本大而全的 CTF 领域指南。因本人能力和时间有限,不可能精通竞赛中各个类别的知识,欢迎任何人提出建议或和我一起完成此书。 +**You think you understand something until you try to teach it.** + -- 开始于 2017.7.17 ### 规范 diff --git a/doc/2.2_gdb&peda.md b/doc/2.2_gdb&peda.md index 0e6cef2..1a3177b 100644 --- a/doc/2.2_gdb&peda.md +++ b/doc/2.2_gdb&peda.md @@ -2,6 +2,8 @@ - [gdb 的组成架构](#gdb-的组成架构) - [gdb 基本工作原理](#gdb-基本工作原理) + - [gdb 的三种调试方式](#gdb-的三种调试方式) + - [断点的实现](#断点的实现) - [gdb 基本操作](#gdb-基本操作) - [gdb-peda](#gdb-peda) - [GEF/pwndbg](#gefpwndbg) @@ -180,6 +182,11 @@ long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data); #### run -- r 启动被调试的程序。可以直接指定参数,也可以用 `set args` 设置(启动所需的)参数。还允许使用 `>`, `<`, 或 `>>` 进行输入和输出重定向。 +甚至可以运行一个脚本,如: +``` +run `python2 -c 'print "A"*100` +``` + #### backtrace -- bt 打印整个栈的回溯。 diff --git a/doc/3.3.4_rop.md b/doc/3.3.4_rop.md index 7c6b30c..257e294 100644 --- a/doc/3.3.4_rop.md +++ b/doc/3.3.4_rop.md @@ -1,6 +1,8 @@ # 3.3.4 返回导向编程(ROP) - [ROP 简介](#rop-简介) + - [寻找 gadgets](#寻找-gadgets) + - [常用的 gadgets](#常用的-gadgets) - [ROP Emporium](#rop-emporium) - [ret2win32](#ret2win32) - [ret2win](#ret2win) @@ -11,7 +13,7 @@ - [write432](#write432) - [write4](#write4) - [badchars32](#badchars32) - - [badchar](#badchar) + - [badchars](#badchars) - [fluff32](#fluff32) - [fluff](#fluff) - [pivot32](#pivot32) @@ -21,7 +23,37 @@ ## ROP 简介 -返回导向编程(Return-Oriented Programming,缩写:ROP)是一种高级的内存攻击技术,该技术允许攻击者在现代操作系统的各种通用防御下执行代码,如内存不可执行和代码签名等。这类攻击往往利用操作堆栈调用时的程序漏洞,通常是缓冲区溢出。攻击者控制堆栈调用以劫持程序控制流并执行针对性的机器语言指令序列(gadgets),每一段 gadget 通常以 return 指令(`ret`)结束,并位于共享库代码中的子程序中。通过执行这些指令序列,也就控制了程序的执行。 +返回导向编程(Return-Oriented Programming,缩写:ROP)是一种高级的内存攻击技术,该技术允许攻击者在现代操作系统的各种通用防御下执行代码,如内存不可执行和代码签名等。这类攻击往往利用操作堆栈调用时的程序漏洞,通常是缓冲区溢出。攻击者控制堆栈调用以劫持程序控制流并执行针对性的机器语言指令序列(gadgets),每一段 gadget 通常以 return 指令(`ret`,机器码为`c3`)结束,并位于共享库代码中的子程序中。通过执行这些指令序列,也就控制了程序的执行。 + +`ret` 指令相当于 `pop eip`。即,首先将 `esp` 指向的 4 字节内容读取并赋值给 `eip`,然后 `esp` 加上 4 字节指向栈的下一个位置。如果当前执行的指令序列仍然以 `ret` 指令结束,则这个过程将重复, `esp` 再次增加并且执行下一个指令序列。 + +#### 寻找 gadgets +1. 在程序中寻找所有的 c3(ret) 字节 +2. 向前搜索,看前面的字节是否包含一个有效指令,这里可以指定最大搜索字节数,以获得不同长度的 gadgets +3. 记录下我们找到的所有有效指令序列 + +理论上我们是可以这样寻找 gadgets 的,但实际上有很多工具可以完成这个工作,如 ROPgadget,Ropper 等。更完整的搜索可以使用 http://ropshell.com/。 + +#### 常用的 gadgets +对于 gadgets 能做的事情,基本上只要你敢想,它就敢执行。下面简单介绍几种用法: +- 保存栈数据到寄存器 + - 将栈顶的数据抛出并保存到寄存器中,然后跳转到新的栈顶地址。所以当返回地址被一个 gadgets 的地址覆盖,程序将在返回后执行该指令序列。 + - 如:`pop eax; ret` +- 保存内存数据到寄存器 + - 将内存地址处的数据加载到内存器中。 + - 如:`mov ecx,[eax]; ret` +- 保存寄存器数据到内存 + - 将寄存器的值保存到内存地址处。 + - 如:`mov [eax],ecx; ret` +- 算数和逻辑运算 + - add, sub, mul, xor 等。 + - 如:`add eax,ebx; ret`, `xor edx,edx; ret` +- 系统调用 + - 执行内核中断 + - 如:`int 0x80; ret`, `call gs:[0x10]; ret` +- 会影响栈帧的 gadgets + - 这些 gadgets 会改变 ebp 的值,从而影响栈帧,在一些操作如 stack pivot 时我们需要这样的指令来转移栈帧。 + - 如:`leave; ret`, `pop ebp; ret` ## ROP Emporium @@ -546,7 +578,7 @@ $ ropgadget --binary write432 --only "mov|pop|ret" 0x080486da : pop edi ; pop ebp ; ret ``` -另外需要注意的是,我们这里是 32 位程序,每次只能写入 4 个字节,所以要分成两次写入,还得注意字符对其之类的问题,构造 payload 如下: +另外需要注意的是,我们这里是 32 位程序,每次只能写入 4 个字节,所以要分成两次写入,还得注意字符对齐,有没有截断字符(`\x00`,`\x0a`等)之类的问题,比如这里 `/bin/sh` 只有七个字节,我们可以使用 `/bin/sh\00` 或者 `/bin//sh`,构造 payload 如下: ```python from zio import * @@ -1222,6 +1254,8 @@ payload_2 += p64(leakaddr) payload_2 += p64(xchg_rax_rsp) ``` +实际上,我本人正是使用这种方法,因为我在构建 payload 时,`0x0000000000400ae0 <+165>: leave`,leave;ret 的地址存在截断字符 `0a`,这样就不能通过正常的方式写入缓冲区,当然这也是可以解决的,比如先将 `0a` 换成非截断字符,之后再使用寄存器将 `0a` 写入该地址,这也是通常解决缓冲区中截断字符的方法,但是这样做难度太大,不推荐,感兴趣的读者可以尝试一下。 + 这样基本的 ROP 也就介绍完了,更高级的用法会在后面的章节中再介绍,所谓的高级,也就是 gadgets 构造更加巧妙,运用操作系统的知识更加底层而已。 @@ -1229,8 +1263,9 @@ payload_2 += p64(xchg_rax_rsp) ROP Emporium 中有几个 64 位程序在这里没有给出 payload,就留作联系吧,答案都可以在这里找到:[ROP Emporium Writeup](https://firmianay.github.io/2017/11/02/rop_emporium.html) -## 更多参考 +## 更多资料 - [ROP Emporium](https://ropemporium.com) - [一步一步 ROP 系列](https://github.com/zhengmin1989/ROP_STEP_BY_STEP) - [64-bit Linux Return-Oriented Programming](http://crypto.stanford.edu/~blynn/rop/) - [Introduction to return oriented programming (ROP)](http://codearcana.com/posts/2013/05/28/introduction-to-return-oriented-programming-rop.html) +- [Return-Oriented Programming:Systems, Languages, and Applications](https://cseweb.ucsd.edu/~hovav/dist/rop.pdf) diff --git a/doc/4.2_Linux_terminal_tips.md b/doc/4.2_Linux_terminal_tips.md index aaa3881..9c68ab1 100644 --- a/doc/4.2_Linux_terminal_tips.md +++ b/doc/4.2_Linux_terminal_tips.md @@ -4,8 +4,8 @@ - [从可执行文件中提取 shellcode](#从可执行文件中提取-shellcode) - [查看进程虚拟地址空间](#查看进程虚拟地址空间) - [ASCII 表](#ascii-表) -- [nohup 和 &](#nohup-和) -- [cat -](#cat) +- [nohup 和 &](#nohup-和-) +- [cat -](#cat--) ## 重定向输入字符 @@ -249,7 +249,7 @@ $ bg 1 $ fg 1 ``` -#### cat - +## cat - 通常使用 cat 时后面都会跟一个文件名,但如果没有,或者只有一个 `-`,则表示从标准输入读取数据,它会保持标准输入开启,如: ``` $ cat - @@ -277,4 +277,4 @@ firmy ^C Segmentation fault (core dumped) ``` -这样就得到了 shell。 \ No newline at end of file +这样就得到了 shell。