AddressSanitizer 是一个内存检测工具。支持GCC 4.8 及以上。在编译时添加-fsanitize=address
选项,如果为了得到更全面的信息可以用-fno-omit-frame-pointer
。
它可以检测出以下错误:
use after free
Heap buffer overflow
int main(int argc, char **argv) {
int *array = new int[100];
array[0] = 0;
int res = array[argc + 100]; // BOOM
delete [] array;
return res;
}
g++ -fsanitize=address
Stack buffer overflow
int main(int argc, char **argv) {
int stack_array[100];
stack_array[1] = 0;
return stack_array[argc + 100]; // BOOM
}
Global buffer overflow
int global_array[100] = {-1};
int main(int argc, char **argv) {
return global_array[argc + 100]; // BOOM
}
Use after return
int *ptr;
__attribute__((noinline))
void FunctionThatEscapesLocalObject() {
int local[100];
ptr = &local[0];
}
int main(int argc, char **argv) {
FunctionThatEscapesLocalObject();
return ptr[argc];
}
Use after scope
volatile int *p = 0;
int main() {
{
int x = 0;
p = &x;
}
*p = 5;
return 0;
}
Initialization order bugs
Memory leaks
#include <stdlib.h>
void *p;
int main() {
p = malloc(7);
p = 0; // The memory is leaked here.
return 0;
}
原理
原理上还是分为2部分:
- 插桩(Instrumentation)
- hook动态运行库(Run-time library)
插桩主要是对访问内存的操作(store,load,alloca等),将它们进行处理。
hook动态运行库主要提供将malloc,free等系统调用函数hook住。
该算法的思路是:如果想防住Buffer Overflow漏洞,只需要在每块内存区域右端(或两端,能防overflow和underflow)加一块区域(RedZone),使RedZone的区域的影子内存(Shadow Memory)设置为不可写即可。具体的示意图如下图所示。
image.png这样可以有效的防止buffer overflow。
hook malloc/free函数。在malloc函数中额外的分配了Redzone区域的内存,将与Redzone区域对应的影子内存加锁,主要的内存区域对应的影子内存不加锁。
free函数将所有分配的内存区域加锁,并放到了隔离区域的队列中(保证在一定的时间内不会再被malloc函数分配),可检测Use after free类的问题。
参考资料
1、https://github.com/google/sanitizers/wiki/AddressSanitizer
2、https://www.bynav.com/cn/resource/bywork/healthy-work/70.html?id=35
网友评论