mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2025-06-23 03:35:03 +07:00
finish 5.4
This commit is contained in:
@ -204,3 +204,64 @@ p = *q;
|
||||
|
||||
|
||||
## 实例分析
|
||||
#### 检测指针变量的错误使用
|
||||
在检测指针变量的错误使用时,我们关心的是变量的状态。
|
||||
|
||||
下面看一个例子:
|
||||
```c
|
||||
int contrived(int *p, int *w, int x) {
|
||||
int *q;
|
||||
if (x) {
|
||||
kfree(w); // w free
|
||||
q = p;
|
||||
}
|
||||
[...]
|
||||
if (!x)
|
||||
return *w;
|
||||
return *q; // p use after free
|
||||
}
|
||||
int contrived_caller(int *w, int x, int *p) {
|
||||
kfree(p); // p free
|
||||
[...]
|
||||
int r = contrived(p, w, x);
|
||||
[...]
|
||||
return *w; // w use after free
|
||||
}
|
||||
```
|
||||
可以看到上面的代码可能出现 use-after-free 漏洞。
|
||||
|
||||
这里我们采用路径敏感的数据流分析,控制流图如下:
|
||||
|
||||

|
||||

|
||||
|
||||
调用图如下:
|
||||
|
||||

|
||||
|
||||
下面是用于检测指针变量错误使用的检测规则:
|
||||
```
|
||||
v 被分配空间 ==> v.start
|
||||
v.start: {kfree(v)} ==> v.free
|
||||
v.free: {*v} ==> v.useAfterFree
|
||||
v.free: {kfree(v)} ==> v.doubleFree
|
||||
```
|
||||
|
||||
分析过程从函数 contrived_call 的入口点开始,对于过程内代码的分析,使用深度优先遍历控制流图的方法,并使用基本块摘要进行辅助,而对于过程间的分析,选择在遇到函数调用时直接分析被调用函数内代码的方式,并使用函数摘要。
|
||||
|
||||
函数 contrived 中的路径有两条:
|
||||
- BB0->BB1->BB2->BB3->BB5->BB6:在进行到 BB5 时,BB5 的前置条件为 p.free, q.free 和 w.free,此时语句 `q1 = *q` 将触发 use-after-free 规则并设置 q.useAfterFree 状态。然后返回到函数 contrived_call 的 BB2,其前置条件为 p.useAfterFree, w.free,此时语句 `w1 = *w` 设置 w.useAfterFree。
|
||||
- BB0->BB1->BB3->BB4->BB6:该路径是安全的。
|
||||
|
||||
#### 检测缓冲区溢出
|
||||
在检测缓冲区溢出时,我们关心的是变量的取值,并在一些预定义的敏感操作所在的程序点上,对变量的取值进行检查。
|
||||
|
||||
下面是一些记录变量的取值的规则:
|
||||
```
|
||||
char s[n]; // len(s) = n
|
||||
strcpy(des, src); // len(des) > len(src)
|
||||
strncpy(des, src, n); // len(des) > min(len(src), n)
|
||||
s = "foo"; // len(s) = 4
|
||||
strcat(s, suffix); // len(s) = len(s) + len(suffix) - 1
|
||||
fgets(s, n, ...); // len(s) > n
|
||||
```
|
||||
|
Reference in New Issue
Block a user