mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2024-12-25 11:41:16 +07:00
small fix
This commit is contained in:
parent
09f673344b
commit
ca00ac14ce
@ -1,3 +1,4 @@
|
|||||||
|
2017-12-22:250 star 成就达成
|
||||||
2017-12-15:中文名“CTF从入门到放弃”
|
2017-12-15:中文名“CTF从入门到放弃”
|
||||||
2017-12-13:开始写 Web 部分(@phantom0301)
|
2017-12-13:开始写 Web 部分(@phantom0301)
|
||||||
2017-12-13:100 star 成就达成
|
2017-12-13:100 star 成就达成
|
||||||
|
@ -3,7 +3,11 @@
|
|||||||
|
|
||||||
市场上已经充斥着大量的 ACM 书籍,而 CTF 以其知识内容之分散、考察面之广泛、题目类型之多变,让许多新手不知所措,同时也加大了该方面书籍的编写难度。
|
市场上已经充斥着大量的 ACM 书籍,而 CTF 以其知识内容之分散、考察面之广泛、题目类型之多变,让许多新手不知所措,同时也加大了该方面书籍的编写难度。
|
||||||
|
|
||||||
此书本着开源之精神,以分享他人提高自己为目的,将是一本大而全的 CTF 领域指南。因本人能力和时间有限,不可能精通竞赛中各个类别的知识,欢迎任何人提出建议或和我一起完成此书。
|
此书本着开源之精神,以分享他人提高自己为目的,将是一本大而全的 CTF 领域指南。因本人能力和时间有限,不可能精通各个类别的知识,欢迎任何人提出任何建议,和我一起完成此书。
|
||||||
|
|
||||||
|
千万不要觉得自己是初学者就不敢提交 PR(issue),千万不要担心自己提交的 PR(issue) 会有问题,毕竟最后合并的人是我,背锅的也是我:)
|
||||||
|
|
||||||
|
如果还有其他想法,请直接给我发邮件 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.**
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ io.read_until(">>")
|
|||||||
io.interact()
|
io.interact()
|
||||||
```
|
```
|
||||||
|
|
||||||
需要注意的的是,zio 正在逐步被开发更活跃,功能更完善的 pwntools 取代,但如果你使用的是 32 位 Linux 系统,zio 可能是你唯一的选择。
|
需要注意的的是,zio 正在逐步被开发更活跃,功能更完善的 pwntools 取代,但如果你使用的是 32 位 Linux 系统,zio 可能是你唯一的选择。而且在线下赛中,内网环境通常都没有 pwntools 环境,但 zio 是单个文件,上传到内网机器上就可以直接使用。
|
||||||
|
|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
@ -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:
|
||||||
```
|
```
|
||||||
|
@ -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
|
||||||
```
|
```
|
||||||
总之,多试试总不会错。
|
总之,多试一试总不会错。
|
||||||
|
|
||||||
|
|
||||||
## 参考资料
|
## 参考资料
|
||||||
|
@ -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
|
||||||
|
@ -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` 查看。
|
||||||
|
|
||||||
比如反编译指定函数:
|
比如反编译指定函数:
|
||||||
|
@ -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
BIN
pic/5.11_top_level.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 97 KiB |
Loading…
Reference in New Issue
Block a user