得分:10/10
C程序homework08.c的主函数如下:
1int main(int argc, char * argv[]) {
2init_buf(Lbuffer, LEN);
3switch(argc)
4{
5case 1: f00(); break;
6case 2: f01(); break;
7case 3: f02(); break;
8default: f00(); break;
9}
10puts("Done.\nThe program exited normally.");
11return 0;
12}
- 在32位的ubuntu16.04系统中用
gcc -fno-stack-protector
编译该程序,得到的可执行程序见附件,通过gdb调试,对f00()、f01()和f02()进行分析:
(1) 函数f00()、f01()和f02()是否导致段错误。
- 如果没有命令行参数(argc 等于 1,因为程序名本身也算一个参数),则执行函数 f00()。
- 如果有一个命令行参数(argc 等于 2),则执行函数 f01()。
- 如果有两个命令行参数(argc 等于 3),则执行函数 f02()。
- 如果有三个或更多的命令行参数,还是执行函数 f00()。 ![[Pasted image 20231122231415.png]]
函数foo()
, 和 foo01()
都会导致段错误。
如果函数f00()、f01()和f02()导致段错误,计算出被攻击的缓冲区首地址与函数的返回地址所在的栈地址的距离(即偏移OFFSET),给出溢出后函数的返回地址(用16进制数表示)。
f00()
![[Pasted image 20231121150016.png]]
打断点
函数入口处的堆栈指针esp指向的栈(地址为0xffffd1dc)保存了 函数f00()返回到调用函数(main)的地址(0x080485a8),即“函数的返回地址”
记录堆栈指针esp的值,在此以A标记:A=$esp = 0xffffd1dc
1(gdb) x/x $esp
20xffffd1dc: 0x080485a8
3(gdb) c
4Continuing.
5
6Breakpoint 2, 0x080484e9 in f00 ()
71: x/i $eip
8=> 0x80484e9 <f00+24>: call 0x8048320 <strcpy@plt>
9(gdb) x/x $esp
100xffffd140: 0xffffd155
11(gdb)
120xffffd144: 0x0804a060
13(gdb) x/x 0x0804a060
140x804a060 <Lbuffer>: 0x44434241
令B = 0xffffd155,则offset=A-B=0xffffd1dc - 0xffffd155 =0x87=135。
1(gdb) c
2Continuing.
3
4Breakpoint 3, 0x080484f3 in f00 ()
51: x/i $eip
6=> 0x80484f3 <f00+34>: ret
7(gdb) x/x $esp
80xffffd1dc: 0x49484746
9(gdb) x/s $esp
100xffffd1dc: "FGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW"...
执行ret之前的堆栈的内容可以推断执行ret后将跳到地址0x49484746去执行
f01
执行程序
1azureuser@MyServer:~/hw$ gdb homework08
main
1(gdb) disas main
2Dump of assembler code for function main:
3 0x0804856c <+0>: lea 0x4(%esp),%ecx
4 0x08048570 <+4>: and $0xfffffff0,%esp
5 0x08048573 <+7>: pushl -0x4(%ecx)
6 0x08048576 <+10>: push %ebp
7 0x08048577 <+11>: mov %esp,%ebp
8 0x08048579 <+13>: push %ebx
9 0x0804857a <+14>: push %ecx
10 0x0804857b <+15>: mov %ecx,%ebx
11 0x0804857d <+17>: sub $0x8,%esp
12 0x08048580 <+20>: push $0x400
13 0x08048585 <+25>: push $0x804a060
14 0x0804858a <+30>: call 0x804846b <init_buf>
15 0x0804858f <+35>: add $0x10,%esp
16 0x08048592 <+38>: mov (%ebx),%eax
17 0x08048594 <+40>: cmp $0x2,%eax
18 0x08048597 <+43>: je 0x80485aa <main+62>
19 0x08048599 <+45>: cmp $0x3,%eax
20 0x0804859c <+48>: je 0x80485b1 <main+69>
21 0x0804859e <+50>: cmp $0x1,%eax
22 0x080485a1 <+53>: jne 0x80485b8 <main+76>
23 0x080485a3 <+55>: call 0x80484d1 <f00>
24 0x080485a8 <+60>: jmp 0x80485be <main+82>
25 0x080485aa <+62>: call 0x80484f4 <f01>
26 0x080485af <+67>: jmp 0x80485be <main+82>
27 0x080485b1 <+69>: call 0x8048530 <f02>
28 0x080485b6 <+74>: jmp 0x80485be <main+82>
29 0x080485b8 <+76>: call 0x80484d1 <f00>
30 0x080485bd <+81>: nop
31 0x080485be <+82>: sub $0xc,%esp
32 0x080485c1 <+85>: push $0x8048660
33 0x080485c6 <+90>: call 0x8048330 <puts@plt>
34 0x080485cb <+95>: add $0x10,%esp
35 0x080485ce <+98>: mov $0x0,%eax
36 0x080485d3 <+103>: lea -0x8(%ebp),%esp
37 0x080485d6 <+106>: pop %ecx
38 0x080485d7 <+107>: pop %ebx
39 0x080485d8 <+108>: pop %ebp
40 0x080485d9 <+109>: lea -0x4(%ecx),%esp
41 0x080485dc <+112>: ret
42End of assembler dump.
f01()
1(gdb) disas f01
2Dump of assembler code for function f01:
3 0x080484f4 <+0>: push %ebp
4 0x080484f5 <+1>: mov %esp,%ebp
5 0x080484f7 <+3>: sub $0x508,%esp
6 0x080484fd <+9>: sub $0x8,%esp
7 0x08048500 <+12>: push $0x400
8 0x08048505 <+17>: lea -0x4fe(%ebp),%eax
9 0x0804850b <+23>: push %eax
10 0x0804850c <+24>: call 0x804846b <init_buf>
11 0x08048511 <+29>: add $0x10,%esp
12 0x08048514 <+32>: sub $0x8,%esp
13 0x08048517 <+35>: lea -0x4fe(%ebp),%eax
14 0x0804851d <+41>: push %eax
15 0x0804851e <+42>: lea -0xfe(%ebp),%eax
16 0x08048524 <+48>: push %eax
17 0x08048525 <+49>: call 0x8048320 <strcpy@plt>
18 0x0804852a <+54>: add $0x10,%esp
19 0x0804852d <+57>: nop
20 0x0804852e <+58>: leave
21 0x0804852f <+59>: ret
22End of assembler dump.
设置断点
1(gdb) b*(f01+0)
2Breakpoint 1 at 0x80484f4
3(gdb) b*(f01+49)
4Breakpoint 2 at 0x8048525
5(gdb) b*(f01+59)
6Breakpoint 3 at 0x804852f
1(gdb) display/i $eip
21: x/i $eip
3<error: No registers.>
4(gdb) x/i $eip
5No registers.
6(gdb) run 1
7Starting program: /home/azureuser/hw/homework08 1
8
9Breakpoint 1, 0x080484f4 in f01 ()
101: x/i $eip
11=> 0x80484f4 <f01>: push %ebp
12(gdb) x/x $esp
130xffffd1cc: 0x080485af
记录堆栈指针esp的值,在此以A标记:A=$esp = 0xffffd1cc
继续执行到下一个断点
1(gdb) c
2Continuing.
3
4Breakpoint 2, 0x08048525 in f01 ()
51: x/i $eip
6=> 0x8048525 <f01+49>: call 0x8048320 <strcpy@plt>
7(gdb) x $esp
80xffffccb0: 0xffffd0ca
9(gdb)
100xffffccb4: 0xffffccca
11(gdb) x/x 0xffffccca
120xffffccca: 0x44434241
B=0xffffd0ca。
offset=A-B= 0xffffd1cc - 0xffffd0ca =0x102=258。
1(gdb) c
2Continuing.
3
4Breakpoint 3, 0x0804852f in f01 ()
51: x/i $eip
6=> 0x804852f <f01+59>: ret
7(gdb) x/x $esp
80xffffd1cc: 0x42415a59
9(gdb) x/s $esp
100xffffd1cc: "YZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP"...
11(gdb) si
120x42415a59 in ?? ()
131: x/i $eip
14=> 0x42415a59: <error: Cannot access memory at address 0x42415a59>
15(gdb) x/s $esp
160xffffd1d0: "CDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST"...
返回地址变 为 0x42415a59
其他(本次实验的一些其它尝试)
- 由于这个可执行文件是ubuntu16.04编译的,本身我的虚拟机系统是ubuntu18.04,一开始执行文件老是报错:
1~$ ./homework08
2-bash: ./homework08: No such file or directory
查询之后发现不是文件不存在,是缺少需要的依赖,因为Ubuntu18.04默认去掉了32bit的library。
解决方法
1sudo apt-get install lib32z1
之后就可以执行了。
- 本身自己的电脑是mac m2芯片,一开始没尝试使用虚拟机而是docker在容器内去pull ubuntu的镜像来尝试实验:
% docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -it --platform linux/386 -v "/Users/agq/Downloads/srcToStudent:/srcToStudent" --name=hw6 i386/ubuntu /bin/bash
发现能运行文件,并且可以显示段错误:
但由于qemu天生不支持ptrace系统调用,而gdb正是依赖这个系统调用,所以无法进行调试(QEMU’s user-mode emulation does not support the ptrace system call)所以第二题就做不了,遂作罢。