finish 4.7

This commit is contained in:
firmianay 2017-11-10 19:45:37 +08:00
parent 0ef4c3b1d6
commit cd0ec632dc
7 changed files with 133 additions and 7 deletions

View File

@ -54,7 +54,7 @@
- [4.4 使用 DynELF 泄露函数地址](doc/4.4_dynelf.md) - [4.4 使用 DynELF 泄露函数地址](doc/4.4_dynelf.md)
- [4.5 Z3 约束求解器](doc/4.5_z3.md) - [4.5 Z3 约束求解器](doc/4.5_z3.md)
- [4.6 zio](doc/4.6_zio.md) - [4.6 zio](doc/4.6_zio.md)
- [4.7 通用 gadget](doc/4.7_normal_gadget.md) - [4.7 通用 gadget](doc/4.7_common_gadget.md)
- [五、高级篇](doc/5_advanced.md) - [五、高级篇](doc/5_advanced.md)
- [5.1 Fuzz 测试](doc/5.1_fuzz.md) - [5.1 Fuzz 测试](doc/5.1_fuzz.md)

View File

@ -52,7 +52,7 @@
* [4.4 使用 DynELF 泄露函数地址](doc/4.4_dynelf.md) * [4.4 使用 DynELF 泄露函数地址](doc/4.4_dynelf.md)
* [4.5 Z3 约束求解器](doc/4.5_z3.md) * [4.5 Z3 约束求解器](doc/4.5_z3.md)
* [4.6 zio](doc/4.6_zio.md) * [4.6 zio](doc/4.6_zio.md)
* [4.7 通用 gadget](doc/4.7_normal_gadget.md) * [4.7 通用 gadget](doc/4.7_common_gadget.md)
* [五、高级篇](doc/5_advanced.md) * [五、高级篇](doc/5_advanced.md)
* [5.1 Fuzz 测试](doc/5.1_fuzz.md) * [5.1 Fuzz 测试](doc/5.1_fuzz.md)
* [5.2 Pin 动态二进制插桩](doc/5.2_pin.md) * [5.2 Pin 动态二进制插桩](doc/5.2_pin.md)

View File

@ -274,11 +274,11 @@ Hello 32 f7f95580 565555f4 !
## 格式化字符串漏洞利用 ## 格式化字符串漏洞利用
通过提供格式字符串,我们就能够控制格式化函数的行为。漏洞的利用主要有下面几种。 通过提供格式字符串,我们就能够控制格式化函数的行为。漏洞的利用主要有下面几种。
#### 使程序崩溃 #### 使程序崩溃
格式字符串漏洞通常要在程序崩溃时才会被发现,所以利用格式化字符串漏洞最简单的方式就是使进程崩溃。在 Linux 中,存取无效的指针会引起进程收到 `SIGSEGV` 信号,从而使程序非正常终止并产生核心转储(在 Linux 基础的章节中详细介绍了核心转储)。我们知道核心转储中存储了程序崩溃时的许多重要信息,这些信息正是攻击者所需要的。 格式字符串漏洞通常要在程序崩溃时才会被发现,所以利用格式化字符串漏洞最简单的方式就是使进程崩溃。在 Linux 中,存取无效的指针会引起进程收到 `SIGSEGV` 信号,从而使程序非正常终止并产生核心转储(在 Linux 基础的章节中详细介绍了核心转储)。我们知道核心转储中存储了程序崩溃时的许多重要信息,这些信息正是攻击者所需要的。
利用类似下面的格式字符串即可触发漏洞: 利用类似下面的格式字符串即可触发漏洞:
```c ```c

View File

@ -1265,7 +1265,7 @@ ROP Emporium 中有几个 64 位程序在这里没有给出 payload就留作
## 更多资料 ## 更多资料
- [ROP Emporium](https://ropemporium.com) - [ROP Emporium](https://ropemporium.com)
- [一步一步 ROP 系列](https://github.com/zhengmin1989/ROP_STEP_BY_STEP) - [一步一步 ROP 系列](https://github.com/zhengmin1989/ROP_STEP_BY_STEP)
- [64-bit Linux Return-Oriented Programming](http://crypto.stanford.edu/~blynn/rop/) - [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) - [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) - [Return-Oriented Programming:Systems, Languages, and Applications](https://cseweb.ucsd.edu/~hovav/dist/rop.pdf)

127
doc/4.7_common_gadget.md Normal file
View File

@ -0,0 +1,127 @@
# 通用 gadget
## __libc_csu_init()
我们知道在程序编译的过程中,会自动加入一些通用函数做初始化的工作,这些初始化函数都是相同的,所以我们可以考虑在这些函数中找到一些通用的 gadget在 x64 程序中,就存在这样的 gadget。x64 程序的前六个参数依次通过寄存器 rdi、rsi、rdx、rcx、r8、r9 进行传递,我们所找的 gadget 自然也是针对这些寄存器进行操作的。
函数 `__libc_csu_init()` 用于对 libc 进行初始化,只要程序调用了 libc就一定存在这个函数。由于每个版本的 libc 都有一定区别,这里的版本如下:
```
$ file /usr/lib32/libc-2.26.so
/usr/lib32/libc-2.26.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (GNU/Linux), dynamically linked, interpreter /usr/lib32/ld-linux.so.2, BuildID[sha1]=ee88d1b2aa81f104ab5645d407e190b244203a52, for GNU/Linux 3.2.0, not stripped
```
下面用 6.1 pwn hctf2016 brop 的程序来做示范,使用 `/r` 参数可以打印出原始指令的十六进制:
```
gdb-peda$ disassemble /r __libc_csu_init
Dump of assembler code for function __libc_csu_init:
0x00000000004007d0 <+0>: 41 57 push r15
0x00000000004007d2 <+2>: 41 56 push r14
0x00000000004007d4 <+4>: 49 89 d7 mov r15,rdx
0x00000000004007d7 <+7>: 41 55 push r13
0x00000000004007d9 <+9>: 41 54 push r12
0x00000000004007db <+11>: 4c 8d 25 16 06 20 00 lea r12,[rip+0x200616] # 0x600df8
0x00000000004007e2 <+18>: 55 push rbp
0x00000000004007e3 <+19>: 48 8d 2d 16 06 20 00 lea rbp,[rip+0x200616] # 0x600e00
0x00000000004007ea <+26>: 53 push rbx
0x00000000004007eb <+27>: 41 89 fd mov r13d,edi
0x00000000004007ee <+30>: 49 89 f6 mov r14,rsi
0x00000000004007f1 <+33>: 4c 29 e5 sub rbp,r12
0x00000000004007f4 <+36>: 48 83 ec 08 sub rsp,0x8
0x00000000004007f8 <+40>: 48 c1 fd 03 sar rbp,0x3
0x00000000004007fc <+44>: ff 15 f6 07 20 00 call QWORD PTR [rip+0x2007f6] # 0x600ff8
0x0000000000400802 <+50>: 48 85 ed test rbp,rbp
0x0000000000400805 <+53>: 74 1f je 0x400826 <__libc_csu_init+86>
0x0000000000400807 <+55>: 31 db xor ebx,ebx
0x0000000000400809 <+57>: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
0x0000000000400810 <+64>: 4c 89 fa mov rdx,r15
0x0000000000400813 <+67>: 4c 89 f6 mov rsi,r14
0x0000000000400816 <+70>: 44 89 ef mov edi,r13d
0x0000000000400819 <+73>: 41 ff 14 dc call QWORD PTR [r12+rbx*8]
0x000000000040081d <+77>: 48 83 c3 01 add rbx,0x1
0x0000000000400821 <+81>: 48 39 dd cmp rbp,rbx
0x0000000000400824 <+84>: 75 ea jne 0x400810 <__libc_csu_init+64>
0x0000000000400826 <+86>: 48 83 c4 08 add rsp,0x8
0x000000000040082a <+90>: 5b pop rbx
0x000000000040082b <+91>: 5d pop rbp
0x000000000040082c <+92>: 41 5c pop r12
0x000000000040082e <+94>: 41 5d pop r13
0x0000000000400830 <+96>: 41 5e pop r14
0x0000000000400832 <+98>: 41 5f pop r15
0x0000000000400834 <+100>: c3 ret
End of assembler dump.
```
从中提取出两段必须以ret结尾把它们叫做 part1 和 part2
```
0x000000000040082a <+90>: 5b pop rbx
0x000000000040082b <+91>: 5d pop rbp
0x000000000040082c <+92>: 41 5c pop r12
0x000000000040082e <+94>: 41 5d pop r13
0x0000000000400830 <+96>: 41 5e pop r14
0x0000000000400832 <+98>: 41 5f pop r15
0x0000000000400834 <+100>: c3 ret
```
```
0x0000000000400810 <+64>: 4c 89 fa mov rdx,r15
0x0000000000400813 <+67>: 4c 89 f6 mov rsi,r14
0x0000000000400816 <+70>: 44 89 ef mov edi,r13d
0x0000000000400819 <+73>: 41 ff 14 dc call QWORD PTR [r12+rbx*8]
0x000000000040081d <+77>: 48 83 c3 01 add rbx,0x1
0x0000000000400821 <+81>: 48 39 dd cmp rbp,rbx
0x0000000000400824 <+84>: 75 ea jne 0x400810 <__libc_csu_init+64>
0x0000000000400826 <+86>: 48 83 c4 08 add rsp,0x8
0x000000000040082a <+90>: 5b pop rbx
0x000000000040082b <+91>: 5d pop rbp
0x000000000040082c <+92>: 41 5c pop r12
0x000000000040082e <+94>: 41 5d pop r13
0x0000000000400830 <+96>: 41 5e pop r14
0x0000000000400832 <+98>: 41 5f pop r15
0x0000000000400834 <+100>: c3 ret
```
part1 中连续六个 pop我们可以通过布置栈来设置这些寄存器然后进入 part2前三条语句r15->rdx、r14->rsi、r13d->edi分别给三个参数寄存器赋值然后调用函数这里需要注意的是第三句是 r13dr13低32位给 edirdi低32位赋值即使这样我们还是可以做很多操作了。
另外为了让程序在调用函数返回后还能继续执行,我们需要像下面这样进行构造:
```
pop rbx #必须为0
pop rbp #必须为1
pop r12 #函数地址
pop r13 #edi
pop r14 #rsi
pop r15 #rdx
ret #跳转到part2
```
上面的 gadget 是显而易见的,但如果有人精通汇编字节码,可以找到一些比较隐蔽的 gadget比如将指定一个位移点再反编译
```
gdb-peda$ disassemble /r 0x0000000000400831,0x0000000000400835
Dump of assembler code from 0x400831 to 0x400835:
0x0000000000400831 <__libc_csu_init+97>: 5e pop rsi
0x0000000000400832 <__libc_csu_init+98>: 41 5f pop r15
0x0000000000400834 <__libc_csu_init+100>: c3 ret
End of assembler dump.
```
```
gdb-peda$ disassemble /r 0x0000000000400833,0x0000000000400835
Dump of assembler code from 0x400833 to 0x400835:
0x0000000000400833 <__libc_csu_init+99>: 5f pop rdi
0x0000000000400834 <__libc_csu_init+100>: c3 ret
End of assembler dump.
```
`5e``5f` 分别是 `pop rsi``pop rdi` 的字节码,于是我们可以通过这种方法轻易地控制 `rsi``rdi`
除了上面介绍的 `__libc_csu_init()`,还可以到下面的函数中找一找:
```
_init
_start
call_gmon_start
deregister_tm_clones
register_tm_clones
__do_global_dtors_aux
frame_dummy
__libc_csu_init
__libc_csu_fini
_fini
```
总之,多试试总不会错。
## 参考资料
- [一步一步学 ROP 系列](https://github.com/zhengmin1989/ROP_STEP_BY_STEP)

View File

@ -1 +0,0 @@
# 通用 gadget

View File

@ -6,4 +6,4 @@
- [4.4 使用 DynELF 泄露函数地址](4.4_dynelf.md) - [4.4 使用 DynELF 泄露函数地址](4.4_dynelf.md)
- [4.5 Z3 约束求解器](4.5_z3.md) - [4.5 Z3 约束求解器](4.5_z3.md)
- [4.6 zio](4.6_zio.md) - [4.6 zio](4.6_zio.md)
- [4.7 通用 gadget](4.7_normal_gadget.md) - [4.7 通用 gadget](4.7_common_gadget.md)