复习
fork()
in the road: 创造平行宇宙本次课回答的问题
本次课主要内容
本次课涉及的手册
(不用听了,可以下课了)
操作系统 “为程序 (状态机) 提供执行环境”
一个描述了状态机的初始状态 + 迁移的
需要满足若干条件
$ ./a.c
bash: ./a.c: Permission denied
$ chmod -x a.out && ./a.out
fish: The file “./a.out” is not executable by this user
$ chmod +x a.c && ./a.c
Failed to execute process './a.c'. Reason:
exec: Exec format error
The file './a.c' is marked as an executable but could not be run by the operating system.
操作系统代码 (execve) 决定的。
动手试一试
segfault.c - 为什么 gdb 知道出错的位置?
$ ./a.out
Segmentation fault (core dumped)
(gdb) r
Starting program: /tmp/demo/a.out
Program received signal SIGSEGV, Segmentation fault.
bar () at segfault.c:4
4 *(int *)NULL = 1;
(gdb) bt
#0 bar () at segfault.c:4
#1 0x0000000000401d0d in foo () at segfault.c:8
#2 0x0000000000401d22 in main () at segfault.c:12
将一个 assembly (机器) 状态映射到 “C 世界” 状态的函数
DW_OP_XXX
<optimized out>
s=<optimized out>
没有 frame pointer 的时候呢?
得到 “不希望” 你看到的商业软件代码 (然后就可以分析漏洞啥了)
被《计算机系统基础》支配的恐惧?
// main.c
void hello();
int main() {
hello();
}
// hello.c
#include <stdio.h>
void hello() {
printf("Hello World\n");
}
编译器生成文本汇编代码 → 汇编器生成二进制指令序列
0000000000000000 <main>:
0: f3 0f 1e fa endbr64
4: 48 83 ec 08 sub $0x8,%rsp
8: 31 c0 xor %eax,%eax
a: e8 00 00 00 00 callq ????????
f: 31 c0 xor %eax,%eax
11: 48 83 c4 08 add $0x8,%rsp
15: c3 retq
但有些地址编译的时候不知道啊 (比如 hello)
但这 4-bytes 最终是需要被填上的,使得 assertion 被满足:
assert(
(char *)hello ==
(char *)main + 0xf + // call hello 的 next PC
*(int32_t *)((uintptr_t)main + 0xb) // call 指令中的 offset
);
这个要求也要被写在文件里
Offset Type Sym. Name + Addend
00000000000b R_X86_64_PLT32 hello - 4
编译器 (gcc)
汇编器 (as)
链接器 (ld)
-Wl,--verbose
); 和 C Runtime Objects (CRT) 链接ELF 就是一个 “容器数据结构”,包含了必要的信息
struct executable {
uint32_t entry;
struct segment *segments;
struct reloc *relocs;
struct symbol *symbols;
};
struct segment { uint32_t flags, size; char data[0]; }
struct reloc { uint32_t S, A, P; char name[32]; };
struct symbol { uint32_t off; char name[32]; };
const char *
而不是 char[]
)本次课回答的问题
Take-away messages