CSAPP Machine Level Programming
C 语言 基础属性
数组的指针运算– 数组存储的是它的指针,其指针++ 会跳过存储数据量的位置(如 int a[10],a++ ,arr[a]会+4)
struct的对齐
由于会根据struct中的最大的基本结构类型[int,double,float 之类的,和列表没关系]来进行对齐[例如,struct中存在double就会按照8byte对齐,如果最大只有int,就按照4byte对齐],因此,最好将结构合理组织,
如
1
2
3
4
5
6
7
8
9
10 struct S4{//char :1 byte, int : 4byte
char c;// 产生3个用于对齐的内存浪费
int i;
char d;// 产生3个用于对齐的浪费
}// waste 3+3 byte
struct S5{
int i;
char c;
char d;//c,d一并存储,产生2个用于对齐的浪费
}
Memory Layout
IMG:
Buffer OverFlow
- 注: 内存是按照0x7FFFFFFFFFFF 也就是2^47来作为地址的,所以各位置之间可能会有较大的差距[因为暂时,硬件条件并不会使得整块可供分配的内存id映射被用尽]
stack:
- 8MB
- 向下拓展[地址高标号低]
Data:
- 用于存放程序开始时分配的数据
- 存放全局变量
Heap:
- 存放通过malloc/相关函数申请的变量,会动态变化
- 大的数据块会出现在靠近stack的位置,并向下增长,小的数据块会出现在靠近Data的位置,并向上增长
SharedLibraries:
- 存放库函数代码[一般在磁盘上]
- 在运行时动态加载到内存中
Unions
BufferOverFlow
代码注入攻击详解
举例: gets 会不断读取字符串,直至收到一个’\0’
1
2
3
4
5
6 void echo()
{
char buf[4];/* Way too small*/
gets(buf);
puts(buf);
}此时,若输入大于4个字符,echo还是可以接收
查看汇编代码可以看到,调用echo的时候给stackFrame分配了24byte的空间
如果输入大于23个字符,就会报出 segment fault
- 这时候该函数的返回位置可能被溢出的字符串覆盖,使得函数不会到main这个接口,而是进入一个新的地区
- 这就是代码注入攻击
小于23就没事,
How to Avoid
- 使用安全的替代
- fgets-> gets
- strncopy-> strcopy
- scanf(“%ns”)-> scanf(“%s”)
- Randomized stack offsets– 地址空间布局随机化
- 使得每次程序运行的时候,它分配到的缓冲区长度都是变化的
- None executable code segments
- 在可读/可写等内存标识之外增加一个 “execute” 权限
- stack canary 栈保护机制
- 程序会检测到栈溢出的问题并返回
A Skill to Avoid Randomized stack offset/None executable code segments
- 但是躲不开canary
Gadget
A Example:
p后面的值恰好和mov rax rdi 相等,结尾又是一个c3,因此这一段额外的代码会在p赋值之后执行,并返回.
这样就实现了在代码中插入一定量的自己的小代码,返回后就可以通过获取rsp栈中的代码,来将之前的代码块拼接一起执行.
GDB Trick
disass [FUNC_NAME]
解析对应函数的汇编代码
CSAPP Machine Level Programming