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:

image-20221007163747876

Buffer OverFlow

image-20221007163839893
  • 注: 内存是按照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

  1. 使用安全的替代
    1. fgets-> gets
    2. strncopy-> strcopy
    3. scanf(“%ns”)-> scanf(“%s”)
  2. Randomized stack offsets– 地址空间布局随机化
    1. 使得每次程序运行的时候,它分配到的缓冲区长度都是变化的
  3. None executable code segments
    1. 在可读/可写等内存标识之外增加一个 “execute” 权限
  4. stack canary 栈保护机制
    1. image-20221007201652095
    2. 程序会检测到栈溢出的问题并返回

A Skill to Avoid Randomized stack offset/None executable code segments

  • 但是躲不开canary

Gadget

A Example:image-20221008122557042

p后面的值恰好和mov rax rdi 相等,结尾又是一个c3,因此这一段额外的代码会在p赋值之后执行,并返回.

这样就实现了在代码中插入一定量的自己的小代码,返回后就可以通过获取rsp栈中的代码,来将之前的代码块拼接一起执行.

GDB Trick

disass [FUNC_NAME]

解析对应函数的汇编代码

CSAPP Machine Level Programming

http://nmhn.github.io/1007csapp_CPu.html

Author

YSH

Posted on

2022-10-07

Updated on

2022-10-13

Licensed under