small fix

This commit is contained in:
firmianay 2017-12-22 21:34:47 +08:00
parent 09f673344b
commit ca00ac14ce
9 changed files with 21 additions and 12 deletions

View File

@ -1,3 +1,4 @@
2017-12-22250 star 成就达成
2017-12-15中文名“CTF从入门到放弃” 2017-12-15中文名“CTF从入门到放弃”
2017-12-13开始写 Web 部分(@phantom0301 2017-12-13开始写 Web 部分(@phantom0301
2017-12-13100 star 成就达成 2017-12-13100 star 成就达成

View File

@ -3,7 +3,11 @@
市场上已经充斥着大量的 ACM 书籍,而 CTF 以其知识内容之分散、考察面之广泛、题目类型之多变,让许多新手不知所措,同时也加大了该方面书籍的编写难度。 市场上已经充斥着大量的 ACM 书籍,而 CTF 以其知识内容之分散、考察面之广泛、题目类型之多变,让许多新手不知所措,同时也加大了该方面书籍的编写难度。
此书本着开源之精神,以分享他人提高自己为目的,将是一本大而全的 CTF 领域指南。因本人能力和时间有限,不可能精通竞赛中各个类别的知识,欢迎任何人提出建议或和我一起完成此书。 此书本着开源之精神,以分享他人提高自己为目的,将是一本大而全的 CTF 领域指南。因本人能力和时间有限,不可能精通各个类别的知识,欢迎任何人提出任何建议,和我一起完成此书。
千万不要觉得自己是初学者就不敢提交 PRissue千万不要担心自己提交的 PRissue 会有问题,毕竟最后合并的人是我,背锅的也是我:)
如果还有其他想法,请直接给我发邮件 firmianay@gmail.com。
**You think you understand something until you try to teach it.** **You think you understand something until you try to teach it.**

View File

@ -45,7 +45,7 @@ io.read_until(">>")
io.interact() io.interact()
``` ```
需要注意的的是zio 正在逐步被开发更活跃,功能更完善的 pwntools 取代,但如果你使用的是 32 位 Linux 系统zio 可能是你唯一的选择。 需要注意的的是zio 正在逐步被开发更活跃,功能更完善的 pwntools 取代,但如果你使用的是 32 位 Linux 系统zio 可能是你唯一的选择。而且在线下赛中,内网环境通常都没有 pwntools 环境,但 zio 是单个文件,上传到内网机器上就可以直接使用。
## 安装 ## 安装

View File

@ -414,7 +414,7 @@ Dump of assembler code for function usefulFunction:
0x0000000000400817 <+16>: ret 0x0000000000400817 <+16>: ret
End of assembler dump. End of assembler dump.
``` ```
64 位程序的第一个参数通过 edi 传递,所以我们调用需要一个 gadgets 来将字符串的地址存进 edi。 64 位程序的第一个参数通过 edi 传递,所以我们调用需要一个 gadgets 来将字符串的地址存进 edi。
我们先找到需要的 gadgets 我们先找到需要的 gadgets
``` ```

View File

@ -93,8 +93,8 @@ ret #跳转到part2
```python ```python
def com_gadget(part1, part2, jmp2, arg1 = 0x0, arg2 = 0x0, arg3 = 0x0): def com_gadget(part1, part2, jmp2, arg1 = 0x0, arg2 = 0x0, arg3 = 0x0):
payload = p64(part1) # part1 entry pop_rbx_pop_rbp_pop_r12_pop_r13_pop_r14_pop_r15_ret payload = p64(part1) # part1 entry pop_rbx_pop_rbp_pop_r12_pop_r13_pop_r14_pop_r15_ret
payload += p64(0x0) # rbx be 0x0 payload += p64(0x0) # rbx must be 0x0
payload += p64(0x1) # rbp be 0x1 payload += p64(0x1) # rbp must be 0x1
payload += p64(jmp2) # r12 jump to payload += p64(jmp2) # r12 jump to
payload += p64(arg1) # r13 -> edi arg1 payload += p64(arg1) # r13 -> edi arg1
payload += p64(arg2) # r14 -> rsi arg2 payload += p64(arg2) # r14 -> rsi arg2
@ -104,7 +104,7 @@ def com_gadget(part1, part2, jmp2, arg1 = 0x0, arg2 = 0x0, arg3 = 0x0):
return payload return payload
``` ```
上面的 gadget 是显而易见的,但如果有人精通汇编字节码,可以找到一些比较隐蔽的 gadget比如指定一个位移点再反编译: 上面的 gadget 是显而易见的,但如果有人精通汇编字节码,可以找到一些比较隐蔽的 gadget比如指定一个位移点再反编译:
``` ```
gdb-peda$ disassemble /r 0x0000000000400831,0x0000000000400835 gdb-peda$ disassemble /r 0x0000000000400831,0x0000000000400835
Dump of assembler code from 0x400831 to 0x400835: Dump of assembler code from 0x400831 to 0x400835:
@ -122,7 +122,7 @@ End of assembler dump.
``` ```
`5e``5f` 分别是 `pop rsi``pop rdi` 的字节码,于是我们可以通过这种方法轻易地控制 `rsi``rdi` `5e``5f` 分别是 `pop rsi``pop rdi` 的字节码,于是我们可以通过这种方法轻易地控制 `rsi``rdi`
在 6.1 pwn hctf2016 brop 的exp中,我们使用了偏移后的 `pop rdi; ret`,而没有用 `com_gadget()` 函数感兴趣的童鞋可以尝试使用它重写exp。 在 6.1.1 pwn HCTF2016 brop 的 exp 中,我们使用了偏移后的 `pop rdi; ret`,而没有用 `com_gadget()` 函数,感兴趣的童鞋可以尝试使用它重写 exp。
除了上面介绍的 `__libc_csu_init()`,还可以到下面的函数中找一找: 除了上面介绍的 `__libc_csu_init()`,还可以到下面的函数中找一找:
``` ```
@ -137,7 +137,7 @@ __libc_csu_init
__libc_csu_fini __libc_csu_fini
_fini _fini
``` ```
总之,多试试总不会错。 总之,多试试总不会错。
## 参考资料 ## 参考资料

View File

@ -95,7 +95,7 @@ DynELF 使用了两种技术:
ssize_t write(int fd, const void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count);
``` ```
write 函数用于向文件描述符中写入数据,三个参数分别是文件描述符,一个指针指向的数据和写入数据的长度。该函数的点是可以读取任意长度的内存数据,即打印数据的长度只由 count 控制,缺点则是需要传递 3 个参数。32 位程序通过栈传递参数,直接将参数布置在栈上就可以了,而 64 位程序首先使用寄存器传递参数,所以我们通常使用通用 gadget参见章节4.7 来为 write 函数传递参数。 write 函数用于向文件描述符中写入数据,三个参数分别是文件描述符,一个指针指向的数据和写入数据的长度。该函数的点是可以读取任意长度的内存数据,即打印数据的长度只由 count 控制,缺点则是需要传递 3 个参数。32 位程序通过栈传递参数,直接将参数布置在栈上就可以了,而 64 位程序首先使用寄存器传递参数,所以我们通常使用通用 gadget参见章节4.7 来为 write 函数传递参数。
例子是 xdctf2015-pwn200[文件地址](../src/writeup/6.2_pwn_xdctf2015_pwn200)。在这个程序中也只有 write 可以利用: 例子是 xdctf2015-pwn200[文件地址](../src/writeup/6.2_pwn_xdctf2015_pwn200)。在这个程序中也只有 write 可以利用:
``` ```
@ -220,7 +220,7 @@ io.interactive()
int puts(const char *s); int puts(const char *s);
``` ```
puts 函数使用的参数只有一个,即需要输出的数据的起始地址,它会一直输出直到遇到 `\x00`所以它输出的数据长度是不容易控制的我们无法预料到零字符会出现在哪里截止后puts 还会自动在末尾加上换行符 `\n`。该函数的优点是在 64 位程序中也可以很方便地使用。缺点是会受到零字符截断的影响,在写 leak 函数时需要特殊处理,在打印出的数据中正确地筛选我们需要的部分,如果打印处了空字符串,则要手动赋值`\x00`,包括我们在 dump 内存的时候,也常常收这个问题的困扰,可以参考章节 6.1 dump 内存的部分。 puts 函数使用的参数只有一个,即需要输出的数据的起始地址,它会一直输出直到遇到 `\x00`所以它输出的数据长度是不容易控制的我们无法预料到零字符会出现在哪里截止后puts 还会自动在末尾加上换行符 `\n`。该函数的优点是在 64 位程序中也可以很方便地使用。缺点是会受到零字符截断的影响,在写 leak 函数时需要特殊处理,在打印出的数据中正确地筛选我们需要的部分,如果打印出了空字符串,则要手动赋值`\x00`,包括我们在 dump 内存的时候,也常常受这个问题的困扰,可以参考章节 6.1 dump 内存的部分。
所以我们常常需要这样做: 所以我们常常需要这样做:
```python ```python

View File

@ -80,6 +80,10 @@ a.out a.out.c a.out.c.backend.bc a.out.c.backend.ll a.out.c.frontend.dsm a.
- 核心阶段:接下来才是重头戏,调用 `bin2llvmir` 将二进制文件转换成 LLVM IR并输出 `a.out.c.frontend.dsm`、`a.out.c.backend.ll` 和 `a.out.c.backend.bc` - 核心阶段:接下来才是重头戏,调用 `bin2llvmir` 将二进制文件转换成 LLVM IR并输出 `a.out.c.frontend.dsm`、`a.out.c.backend.ll` 和 `a.out.c.backend.bc`
- 后端阶段:这个阶段通过一系列代码优化和生成等操作,将 LLVM IR 反编译成 C 代码 `a.out.c`,还有 CFG 等。 - 后端阶段:这个阶段通过一系列代码优化和生成等操作,将 LLVM IR 反编译成 C 代码 `a.out.c`,还有 CFG 等。
整个过程的结构如下:
![](../pic/5.11_top_level.png)
`decompile.sh` 有很多选项,使用 `decompile.sh -h` 查看。 `decompile.sh` 有很多选项,使用 `decompile.sh -h` 查看。
比如反编译指定函数: 比如反编译指定函数:

View File

@ -61,7 +61,7 @@ done
## BROP 原理及题目解析 ## BROP 原理及题目解析
BROP 即 Blind ROP需要我们在无法获得二进制文件的情况下通过 ROP 进行远程攻击,劫持该应用程序的控制流,可用于开启了 ASLR、NX和栈canaries的 64-bit Linux。这一概念是是在 2014 年提出的,论文和幻灯片在参考资料中。 BROP 即 Blind ROP需要我们在无法获得二进制文件的情况下通过 ROP 进行远程攻击,劫持该应用程序的控制流,可用于开启了 ASLR、NX 和栈 canary 的 64-bit Linux。这一概念是是在 2014 年提出的,论文和幻灯片在参考资料中。
实现这一攻击有两个必要条件: 实现这一攻击有两个必要条件:
1. 目标程序存在一个栈溢出漏洞,并且我们知道怎样去触发它 1. 目标程序存在一个栈溢出漏洞,并且我们知道怎样去触发它
@ -92,7 +92,7 @@ def get_buffer_size():
``` ```
[*] buffer size: 72 [*] buffer size: 72
``` ```
要注意的是,崩溃意味着我们覆盖到了返回地址,所以缓冲区应该是发送的字符数减一,即 buf(64)+ebp(8)=72。该题并没有开启canary所以跳过爆破的过程。 要注意的是,崩溃意味着我们覆盖到了返回地址,所以缓冲区应该是发送的字符数减一,即 buf(64)+ebp(8)=72。该题并没有开启 canary所以跳过爆破的过程。
#### stop gadget #### stop gadget
在寻找通用 gadget 之前,我们需要一个 stop gadget。一般情况下当我们把返回地址覆盖后程序有很大的几率会挂掉因为所覆盖的地址可能并不是合法的所以我们需要一个能够使程序正常返回的地址称作 stop gadget这一步至关重要。stop gadget 可能不止一个,这里我们之间返回找到的第一个好了: 在寻找通用 gadget 之前,我们需要一个 stop gadget。一般情况下当我们把返回地址覆盖后程序有很大的几率会挂掉因为所覆盖的地址可能并不是合法的所以我们需要一个能够使程序正常返回的地址称作 stop gadget这一步至关重要。stop gadget 可能不止一个,这里我们之间返回找到的第一个好了:

BIN
pic/5.11_top_level.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB