栈粉碎原理分析

栈粉碎原理分析

源代码如下

#include 

void function(int a, int b) {
	char buffer[12];
	gets(buffer);

	//long* ret = (long *) ((long)buffer+28);
	//*ret = *ret + 7;

	return;
}

void main() {
	 int x;
	 x = 0;
	 function(1,2);
	 x = 1;
	 printf("%d\n",x);
} 
  1. 由解注释前的源代码生成二进制,分析其汇编程序,画出栈操作过程。
    Makefile
cc=gcc

all: stack_smashing stack_smashing.asm

.PHONY : clean

stack_smashing: stack_smashing.o
	cc -o stack_smashing stack_smashing.o

stack_smashing.o: stack_smashing.s
	cc -c -o stack_smashing.o stack_smashing.s

stack_smashing.s: stack_smashing.c
	cc -S -O0 -fno-stack-protector -o stack_smashing.s stack_smashing.c

stack_smashing.asm: stack_smashing
	objdump -d stack_smashing > stack_smashing.asm

clean:
	rm *.s
	rm *.o

由于存在Makefile是来编译stack_smashing.c,因此直接输入命令进行编译

make 

stack_smashing:     文件格式 elf64-x86-64


Disassembly of section .init:

0000000000001000 <_init>:
    1000:	f3 0f 1e fa          	endbr64 
    1004:	48 83 ec 08          	sub    $0x8,%rsp
    1008:	48 8b 05 d9 2f 00 00 	mov    0x2fd9(%rip),%rax        # 3fe8 <__gmon_start__@Base>
    100f:	48 85 c0             	test   %rax,%rax
    1012:	74 02                	je     1016 <_init+0x16>
    1014:	ff d0                	call   *%rax
    1016:	48 83 c4 08          	add    $0x8,%rsp
    101a:	c3                   	ret    

Disassembly of section .plt:

0000000000001020 <.plt>:
    1020:	ff 35 92 2f 00 00    	push   0x2f92(%rip)        # 3fb8 <_GLOBAL_OFFSET_TABLE_+0x8>
    1026:	f2 ff 25 93 2f 00 00 	bnd jmp *0x2f93(%rip)        # 3fc0 <_GLOBAL_OFFSET_TABLE_+0x10>
    102d:	0f 1f 00             	nopl   (%rax)
    1030:	f3 0f 1e fa          	endbr64 
    1034:	68 00 00 00 00       	push   $0x0
    1039:	f2 e9 e1 ff ff ff    	bnd jmp 1020 <_init+0x20>
    103f:	90                   	nop
    1040:	f3 0f 1e fa          	endbr64 
    1044:	68 01 00 00 00       	push   $0x1
    1049:	f2 e9 d1 ff ff ff    	bnd jmp 1020 <_init+0x20>
    104f:	90                   	nop

Disassembly of section .plt.got:

0000000000001050 <__cxa_finalize@plt>:
    1050:	f3 0f 1e fa          	endbr64 
    1054:	f2 ff 25 9d 2f 00 00 	bnd jmp *0x2f9d(%rip)        # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
    105b:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)

Disassembly of section .plt.sec:

0000000000001060 :
    1060:	f3 0f 1e fa          	endbr64 
    1064:	f2 ff 25 5d 2f 00 00 	bnd jmp *0x2f5d(%rip)        # 3fc8 
    106b:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)

0000000000001070 :
    1070:	f3 0f 1e fa          	endbr64 
    1074:	f2 ff 25 55 2f 00 00 	bnd jmp *0x2f55(%rip)        # 3fd0 
    107b:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)

Disassembly of section .text:

0000000000001080 <_start>:
    1080:	f3 0f 1e fa          	endbr64 
    1084:	31 ed                	xor    %ebp,%ebp
    1086:	49 89 d1             	mov    %rdx,%r9
    1089:	5e                   	pop    %rsi
    108a:	48 89 e2             	mov    %rsp,%rdx
    108d:	48 83 e4 f0          	and    $0xfffffffffffffff0,%rsp
    1091:	50                   	push   %rax
    1092:	54                   	push   %rsp
    1093:	45 31 c0             	xor    %r8d,%r8d
    1096:	31 c9                	xor    %ecx,%ecx
    1098:	48 8d 3d f0 00 00 00 	lea    0xf0(%rip),%rdi        # 118f 
109f: ff 15 33 2f 00 00 call *0x2f33(%rip) # 3fd8 <__libc_start_main@GLIBC_2.34> 10a5: f4 hlt 10a6: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 10ad: 00 00 00 00000000000010b0 : 10b0: 48 8d 3d 59 2f 00 00 lea 0x2f59(%rip),%rdi # 4010 <__TMC_END__> 10b7: 48 8d 05 52 2f 00 00 lea 0x2f52(%rip),%rax # 4010 <__TMC_END__> 10be: 48 39 f8 cmp %rdi,%rax 10c1: 74 15 je 10d8 10c3: 48 8b 05 16 2f 00 00 mov 0x2f16(%rip),%rax # 3fe0 <_ITM_deregisterTMCloneTable@Base> 10ca: 48 85 c0 test %rax,%rax 10cd: 74 09 je 10d8 10cf: ff e0 jmp *%rax 10d1: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 10d8: c3 ret 10d9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 00000000000010e0 : 10e0: 48 8d 3d 29 2f 00 00 lea 0x2f29(%rip),%rdi # 4010 <__TMC_END__> 10e7: 48 8d 35 22 2f 00 00 lea 0x2f22(%rip),%rsi # 4010 <__TMC_END__> 10ee: 48 29 fe sub %rdi,%rsi 10f1: 48 89 f0 mov %rsi,%rax 10f4: 48 c1 ee 3f shr $0x3f,%rsi 10f8: 48 c1 f8 03 sar $0x3,%rax 10fc: 48 01 c6 add %rax,%rsi 10ff: 48 d1 fe sar %rsi 1102: 74 14 je 1118 1104: 48 8b 05 e5 2e 00 00 mov 0x2ee5(%rip),%rax # 3ff0 <_ITM_registerTMCloneTable@Base> 110b: 48 85 c0 test %rax,%rax 110e: 74 08 je 1118 1110: ff e0 jmp *%rax 1112: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 1118: c3 ret 1119: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 0000000000001120 <__do_global_dtors_aux>: 1120: f3 0f 1e fa endbr64 1124: 80 3d e5 2e 00 00 00 cmpb $0x0,0x2ee5(%rip) # 4010 <__TMC_END__> 112b: 75 2b jne 1158 <__do_global_dtors_aux+0x38> 112d: 55 push %rbp 112e: 48 83 3d c2 2e 00 00 cmpq $0x0,0x2ec2(%rip) # 3ff8 <__cxa_finalize@GLIBC_2.2.5> 1135: 00 1136: 48 89 e5 mov %rsp,%rbp 1139: 74 0c je 1147 <__do_global_dtors_aux+0x27> 113b: 48 8b 3d c6 2e 00 00 mov 0x2ec6(%rip),%rdi # 4008 <__dso_handle> 1142: e8 09 ff ff ff call 1050 <__cxa_finalize@plt> 1147: e8 64 ff ff ff call 10b0 114c: c6 05 bd 2e 00 00 01 movb $0x1,0x2ebd(%rip) # 4010 <__TMC_END__> 1153: 5d pop %rbp 1154: c3 ret 1155: 0f 1f 00 nopl (%rax) 1158: c3 ret 1159: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 0000000000001160 : 1160: f3 0f 1e fa endbr64 1164: e9 77 ff ff ff jmp 10e0 0000000000001169 : 1169: f3 0f 1e fa endbr64 116d: 55 push %rbp 116e: 48 89 e5 mov %rsp,%rbp 1171: 48 83 ec 20 sub $0x20,%rsp 1175: 89 7d ec mov %edi,-0x14(%rbp) 1178: 89 75 e8 mov %esi,-0x18(%rbp) 117b: 48 8d 45 f4 lea -0xc(%rbp),%rax 117f: 48 89 c7 mov %rax,%rdi 1182: b8 00 00 00 00 mov $0x0,%eax 1187: e8 e4 fe ff ff call 1070 118c: 90 nop 118d: c9 leave 118e: c3 ret 000000000000118f
: 118f: f3 0f 1e fa endbr64 1193: 55 push %rbp 1194: 48 89 e5 mov %rsp,%rbp 1197: 48 83 ec 10 sub $0x10,%rsp 119b: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) 11a2: be 02 00 00 00 mov $0x2,%esi 11a7: bf 01 00 00 00 mov $0x1,%edi 11ac: e8 b8 ff ff ff call 1169 11b1: c7 45 fc 01 00 00 00 movl $0x1,-0x4(%rbp) 11b8: 8b 45 fc mov -0x4(%rbp),%eax 11bb: 89 c6 mov %eax,%esi 11bd: 48 8d 05 40 0e 00 00 lea 0xe40(%rip),%rax # 2004 <_IO_stdin_used+0x4> 11c4: 48 89 c7 mov %rax,%rdi 11c7: b8 00 00 00 00 mov $0x0,%eax 11cc: e8 8f fe ff ff call 1060 11d1: 90 nop 11d2: c9 leave 11d3: c3 ret Disassembly of section .fini: 00000000000011d4 <_fini>: 11d4: f3 0f 1e fa endbr64 11d8: 48 83 ec 08 sub $0x8,%rsp 11dc: 48 83 c4 08 add $0x8,%rsp 11e0: c3 ret

这个asm汇编程序的主要涉及到栈操作的为functionmain函数

main函数

0000000000001169 :
    1169:	f3 0f 1e fa          	endbr64         # 将64位模式下的栈对齐到16字节
    116d:	55                   	push   %rbp      #保存调用该函数前的栈基指针。
    116e:	48 89 e5             	mov    %rsp,%rbp # 将rsp寄存器的值赋给rbp寄存器
    1171:	48 83 ec 20          	sub    $0x20,%rsp # 在栈中为局部变量分配空间,将rsp寄存器的值减去0x20,即开辟栈空间0x20
    1175:	89 7d ec             	mov    %edi,-0x14(%rbp) # 将edi寄存器的值赋给局部变量-0x14(%rbp)
    1178:	89 75 e8             	mov    %esi,-0x18(%rbp) # 将esi寄存器的值赋给局部变量-0x18(%rbp)
    117b:	48 8d 45 f4          	lea    -0xc(%rbp),%rax  # 将局部变量-0xc(%rbp)的地址赋给rax寄存器
    117f:	48 89 c7             	mov    %rax,%rdi        # 将rax寄存器的值赋给rdi寄存器
    1182:	b8 00 00 00 00       	mov    $0x0,%eax      # 将0x0赋给eax寄存器目的是为了调用printf函数
    1187:	e8 e4 fe ff ff       	call   1070  # 调用gets函数
    118c:	90                   	nop                    # 无操作,目的是为了填充字节,使得函数的长度为16的倍数
    118d:	c9                   	leave                 # 恢复rbp寄存器的值
    118e:	c3                   	ret                 # 函数返回
000000000000118f 
: 118f: f3 0f 1e fa endbr64 # 将64位模式下的栈对齐到16字节 1193: 55 push %rbp # 保存调用该函数前的栈基指针 1194: 48 89 e5 mov %rsp,%rbp # 将rsp寄存器的值赋给rbp寄存器 1197: 48 83 ec 10 sub $0x10,%rsp # 在栈中为局部变量分配空间,将rsp寄存器的值减去0x10,即开辟栈空间0x10 119b: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) # 将0x0赋给局部变量-0x4(%rbp) 11a2: be 02 00 00 00 mov $0x2,%esi # 将0x2赋给esi寄存器 11a7: bf 01 00 00 00 mov $0x1,%edi # 将0x1赋给edi寄存器 11ac: e8 b8 ff ff ff call 1169 # 调用function函数 11b1: c7 45 fc 01 00 00 00 movl $0x1,-0x4(%rbp) # 将0x1赋给局部变量-0x4(%rbp) 11b8: 8b 45 fc mov -0x4(%rbp),%eax # 将局部变量-0x4(%rbp)的值赋给eax寄存器 11bb: 89 c6 mov %eax,%esi # 将eax寄存器的值赋给esi寄存器 11bd: 48 8d 05 40 0e 00 00 lea 0xe40(%rip),%rax # 2004 <_IO_stdin_used+0x4> # 将字符串的地址赋给rax寄存器 11c4: 48 89 c7 mov %rax,%rdi # 将rax寄存器的值赋给rdi寄存器 11c7: b8 00 00 00 00 mov $0x0,%eax # 将0x0赋给eax寄存器目的是为了调用printf函数 11cc: e8 8f fe ff ff call 1060 # 调用printf函数 11d1: 90 nop # 无操作,目的是为了填充字节,使得函数的长度为16的倍数 11d2: c9 leave # 恢复rbp寄存器的值 11d3: c3 ret # 函数返回

0x1193-0x1194 push %rbp 将栈顶指针向下移动 8 字节,并将rbp中的值压入栈中。mov %rsp,%rbprsp的值复制到rbp中,这样就建立了一个新的基址指针,用于指向当前函数的栈帧。

0x1197 sub $0x10,%rsp 将栈顶指针向下移动了0x10个字节,给当前函数分配了16个字节的栈空间。这些空间用于存储本地变量和函数调用时需要保存的寄存器。

0x119b movl $0x0,-0x4(%rbp) 将变量x初始化为 0

栈粉碎原理分析_第1张图片

0x11a2-0x11a7 mov $0x2,%esimov $0x1,%edi 分别将值2和1存储到 %esi%edi 中。

0x11ac call 1169 调用function(1,2) 在调用函数之前,当前函数的返回地址%rip被压入栈中,同时 %rsp 指针向下移动了8个字节

栈粉碎原理分析_第2张图片

0x116d-0x116epush %rbp 将栈顶指针向下移动 8 字节,并将 %rbp 中的值压入栈中。 mov %rsp,%rbp%rsp 的值复制到 %rbp 中,建立一个新的基址指针,用于指向当前函数的栈帧。

0x1171 sub $0x20,%rsp 将栈顶指针向下移动了0x20个字节,给当前函数分配了32个字节的栈空间。

0x1175-0x1178mov %edi,-0x14(%rbp)mov %esi,-0x18(%rbp) 分别将 %edi%esi 寄存器中的值存储到当前栈帧中的相对偏移量为 -0x14 和 -0x18 的位置中。这两个值分别是函数 function 的形参a,b

栈粉碎原理分析_第3张图片

接下来调用 gets(buffer)

lea -0xc(%rbp),%rax
mov %rax,%rdi
mov $0x0,%eax 将 buffer 地址传给寄存器 rdi
call 1070 调用 gets(buffer)

nop; leave; ret 返回到 ret_function(0x11b1) 中

movl $0x1,-0x4(%rbp) # 将0x1赋给局部变量-0x4(%rbp) 将 x 设为 1

栈粉碎原理分析_第4张图片

接下来调用 printf("%d\n", x)

mov -0x4(%rbp),%eax 将局部变量-0x4(%rbp)的值赋给eax寄存
mov %eax,%esi 将eax寄存器的值赋给esi寄存器,将 x 值传给寄存器 esi
lea 0xe40(%rip),%rax 将字符串的地址赋给rax寄存器
mov %rax,%rdi
mov $0x0,%eax 将 “%d\n” 字符串地址传给寄存器 rdi
call 1060 调用 printf(“%d\n”, x)

nop; leave; ret

  1. 将源代码中的语句解注释,再生成二进制,分析其汇编程序,画出栈操作过程。

将源代码解注释的汇编代码


stack_smashing:     文件格式 elf64-x86-64


Disassembly of section .init:

0000000000001000 <_init>:
    1000:	f3 0f 1e fa          	endbr64 
    1004:	48 83 ec 08          	sub    $0x8,%rsp
    1008:	48 8b 05 d9 2f 00 00 	mov    0x2fd9(%rip),%rax        # 3fe8 <__gmon_start__@Base>
    100f:	48 85 c0             	test   %rax,%rax
    1012:	74 02                	je     1016 <_init+0x16>
    1014:	ff d0                	call   *%rax
    1016:	48 83 c4 08          	add    $0x8,%rsp
    101a:	c3                   	ret    

Disassembly of section .plt:

0000000000001020 <.plt>:
    1020:	ff 35 92 2f 00 00    	push   0x2f92(%rip)        # 3fb8 <_GLOBAL_OFFSET_TABLE_+0x8>
    1026:	f2 ff 25 93 2f 00 00 	bnd jmp *0x2f93(%rip)        # 3fc0 <_GLOBAL_OFFSET_TABLE_+0x10>
    102d:	0f 1f 00             	nopl   (%rax)
    1030:	f3 0f 1e fa          	endbr64 
    1034:	68 00 00 00 00       	push   $0x0
    1039:	f2 e9 e1 ff ff ff    	bnd jmp 1020 <_init+0x20>
    103f:	90                   	nop
    1040:	f3 0f 1e fa          	endbr64 
    1044:	68 01 00 00 00       	push   $0x1
    1049:	f2 e9 d1 ff ff ff    	bnd jmp 1020 <_init+0x20>
    104f:	90                   	nop

Disassembly of section .plt.got:

0000000000001050 <__cxa_finalize@plt>:
    1050:	f3 0f 1e fa          	endbr64 
    1054:	f2 ff 25 9d 2f 00 00 	bnd jmp *0x2f9d(%rip)        # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
    105b:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)

Disassembly of section .plt.sec:

0000000000001060 :
    1060:	f3 0f 1e fa          	endbr64 
    1064:	f2 ff 25 5d 2f 00 00 	bnd jmp *0x2f5d(%rip)        # 3fc8 
    106b:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)

0000000000001070 :
    1070:	f3 0f 1e fa          	endbr64 
    1074:	f2 ff 25 55 2f 00 00 	bnd jmp *0x2f55(%rip)        # 3fd0 
    107b:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)

Disassembly of section .text:

0000000000001080 <_start>:
    1080:	f3 0f 1e fa          	endbr64 
    1084:	31 ed                	xor    %ebp,%ebp
    1086:	49 89 d1             	mov    %rdx,%r9
    1089:	5e                   	pop    %rsi
    108a:	48 89 e2             	mov    %rsp,%rdx
    108d:	48 83 e4 f0          	and    $0xfffffffffffffff0,%rsp
    1091:	50                   	push   %rax
    1092:	54                   	push   %rsp
    1093:	45 31 c0             	xor    %r8d,%r8d
    1096:	31 c9                	xor    %ecx,%ecx
    1098:	48 8d 3d 0e 01 00 00 	lea    0x10e(%rip),%rdi        # 11ad 
109f: ff 15 33 2f 00 00 call *0x2f33(%rip) # 3fd8 <__libc_start_main@GLIBC_2.34> 10a5: f4 hlt 10a6: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 10ad: 00 00 00 00000000000010b0 : 10b0: 48 8d 3d 59 2f 00 00 lea 0x2f59(%rip),%rdi # 4010 <__TMC_END__> 10b7: 48 8d 05 52 2f 00 00 lea 0x2f52(%rip),%rax # 4010 <__TMC_END__> 10be: 48 39 f8 cmp %rdi,%rax 10c1: 74 15 je 10d8 10c3: 48 8b 05 16 2f 00 00 mov 0x2f16(%rip),%rax # 3fe0 <_ITM_deregisterTMCloneTable@Base> 10ca: 48 85 c0 test %rax,%rax 10cd: 74 09 je 10d8 10cf: ff e0 jmp *%rax 10d1: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 10d8: c3 ret 10d9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 00000000000010e0 : 10e0: 48 8d 3d 29 2f 00 00 lea 0x2f29(%rip),%rdi # 4010 <__TMC_END__> 10e7: 48 8d 35 22 2f 00 00 lea 0x2f22(%rip),%rsi # 4010 <__TMC_END__> 10ee: 48 29 fe sub %rdi,%rsi 10f1: 48 89 f0 mov %rsi,%rax 10f4: 48 c1 ee 3f shr $0x3f,%rsi 10f8: 48 c1 f8 03 sar $0x3,%rax 10fc: 48 01 c6 add %rax,%rsi 10ff: 48 d1 fe sar %rsi 1102: 74 14 je 1118 1104: 48 8b 05 e5 2e 00 00 mov 0x2ee5(%rip),%rax # 3ff0 <_ITM_registerTMCloneTable@Base> 110b: 48 85 c0 test %rax,%rax 110e: 74 08 je 1118 1110: ff e0 jmp *%rax 1112: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 1118: c3 ret 1119: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 0000000000001120 <__do_global_dtors_aux>: 1120: f3 0f 1e fa endbr64 1124: 80 3d e5 2e 00 00 00 cmpb $0x0,0x2ee5(%rip) # 4010 <__TMC_END__> 112b: 75 2b jne 1158 <__do_global_dtors_aux+0x38> 112d: 55 push %rbp 112e: 48 83 3d c2 2e 00 00 cmpq $0x0,0x2ec2(%rip) # 3ff8 <__cxa_finalize@GLIBC_2.2.5> 1135: 00 1136: 48 89 e5 mov %rsp,%rbp 1139: 74 0c je 1147 <__do_global_dtors_aux+0x27> 113b: 48 8b 3d c6 2e 00 00 mov 0x2ec6(%rip),%rdi # 4008 <__dso_handle> 1142: e8 09 ff ff ff call 1050 <__cxa_finalize@plt> 1147: e8 64 ff ff ff call 10b0 114c: c6 05 bd 2e 00 00 01 movb $0x1,0x2ebd(%rip) # 4010 <__TMC_END__> 1153: 5d pop %rbp 1154: c3 ret 1155: 0f 1f 00 nopl (%rax) 1158: c3 ret 1159: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 0000000000001160 : 1160: f3 0f 1e fa endbr64 1164: e9 77 ff ff ff jmp 10e0 0000000000001169 : 1169: f3 0f 1e fa endbr64 116d: 55 push %rbp 116e: 48 89 e5 mov %rsp,%rbp 1171: 48 83 ec 30 sub $0x30,%rsp 1175: 89 7d dc mov %edi,-0x24(%rbp) 1178: 89 75 d8 mov %esi,-0x28(%rbp) 117b: 48 8d 45 ec lea -0x14(%rbp),%rax 117f: 48 89 c7 mov %rax,%rdi 1182: b8 00 00 00 00 mov $0x0,%eax 1187: e8 e4 fe ff ff call 1070 118c: 48 8d 45 ec lea -0x14(%rbp),%rax 1190: 48 83 c0 1c add $0x1c,%rax 1194: 48 89 45 f8 mov %rax,-0x8(%rbp) 1198: 48 8b 45 f8 mov -0x8(%rbp),%rax 119c: 48 8b 00 mov (%rax),%rax 119f: 48 8d 50 07 lea 0x7(%rax),%rdx 11a3: 48 8b 45 f8 mov -0x8(%rbp),%rax 11a7: 48 89 10 mov %rdx,(%rax) 11aa: 90 nop 11ab: c9 leave 11ac: c3 ret 00000000000011ad
: 11ad: f3 0f 1e fa endbr64 11b1: 55 push %rbp 11b2: 48 89 e5 mov %rsp,%rbp 11b5: 48 83 ec 10 sub $0x10,%rsp 11b9: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) 11c0: be 02 00 00 00 mov $0x2,%esi 11c5: bf 01 00 00 00 mov $0x1,%edi 11ca: e8 9a ff ff ff call 1169 11cf: c7 45 fc 01 00 00 00 movl $0x1,-0x4(%rbp) 11d6: 8b 45 fc mov -0x4(%rbp),%eax 11d9: 89 c6 mov %eax,%esi 11db: 48 8d 05 22 0e 00 00 lea 0xe22(%rip),%rax # 2004 <_IO_stdin_used+0x4> 11e2: 48 89 c7 mov %rax,%rdi 11e5: b8 00 00 00 00 mov $0x0,%eax 11ea: e8 71 fe ff ff call 1060 11ef: 90 nop 11f0: c9 leave 11f1: c3 ret Disassembly of section .fini: 00000000000011f4 <_fini>: 11f4: f3 0f 1e fa endbr64 11f8: 48 83 ec 08 sub $0x8,%rsp 11fc: 48 83 c4 08 add $0x8,%rsp 1200: c3 ret

这个asm汇编程序的同样主要涉及到栈操作的为functionmain函数,这里就不再重复上述的注释过程

main函数的栈帧变化与上面的相同

lea -0x14(%rbp),%rax
mov %rax,%rdi
mov $0x0,%eax 将 buffer 地址传给寄存器 rdi
call 1070 调用 gets(buffer)

gets函数结束时

栈粉碎原理分析_第5张图片

那么我们来分析解注释及在调用gets函数后的变化

lea -0x14(%rbp),%rax 计算距离当前 %rbp 20 个字节的地址,并将其存储到 %rax 中。

add $0x1c,%rax 指令将 %rax中的值加上 0x1c,执行(long *) ((long)buffer+28),此时rsp指向rbp+8即ret_function位置

mov %rax,-0x8(%rbp)%rax的值存储到距离当前%rbp8个字节的位置,即将ret_function的地址传给ret
栈粉碎原理分析_第6张图片

mov -0x8(%rbp),%rax 将ret值传给rax

mov (%rax),%rax
lea 0x7(%rax),%rdx将 rax + 0x7的地址传给rdx
mov -0x8(%rbp),%rax将ret值传给rax
mov %rdx,(%rax) 将 rax + 0x7 的值传给 ret_function

栈粉碎原理分析_第7张图片

nop; leave; ret 返回到 ret_function(0x11cf+0x7=0x11d6) 中

因此返回main函数时不会执行0x11d6的命令即movl $0x1,-0x4(%rbp)作用为将x=1

因此最终程序会输出0

  1. 思考注释的源码语句,在你的系统环境和编译器设置下,是否偏移量28和7能够实现跳过main函数中“x=1;”语句的功能?如果不能,在你的系统/编译器设置下,这两个偏移量应设置为多少?

根据上述分析和测试结果能

栈粉碎原理分析_第8张图片

  1. 解释被注释的源码语句,是如何在源码层面实现修改返回指令指针的?

%rax lea 0x7(%rax),%rdx将 rax + 0x7的地址传给rdx mov -0x8(%rbp),%rax将ret值传给rax mov %rdx,(%rax)` 将 rax + 0x7 的值传给 ret_function

[外链图片转存中…(img-71yUOgqP-1690513044497)]

nop; leave; ret 返回到 ret_function(0x11cf+0x7=0x11d6) 中

因此返回main函数时不会执行0x11d6的命令即movl $0x1,-0x4(%rbp)作用为将x=1

因此最终程序会输出0

  1. 思考注释的源码语句,在你的系统环境和编译器设置下,是否偏移量28和7能够实现跳过main函数中“x=1;”语句的功能?如果不能,在你的系统/编译器设置下,这两个偏移量应设置为多少?

根据上述分析和测试结果能
栈粉碎原理分析_第9张图片

  1. 解释被注释的源码语句,是如何在源码层面实现修改返回指令指针的?

根据 function函数栈帧的排列分布,该代码中ret获取buffer数组的地址后,再加上28(0x1c),便获取到了function函数返回地址所在的空间,将该值加上 7(0x7)后,在函数返回main 函数时,便会跳过x=1的执行

你可能感兴趣的:(pwn,系统安全)