X86-64 Register

Simple Demo 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void func(char *str){
char buffer[256];
int i;
i = 0;
while(*str) buffer[i++] = *str++;
}
int main(int ac, char **av)
{
char *fstring = "First string";
char *sstring = "Second string";
if(ac >= 2)
func(av[1]);
printf("%s => %s\n",fstring,sstring);
}

GDB Disassemble Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Dump of assembler code for function main:
0x0000000100000f00 <+0>: push %rbp
0x0000000100000f01 <+1>: mov %rsp,%rbp
0x0000000100000f04 <+4>: sub $0x30,%rsp
0x0000000100000f08 <+8>: lea 0x88(%rip),%rax # 0x100000f97
0x0000000100000f0f <+15>: lea 0x74(%rip),%rcx # 0x100000f8a
0x0000000100000f16 <+22>: movl $0x0,-0x4(%rbp)
0x0000000100000f1d <+29>: mov %edi,-0x8(%rbp)
0x0000000100000f20 <+32>: mov %rsi,-0x10(%rbp)
0x0000000100000f24 <+36>: mov %rcx,-0x18(%rbp)
0x0000000100000f28 <+40>: mov %rax,-0x20(%rbp)
0x0000000100000f2c <+44>: cmpl $0x2,-0x8(%rbp)
0x0000000100000f30 <+48>: jl 0x100000f43 <main+67>
0x0000000100000f36 <+54>: mov -0x10(%rbp),%rax
0x0000000100000f3a <+58>: mov 0x8(%rax),%rdi
0x0000000100000f3e <+62>: callq 0x100000ea0 <func>
0x0000000100000f43 <+67>: lea 0x5b(%rip),%rdi # 0x100000fa5
0x0000000100000f4a <+74>: mov -0x18(%rbp),%rsi
0x0000000100000f4e <+78>: mov -0x20(%rbp),%rdx
0x0000000100000f52 <+82>: mov $0x0,%al
0x0000000100000f54 <+84>: callq 0x100000f68
0x0000000100000f59 <+89>: mov -0x4(%rbp),%ecx
0x0000000100000f5c <+92>: mov %eax,-0x24(%rbp)
0x0000000100000f5f <+95>: mov %ecx,%eax
0x0000000100000f61 <+97>: add $0x30,%rsp
0x0000000100000f65 <+101>: pop %rbp
0x0000000100000f66 <+102>: retq
End of assembler dump.

注意到

1
2
3
4
0x0000000100000f1d <+29>: mov %edi,-0x8(%rbp)
0x0000000100000f20 <+32>: mov %rsi,-0x10(%rbp)
0x0000000100000f24 <+36>: mov %rcx,-0x18(%rbp)
0x0000000100000f28 <+40>: mov %rax,-0x20(%rbp)

使用了%edi,%rsi,%rcx,%rax,查阅手册

register.png

Simple Demo2

1
2
3
4
5
6
7
8
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[]) {
/* [1] */ char buf[256];
/* [2] */ strcpy(buf,argv[1]);
/* [3] */ printf("Input:%s\n",buf);
return 0;
}

如果在MacOS系统想要进行Buffer Overflow的测试的话,如果使用GCC编译需要用这两个-fno-stack-protector -D_FORTIFY_SOURCE=0选项。

GCC堆栈保护

-fstack-protector:

启用堆栈保护,不过只为局部变量中含有 char 数组的函数插入保护代码。

-fstack-protector-all:

启用堆栈保护,为所有函数插入保护代码。

-fno-stack-protector:

禁用堆栈保护。

stack-protector保护方式修改函数栈的组织,在缓冲区和可控数据buffer间插入一个canary word(标志)。当缓冲区被溢出时,canary word 会首先被覆盖。通过检查 canary word 的值是否被修改,就可以判断是否发生了溢出。

汇编代码中mov %edi,-0x8(%rbp)这样的为AT&T的语法。
Intel 语法的间接内存引用的格式为:
section:[base+index*scale+displacement]
而在 AT&T 语法中对应的形式为:
section:displacement(base,index,scale)

mov %edi,-0x8(%rbp) =(%rbp + 0*0 - 0x8)

Comments

⬆︎TOP