mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2024-12-24 19:21:15 +07:00
fix
This commit is contained in:
parent
7ef0b1679e
commit
d19b1ff24b
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -81,6 +82,8 @@ Command: 5
|
|||||||
|
|
||||||
怎么利用 Dump 操作呢?如果能使两个 chunk 相重叠,Free 一个,Dump 另一个,或许可行。
|
怎么利用 Dump 操作呢?如果能使两个 chunk 相重叠,Free 一个,Dump 另一个,或许可行。
|
||||||
|
|
||||||
|
|
||||||
|
## 漏洞利用
|
||||||
#### leak libc
|
#### leak libc
|
||||||
还是一样的,为了方便调试,先关掉 ASLR。首先分配 3 个 fast chunk 和 1 个 small chunk,其实填充数据对漏洞利用是没有意义的,这里只是为了方便观察:
|
还是一样的,为了方便调试,先关掉 ASLR。首先分配 3 个 fast chunk 和 1 个 small chunk,其实填充数据对漏洞利用是没有意义的,这里只是为了方便观察:
|
||||||
```python
|
```python
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -63,5 +64,7 @@ n
|
|||||||
|
|
||||||
## 题目解析
|
## 题目解析
|
||||||
|
|
||||||
|
## 漏洞利用
|
||||||
|
|
||||||
## 参考资料
|
## 参考资料
|
||||||
- [how2heap](https://github.com/shellphish/how2heap)
|
- [how2heap](https://github.com/shellphish/how2heap)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -36,8 +37,8 @@ $ socat tcp4-listen:10001,reuseaddr,fork exec:"env LD_PRELOAD=./libc-2.23.so ./v
|
|||||||
|
|
||||||
|
|
||||||
## 题目解析
|
## 题目解析
|
||||||
#### Exploit
|
|
||||||
|
|
||||||
|
## 漏洞利用
|
||||||
|
|
||||||
## 参考资料
|
## 参考资料
|
||||||
https://ctftime.org/task/5490
|
https://ctftime.org/task/5490
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
- [Exploit](#exploit)
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ __register_printf_specifier (int spec, printf_function converter,
|
|||||||
然后发现 `spec` 被直接用做数组 `__printf_function_table` 和 `__printf_arginfo_table` 的下标。`s` 也就是 `0x73`,这和我们在 gdb 里看到的相符:`rdx=0x73`,`[rax+rdx*8]`正好是数组取值的方式,虽然这里的 `rax` 里保存的是 `__printf_modifier_table`。
|
然后发现 `spec` 被直接用做数组 `__printf_function_table` 和 `__printf_arginfo_table` 的下标。`s` 也就是 `0x73`,这和我们在 gdb 里看到的相符:`rdx=0x73`,`[rax+rdx*8]`正好是数组取值的方式,虽然这里的 `rax` 里保存的是 `__printf_modifier_table`。
|
||||||
|
|
||||||
|
|
||||||
## Exploit
|
## 漏洞利用
|
||||||
有了上面的分析,下面我们来构造 exp。
|
有了上面的分析,下面我们来构造 exp。
|
||||||
|
|
||||||
回顾一下 `__parse_one_specmb()` 函数里的 `if` 判断语句,我们知道 C 语言对 `||` 的处理机制是如果第一个表达式为 True,就不再进行第二个表达式的判断,所以为了执行函数 `*__printf_arginfo_table[spec->info.spec]`,需要前面的判断条件都为 False。我们可以在 `.bss` 段上伪造一个 `printf_arginfo_size_function` 结构体,在结构体偏移 `0x73*8` 的地方放上 `__stack_chk_fail()` 的地址,当该函数执行时,将打印出 `argv[0]` 指向的字符串,所以我们还需要将 `argv[0]` 覆盖为 flag 的地址。
|
回顾一下 `__parse_one_specmb()` 函数里的 `if` 判断语句,我们知道 C 语言对 `||` 的处理机制是如果第一个表达式为 True,就不再进行第二个表达式的判断,所以为了执行函数 `*__printf_arginfo_table[spec->info.spec]`,需要前面的判断条件都为 False。我们可以在 `.bss` 段上伪造一个 `printf_arginfo_size_function` 结构体,在结构体偏移 `0x73*8` 的地方放上 `__stack_chk_fail()` 的地址,当该函数执行时,将打印出 `argv[0]` 指向的字符串,所以我们还需要将 `argv[0]` 覆盖为 flag 的地址。
|
||||||
@ -251,6 +251,7 @@ $ python2 exp.py
|
|||||||
*** stack smashing detected ***: 34C3_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX terminated
|
*** stack smashing detected ***: 34C3_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX terminated
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### exploit
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
from pwn import *
|
from pwn import *
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
- [Exploit](#exploit)
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -119,6 +119,8 @@ Please overwrite the flag: Thank you, bye!
|
|||||||
```
|
```
|
||||||
看注释已经很明显了,第一次的输入需要我们触发栈溢出,使程序调用 `__stack_chk_fail()`,并打印出 `argv[0]`。第二次的输入将覆盖掉位于 `0x00600d20` 的 flag。
|
看注释已经很明显了,第一次的输入需要我们触发栈溢出,使程序调用 `__stack_chk_fail()`,并打印出 `argv[0]`。第二次的输入将覆盖掉位于 `0x00600d20` 的 flag。
|
||||||
|
|
||||||
|
|
||||||
|
## 漏洞利用
|
||||||
那么问题来了,如果 flag 被覆盖掉了,那还怎样将其打印出来。这就涉及到了 ELF 文件的映射问题,我们知道 x86-64 程序的映射是从 `0x400000` 开始的:
|
那么问题来了,如果 flag 被覆盖掉了,那还怎样将其打印出来。这就涉及到了 ELF 文件的映射问题,我们知道 x86-64 程序的映射是从 `0x400000` 开始的:
|
||||||
```
|
```
|
||||||
$ ld --verbose | grep __executable_start
|
$ ld --verbose | grep __executable_start
|
||||||
@ -269,8 +271,19 @@ __libc_message (do_abort=do_abort@entry=0x1, fmt=fmt@entry=0x7ffff7b9c49f "*** %
|
|||||||
81 ../sysdeps/posix/libc_fatal.c: No such file or directory.
|
81 ../sysdeps/posix/libc_fatal.c: No such file or directory.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Bingo!!!
|
||||||
|
```
|
||||||
|
$ python exp.py
|
||||||
|
[+] Opening connection to 127.0.0.1 on port 10001: Done
|
||||||
|
[+] Receiving all data: Done (703B)
|
||||||
|
[*] Closed connection to 127.0.0.1 port 10001
|
||||||
|
Hello!
|
||||||
|
What's your name? Nice to meet you, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @.
|
||||||
|
Please overwrite the flag: Thank you, bye!
|
||||||
|
*** stack smashing detected ***: 32C3_TheServerHasTheFlagHere... terminated
|
||||||
|
```
|
||||||
|
|
||||||
## Exploit
|
#### exploit
|
||||||
最终的 exp 如下:
|
最终的 exp 如下:
|
||||||
```python
|
```python
|
||||||
from pwn import *
|
from pwn import *
|
||||||
@ -288,18 +301,6 @@ io.sendline(payload_2)
|
|||||||
print io.recvall()
|
print io.recvall()
|
||||||
```
|
```
|
||||||
|
|
||||||
Bingo!!!
|
|
||||||
```
|
|
||||||
$ python exp.py
|
|
||||||
[+] Opening connection to 127.0.0.1 on port 10001: Done
|
|
||||||
[+] Receiving all data: Done (703B)
|
|
||||||
[*] Closed connection to 127.0.0.1 port 10001
|
|
||||||
Hello!
|
|
||||||
What's your name? Nice to meet you, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @.
|
|
||||||
Please overwrite the flag: Thank you, bye!
|
|
||||||
*** stack smashing detected ***: 32C3_TheServerHasTheFlagHere... terminated
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## 参考资料
|
## 参考资料
|
||||||
- https://ctftime.org/task/1958
|
- https://ctftime.org/task/1958
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
- [Exploit one](#exploit-one)
|
- [漏洞利用](#漏洞利用)
|
||||||
- [Exploit two](#exploit-two)
|
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -679,7 +678,7 @@ struct user *users[0x60];
|
|||||||
然后是删除 user 的过程中,只释放了 user 本身和 user->group,而 user->name 没有被释放。可能导致信息泄漏。
|
然后是删除 user 的过程中,只释放了 user 本身和 user->group,而 user->name 没有被释放。可能导致信息泄漏。
|
||||||
|
|
||||||
|
|
||||||
## Exploit
|
## 漏洞利用
|
||||||
逆向分析完成,来简单地总结一下。
|
逆向分析完成,来简单地总结一下。
|
||||||
- 两个结构体和两个由结构体指针构成的数组:
|
- 两个结构体和两个由结构体指针构成的数组:
|
||||||
```c
|
```c
|
||||||
@ -706,7 +705,6 @@ struct group *groups[0x60]; // 0x6023e0
|
|||||||
|
|
||||||
然后是关于 tcache 的问题。在这个程序中有两个线程,thread-1 为主线程,thread-2 为 GC 线程,它们都有自己的 tcache。程序中所有 chunk 的分配工作都由 thread-1 执行,thread-2 只释放(group和group_name)不分配,所以在它的 tcache bins 被装满以后所有该线程释放的 fast chunk 都被放进 fastbins 中。而 fastbins 是进程公用的,所以会被主线程在分配时使用。
|
然后是关于 tcache 的问题。在这个程序中有两个线程,thread-1 为主线程,thread-2 为 GC 线程,它们都有自己的 tcache。程序中所有 chunk 的分配工作都由 thread-1 执行,thread-2 只释放(group和group_name)不分配,所以在它的 tcache bins 被装满以后所有该线程释放的 fast chunk 都被放进 fastbins 中。而 fastbins 是进程公用的,所以会被主线程在分配时使用。
|
||||||
|
|
||||||
## Exploit one
|
|
||||||
第一种方法,我们利用 ref_count 溢出的 UAF。
|
第一种方法,我们利用 ref_count 溢出的 UAF。
|
||||||
|
|
||||||
#### overflow
|
#### overflow
|
||||||
@ -987,8 +985,6 @@ LD_PRELOAD=./libc-2.26.so /bin/sh
|
|||||||
```
|
```
|
||||||
应该换成 Ubuntu-17.10 试试。(本机Arch)
|
应该换成 Ubuntu-17.10 试试。(本机Arch)
|
||||||
|
|
||||||
|
|
||||||
## Exploit two
|
|
||||||
第二种方法,我们利用两个具有同名 group 的 user 释放时的 UAF。这种方法似乎与 tcache 的关系更大一点。
|
第二种方法,我们利用两个具有同名 group 的 user 释放时的 UAF。这种方法似乎与 tcache 的关系更大一点。
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
- [Exploit](#exploit)
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -340,7 +340,7 @@ vaddr=0x00201fd0 paddr=0x00001fd0 type=SET_64 system
|
|||||||
可以看到 `read()` 函数有一个很明显的栈溢出漏洞,`local_30h` 并没有 `0x400` 这么大的空间。由于游戏是递归的,所以我们需要答对前 999 道题,在最后一题时溢出,构造 ROP。
|
可以看到 `read()` 函数有一个很明显的栈溢出漏洞,`local_30h` 并没有 `0x400` 这么大的空间。由于游戏是递归的,所以我们需要答对前 999 道题,在最后一题时溢出,构造 ROP。
|
||||||
|
|
||||||
|
|
||||||
## Exploit
|
## 漏洞利用
|
||||||
总结一下,程序存在两个漏洞:
|
总结一下,程序存在两个漏洞:
|
||||||
- hint 函数将 system 放到栈上,而 go 函数在使用该地址时未进行初始化
|
- hint 函数将 system 放到栈上,而 go 函数在使用该地址时未进行初始化
|
||||||
- level 函数存在栈溢出
|
- level 函数存在栈溢出
|
||||||
@ -448,7 +448,7 @@ $ whoami
|
|||||||
firmy
|
firmy
|
||||||
```
|
```
|
||||||
|
|
||||||
#### exp
|
#### exploit
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
- [Exploit](#exploit)
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -424,7 +424,7 @@ struct student *my_class[0x1e];
|
|||||||
漏洞就是在读入 memo 和 name 的时候都存在的 one-byte overflow,其中 memo 会覆盖掉 name 指针的低字节。考虑可以将 name 指针改成其它地址,并利用修改 name 的功能修改地址上的内容。
|
漏洞就是在读入 memo 和 name 的时候都存在的 one-byte overflow,其中 memo 会覆盖掉 name 指针的低字节。考虑可以将 name 指针改成其它地址,并利用修改 name 的功能修改地址上的内容。
|
||||||
|
|
||||||
|
|
||||||
## Exploit
|
## 漏洞利用
|
||||||
所以我们的思路是通过 one-byte overflow,使 my_class[0]->name 指向 my_class[1]->name,从而获得任意地址读写的能力。然后泄漏 system 函数地址和 main 函数的返回地址,将返回地址覆盖以制造 ROP,调用 system('/bin/sh') 获得 shell。
|
所以我们的思路是通过 one-byte overflow,使 my_class[0]->name 指向 my_class[1]->name,从而获得任意地址读写的能力。然后泄漏 system 函数地址和 main 函数的返回地址,将返回地址覆盖以制造 ROP,调用 system('/bin/sh') 获得 shell。
|
||||||
|
|
||||||
#### overflow
|
#### overflow
|
||||||
@ -550,7 +550,7 @@ $ whoami
|
|||||||
firmy
|
firmy
|
||||||
```
|
```
|
||||||
|
|
||||||
#### exp
|
#### exploit
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
@ -706,7 +706,7 @@ $ whoami
|
|||||||
firmy
|
firmy
|
||||||
```
|
```
|
||||||
|
|
||||||
#### exp
|
#### exploit
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
- [Exploit](#exploit)
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -687,7 +687,7 @@ $ whoami
|
|||||||
firmy
|
firmy
|
||||||
```
|
```
|
||||||
|
|
||||||
#### exp
|
#### exploit
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [BROP 原理及题目解析](#brop-原理及题目解析)
|
- [BROP 原理及题目解析](#brop-原理及题目解析)
|
||||||
- [Exploit](#exploit)
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -69,6 +69,8 @@ BROP 即 Blind ROP,需要我们在无法获得二进制文件的情况下,
|
|||||||
|
|
||||||
下面我们结合题目来讲一讲。
|
下面我们结合题目来讲一讲。
|
||||||
|
|
||||||
|
|
||||||
|
## 漏洞利用
|
||||||
#### 栈溢出
|
#### 栈溢出
|
||||||
首先是要找到栈溢出的漏洞,老办法从 1 个字符开始,暴力枚举,直到它崩溃。
|
首先是要找到栈溢出的漏洞,老办法从 1 个字符开始,暴力枚举,直到它崩溃。
|
||||||
```python
|
```python
|
||||||
@ -359,6 +361,7 @@ p.recvline()
|
|||||||
p.sendline(payload)
|
p.sendline(payload)
|
||||||
p.interactive()
|
p.interactive()
|
||||||
```
|
```
|
||||||
|
|
||||||
Bingo!!!
|
Bingo!!!
|
||||||
```
|
```
|
||||||
$ python2 exp.py
|
$ python2 exp.py
|
||||||
@ -368,8 +371,7 @@ $ whoami
|
|||||||
firmy
|
firmy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### exploit
|
||||||
## Exploit
|
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
from pwn import *
|
from pwn import *
|
||||||
|
@ -364,7 +364,7 @@ store 放在 `0x804b080`,当前 user 个数 user_num 放在 `0x804b069`。
|
|||||||
|
|
||||||
|
|
||||||
## 漏洞利用
|
## 漏洞利用
|
||||||
所以我们首先添加两个 user,用于绕过检查。第 3 个 user 存放 "/bin/sh"。然后删掉第 1 个 user,并创建一个 description 很长的 user,其长度是第 1 个 user 的 description 长度加上 user 结构体长度。这时候检查就绕过了,我们可以在添加新 user 的时候修改 description 大小,造成堆溢出,并修改第 2 个 user 的 user->desc 为 free@got.plt,从而泄漏出 libc 地址。得到 system 地址后,此时修改第 2 个 user 的 description,其实是修改 free 的 GOT,所以我们将其改成 system@got.plt。最后删除第 3 个 user,触发 system('/bin/sh'),得到 shell。
|
所以我们首先添加两个 user,用于绕过检查。第 3 个 user 存放 "/bin/sh"。然后删掉第 1 个 user,并创建一个 description 很长的 user,其长度是第 1 个 user 的 description 长度加上 user 结构体长度。这时候检查就绕过了,我们可以在添加新 user 的时候修改 description 大小,造成堆溢出,并修改第 2 个 user 的 user->desc 为 `free@got.plt`,从而泄漏出 libc 地址。得到 system 地址后,此时修改第 2 个 user 的 description,其实是修改 free 的 GOT,所以我们将其改成 `system@got.plt`。最后删除第 3 个 user,触发 system('/bin/sh'),得到 shell。
|
||||||
|
|
||||||
开启 ASLR。Bingo!!!
|
开启 ASLR。Bingo!!!
|
||||||
```
|
```
|
||||||
@ -376,7 +376,7 @@ $ whoami
|
|||||||
firmy
|
firmy
|
||||||
```
|
```
|
||||||
|
|
||||||
#### exp
|
#### exploit
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [Blind fmt 原理及题目解析](#blind-fmt-原理及题目解析)
|
- [Blind fmt 原理及题目解析](#blind-fmt-原理及题目解析)
|
||||||
- [Exploit](#exploit)
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -28,6 +28,8 @@ $ socat tcp4-listen:10001,reuseaddr,fork exec:./pingme &
|
|||||||
|
|
||||||
通常有两种方法可以解决这种问题,一种是利用信息泄露把程序从内存中 dump 下来,另一种是使用 pwntools 的 DynELF 模块(关于该模块的使用我们在章节 4.4 中有讲过)。
|
通常有两种方法可以解决这种问题,一种是利用信息泄露把程序从内存中 dump 下来,另一种是使用 pwntools 的 DynELF 模块(关于该模块的使用我们在章节 4.4 中有讲过)。
|
||||||
|
|
||||||
|
|
||||||
|
## 漏洞利用
|
||||||
#### 确认漏洞
|
#### 确认漏洞
|
||||||
首先你当然不知道这是一个栈溢出还是格式化字符串,栈溢出的话输入一段长字符串,但程序是否崩溃,格式化字符串的话就输入格式字符,看输出。
|
首先你当然不知道这是一个栈溢出还是格式化字符串,栈溢出的话输入一段长字符串,但程序是否崩溃,格式化字符串的话就输入格式字符,看输出。
|
||||||
```
|
```
|
||||||
@ -86,11 +88,11 @@ payload = "%9$s.AAA" + p32(start_addr)
|
|||||||
于是就成了有二进制文件无 libc 的格式化字符串漏洞,在 r2 中查询 printf 的 got 地址:
|
于是就成了有二进制文件无 libc 的格式化字符串漏洞,在 r2 中查询 printf 的 got 地址:
|
||||||
```
|
```
|
||||||
[0x08048490]> is~printf
|
[0x08048490]> is~printf
|
||||||
vaddr=0x08048400 paddr=0x00000400 ord=002 fwd=NONE sz=16 bind=GLOBAL type=FUNC name=imp.printf
|
vaddr=0x08048400 paddr=0x00000400 ord=002 fwd=NONE sz=16 bind=GLOBAL type=FUNC name=imp.printf
|
||||||
[0x08048490]> pd 3 @ 0x08048400
|
[0x08048490]> pd 3 @ 0x08048400
|
||||||
: ;-- imp.printf:
|
: ;-- imp.printf:
|
||||||
: 0x08048400 ff2574990408 jmp dword [reloc.printf_116] ; 0x8049974
|
: 0x08048400 ff2574990408 jmp dword [reloc.printf_116] ; 0x8049974
|
||||||
: 0x08048406 6808000000 push 8 ; 8
|
: 0x08048406 6808000000 push 8 ; 8
|
||||||
`=< 0x0804840b e9d0ffffff jmp 0x80483e0
|
`=< 0x0804840b e9d0ffffff jmp 0x80483e0
|
||||||
```
|
```
|
||||||
地址为 `0x8049974`。
|
地址为 `0x8049974`。
|
||||||
@ -200,8 +202,7 @@ $ whoami
|
|||||||
firmy
|
firmy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### exploit
|
||||||
## Exploit
|
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
from pwn import *
|
from pwn import *
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [ret2dl-resolve 原理及题目解析](#ret2dlresolve-原理及题目解析)
|
- [ret2dl-resolve 原理及题目解析](#ret2dlresolve-原理及题目解析)
|
||||||
- [Exploit](#exploit)
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -942,7 +942,7 @@ firmy
|
|||||||
如果觉得手工构造太麻烦,有一个工具 [roputils](https://github.com/inaz2/roputils) 可以简化此过程,感兴趣的同学可以自行尝试。
|
如果觉得手工构造太麻烦,有一个工具 [roputils](https://github.com/inaz2/roputils) 可以简化此过程,感兴趣的同学可以自行尝试。
|
||||||
|
|
||||||
|
|
||||||
## Exploit
|
## 漏洞利用
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
from pwn import *
|
from pwn import *
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
# 6.1.5 pwn GreHackCTF2017 beerfighter
|
# 6.1.5 pwn GreHackCTF2017 beerfighter
|
||||||
|
|
||||||
|
- [题目复现](#题目复现)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
- [Exploit](#exploit)
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
[下载文件](../src/writeup/6.1.5_pwn_grehackctf2017_beerfighter)
|
[下载文件](../src/writeup/6.1.5_pwn_grehackctf2017_beerfighter)
|
||||||
|
|
||||||
## 题目解析
|
## 题目复现
|
||||||
```
|
```
|
||||||
$ file game
|
$ file game
|
||||||
game: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=1f9b11cb913afcbbbf9cb615709b3c62b2fdb5a2, stripped
|
game: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=1f9b11cb913afcbbbf9cb615709b3c62b2fdb5a2, stripped
|
||||||
@ -43,6 +44,8 @@ By !
|
|||||||
Segmentation fault (core dumped)
|
Segmentation fault (core dumped)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
##题目解析
|
||||||
程序大概清楚了,看代码吧,经过一番搜索,发现了一个很有意思的函数:
|
程序大概清楚了,看代码吧,经过一番搜索,发现了一个很有意思的函数:
|
||||||
```
|
```
|
||||||
[0x00400d8e]> pdf @ fcn.00400773
|
[0x00400d8e]> pdf @ fcn.00400773
|
||||||
@ -67,6 +70,8 @@ gdb-peda$ pattern_offset $ebp
|
|||||||
```
|
```
|
||||||
缓冲区还挺大的,`1040+8=1048`。
|
缓冲区还挺大的,`1040+8=1048`。
|
||||||
|
|
||||||
|
|
||||||
|
## 漏洞利用
|
||||||
好,现在思路已经清晰了,先利用缓冲区溢出漏洞,用 `syscall;ret` 地址覆盖返回地址,通过 frame\_1 调用 `read()` 读入 frame_2 到 `.data` 段(这个程序没有`.bss`,而且`.data`可写),然后将栈转移过去,调用 `execve()` 执行“/bin/sh”,从而拿到 shell。
|
好,现在思路已经清晰了,先利用缓冲区溢出漏洞,用 `syscall;ret` 地址覆盖返回地址,通过 frame\_1 调用 `read()` 读入 frame_2 到 `.data` 段(这个程序没有`.bss`,而且`.data`可写),然后将栈转移过去,调用 `execve()` 执行“/bin/sh”,从而拿到 shell。
|
||||||
|
|
||||||
构造 sigreturn:
|
构造 sigreturn:
|
||||||
@ -122,8 +127,7 @@ $ whoami
|
|||||||
firmy
|
firmy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### exploit
|
||||||
## Exploit
|
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
from pwn import *
|
from pwn import *
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
- [ret2vdso 原理](#ret2vdso-原理)
|
- [ret2vdso 原理](#ret2vdso-原理)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
- [Exploit](#exploit)
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -29,8 +29,7 @@ RELRO STACK CANARY NX PIE RPATH RUNPA
|
|||||||
No RELRO No canary found NX enabled No PIE No RPATH No RUNPATH No 0 0 fuckup
|
No RELRO No canary found NX enabled No PIE No RPATH No RUNPATH No 0 0 fuckup
|
||||||
```
|
```
|
||||||
|
|
||||||
## Exploit
|
## 漏洞利用
|
||||||
完整的 exp 如下:
|
|
||||||
|
|
||||||
## 参考资料
|
## 参考资料
|
||||||
- `man vdso`
|
- `man vdso`
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
# 6.1.7 pwn 0CTF2015 freenote
|
# 6.1.7 pwn 0CTF2015 freenote
|
||||||
|
|
||||||
- [题目简介](#题目解析)
|
- [题目复现](#题目复现)
|
||||||
- [题目逆向](#题目逆向)
|
- [题目解析](#题目解析)
|
||||||
- [Exploit](#exploit)
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
[下载文件](../src/writeup/6.1.7_pwn_0ctf2015_freenote)
|
[下载文件](../src/writeup/6.1.7_pwn_0ctf2015_freenote)
|
||||||
|
|
||||||
## 题目解析
|
## 题目复现
|
||||||
```
|
```
|
||||||
$ file freenote
|
$ file freenote
|
||||||
freenote: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=dd259bb085b3a4aeb393ec5ef4f09e312555a64d, stripped
|
freenote: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=dd259bb085b3a4aeb393ec5ef4f09e312555a64d, stripped
|
||||||
@ -105,7 +105,7 @@ $ socat tcp4-listen:10001,reuseaddr,fork exec:"env LD_PRELOAD=./libc.so_1 ./free
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## 题目逆向
|
## 题目解析
|
||||||
我们先来看一下 main 函数:
|
我们先来看一下 main 函数:
|
||||||
```
|
```
|
||||||
[0x00400770]> pdf @ main
|
[0x00400770]> pdf @ main
|
||||||
@ -702,7 +702,7 @@ Delete 的实现如下:
|
|||||||
该函数在读入要删除的笔记序号后,首先将 Notes 结构体成员 `length -1`,然后将对应的 Note 结构体的 `isValid` 和 `length` 修改为 `0`,然后 free 掉笔记的内容(`*content`)。
|
该函数在读入要删除的笔记序号后,首先将 Notes 结构体成员 `length -1`,然后将对应的 Note 结构体的 `isValid` 和 `length` 修改为 `0`,然后 free 掉笔记的内容(`*content`)。
|
||||||
|
|
||||||
|
|
||||||
## Exploit
|
## 漏洞利用
|
||||||
在上面逆向的过程中我们发现,程序存在 double free 漏洞。在 Delete 的时候,只是设置了 `isValid =0` 作为标记,而没有将该笔记从 Notes 中移除,也没有将 `content` 设置为 NULL,然后就调用了 free 函数。整个过程没有对 `isValid` 是否已经为 `0` 做任何检查。于是我们可以对同一个笔记 Delete 两次,造成 double free,修改 GOT 表,改变程序的执行流。
|
在上面逆向的过程中我们发现,程序存在 double free 漏洞。在 Delete 的时候,只是设置了 `isValid =0` 作为标记,而没有将该笔记从 Notes 中移除,也没有将 `content` 设置为 NULL,然后就调用了 free 函数。整个过程没有对 `isValid` 是否已经为 `0` 做任何检查。于是我们可以对同一个笔记 Delete 两次,造成 double free,修改 GOT 表,改变程序的执行流。
|
||||||
|
|
||||||
#### 泄漏地址
|
#### 泄漏地址
|
||||||
@ -1040,6 +1040,7 @@ $ whoami
|
|||||||
firmy
|
firmy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### exploit
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
from pwn import *
|
from pwn import *
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [C++ 异常处理机制](#C-异常处理机制)
|
- [C++ 异常处理机制](#C-异常处理机制)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -360,6 +361,8 @@ $ ldd flex
|
|||||||
|
|
||||||
分析完了,接下来就写 exp 吧。
|
分析完了,接下来就写 exp 吧。
|
||||||
|
|
||||||
|
|
||||||
|
## 漏洞利用
|
||||||
#### stack pivot
|
#### stack pivot
|
||||||
在 `0x004012b4` 下断点,以检查溢出点:
|
在 `0x004012b4` 下断点,以检查溢出点:
|
||||||
```
|
```
|
||||||
@ -465,7 +468,7 @@ $ whoami
|
|||||||
firmy
|
firmy
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Exploit
|
#### exploit
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
from pwn import *
|
from pwn import *
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
- [题目复现](#题目复现)
|
- [题目复现](#题目复现)
|
||||||
- [题目解析](#题目解析)
|
- [题目解析](#题目解析)
|
||||||
|
- [漏洞利用](#漏洞利用)
|
||||||
- [参考资料](#参考资料)
|
- [参考资料](#参考资料)
|
||||||
|
|
||||||
|
|
||||||
@ -630,6 +631,8 @@ She's gone!
|
|||||||
```
|
```
|
||||||
很好地验证了球员分配和删除的过程。
|
很好地验证了球员分配和删除的过程。
|
||||||
|
|
||||||
|
|
||||||
|
## 漏洞利用
|
||||||
#### alloc and select
|
#### alloc and select
|
||||||
然后是内存,根据我们对堆管理机制的理解,这里选择使用 small chunk(球员 name chunk):
|
然后是内存,根据我们对堆管理机制的理解,这里选择使用 small chunk(球员 name chunk):
|
||||||
```python
|
```python
|
||||||
@ -883,7 +886,7 @@ $ whoami
|
|||||||
firmy
|
firmy
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Exploit
|
#### exploit
|
||||||
完整的 exp 如下:
|
完整的 exp 如下:
|
||||||
```python
|
```python
|
||||||
from pwn import *
|
from pwn import *
|
||||||
|
Loading…
Reference in New Issue
Block a user