这个问题的根源来自于此。
正如标题所说,问题是:;如何对ASAN(OR/AND-libfuzzer(指令的2个IR进行适当的单独编译&";。在我们深入研究实际问题之前,有一个例子可以在没有单独编译和IR层的情况下工作。
工作示例
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
char* sanitize_cookie_path(const char* cookie_path) {
size_t len;
char* new_path = strdup(cookie_path);
if (!new_path) {
return NULL;
}
if (new_path[0] == '"') {
memmove((void*)new_path, (const void*)(new_path + 1), strlen(new_path));
}
if (new_path[strlen(new_path) - 1] == '"') {
new_path[strlen(new_path) - 1] = 0x0;
}
if (new_path[0] !='/') {
free(new_path);
new_path = strdup("/");
return new_path;
}
len = strlen(new_path);
if (1 < len && new_path[len - 1] == '/') {
new_path[len - 1] = 0x0;
}
return new_path;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
char* string_ = new char[size + 1];
memcpy(string_, data, size);
string_[size] = 0x0;
sanitize_cookie_path(string_);
delete[] string_;
return 0;
}
上面的代码是用下面的命令编译的,工作正常:
$ clang++ -O0 -g -fno-omit-frame-pointer -fsanitize=address,fuzzer -fsanitize-coverage=trace-cmp,trace-gep,trace-div sanitize_cookie_path.c -o fuzzer
$ ./fuzzer
=================================================================
==10081==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000004f at pc 0x55ec692f7e51 bp 0x7ffde3767450 sp 0x7ffde3767448
实际问题
现在让任务稍微复杂一点。我有下面的一段代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stddef.h>
char* sanitize_cookie_path(const char* cookie_path) {
size_t len;
char* new_path = strdup(cookie_path);
if (!new_path) {
return NULL;
}
if (new_path[0] == '"') {
memmove((void*)new_path, (const void*)(new_path + 1), strlen(new_path));
}
if (new_path[strlen(new_path) - 1] == '"') {
new_path[strlen(new_path) - 1] = 0x0;
}
if (new_path[0] !='/') {
free(new_path);
new_path = strdup("/");
return new_path;
}
len = strlen(new_path);
if (1 < len && new_path[len - 1] == '/') {
new_path[len - 1] = 0x0;
}
return new_path;
}
// Ditch this part further
int main(int argc, char** argv) {
return 0;
}
//
上面代码的编译命令:
$ clang -O0 -emit-llvm sanitize_cookie_path.c -S -o sanitize_cookie_path.ll
下面的另一段代码:
#include <cstdio>
#include <cstdint>
#include <cstring>
char* sanitize_cookie_path(const char* cookie_path);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
char* string_ = new char[size + 1];
memcpy(string_, data, size);
string_[size] = 0x0;
sanitize_cookie_path(string_);
delete[] string_;
return 0;
}
上面代码的编译命令:
$ clang -O0 -emit-llvm fuzz_sanitize_cookie_path.cc -S -o fuzz_sanitize_cookie_path.ll
在这一点上,我调整了2个IR(解决C++名称篡改,删除"主要"部分(,使它们相互匹配,然后我用下面的命令编译它们并运行:
$ clang++ -O0 -g -fno-omit-frame-pointer -fsanitize=address,fuzzer -fsanitize-coverage=trace-cmp,trace-gep,trace-div sanitize_cookie_path.ll fuzz_sanitize_cookie_path.ll -o fuzzer
$ ./fuzzer
结果不是预期的,准确地说是:
=================================================================
==10186==ERROR: LeakSanitizer: detected memory leaks
,就sanitize_cookie_path
中的漏洞而言,这是不正确的。
我尝试了什么
下面我将列出我尝试执行的命令的一些变体及其各自的输出。
#1
$ clang -O0 -fno-omit-frame-pointer -fsanitize=address -fsanitize-coverage=trace-cmp,trace-gep,trace-div -emit-llvm sanitize_cookie_path.c -S -o sanitize_cookie_path.ll
$ clang -O0 -fno-omit-frame-pointer -fsanitize=address -fsanitize-coverage=trace-cmp,trace-gep,trace-div -emit-llvm fuzz_sanitize_cookie_path.cc -S -o fuzz_sanitize_cookie_path.ll
$ clang++ -O0 -g -fno-omit-frame-pointer -fsanitize=address,fuzzer -fsanitize-coverage=trace-cmp,trace-gep,trace-div sanitize_cookie_path.ll fuzz_sanitize_cookie_path.ll -o fuzzer
$ ./fuzzer
AddressSanitizer:DEADLYSIGNAL
=================================================================
==10333==ERROR: AddressSanitizer: SEGV on unknown address 0x01810fff7000 (pc 0x557746efa890 bp 0x7fff83a152a0 sp 0x7fff83a15230 T0)
==10333==The signal is caused by a READ memory access.
#2
$ clang -O0 -fno-omit-frame-pointer -fsanitize=address -fsanitize-coverage=trace-cmp,trace-gep,trace-div -emit-llvm sanitize_cookie_path.c -S -o sanitize_cookie_path.ll
$ clang -O0 -emit-llvm fuzz_sanitize_cookie_path.cc -S -o fuzz_sanitize_cookie_path.ll
$ clang++ -O0 -g -fno-omit-frame-pointer -fsanitize=address,fuzzer -fsanitize-coverage=trace-cmp,trace-gep,trace-div sanitize_cookie_path.ll fuzz_sanitize_cookie_path.ll -o fuzzer
$ ./fuzzer
AddressSanitizer:DEADLYSIGNAL
=================================================================
==10387==ERROR: AddressSanitizer: SEGV on unknown address 0x01810fff7001 (pc 0x561d9ef01d63 bp 0x7ffdd7eb7180 sp 0x7ffdd7eb7030 T0)
==10387==The signal is caused by a READ memory access.
#3
$ clang -O0 -fno-omit-frame-pointer -fsanitize=address -fsanitize-coverage=trace-cmp,trace-gep,trace-div -emit-llvm sanitize_cookie_path.c -S -o sanitize_cookie_path.ll
$ clang -O0 -emit-llvm fuzz_sanitize_cookie_path.cc -S -o fuzz_sanitize_cookie_path.ll
$ clang++ -O0 -g -fno-omit-frame-pointer -fsanitize=fuzzer -fsanitize-coverage=trace-cmp,trace-gep,trace-div sanitize_cookie_path.ll fuzz_sanitize_cookie_path.ll -o fuzzer
$ ./fuzzer
clang-14: error: linker command failed with exit code 1 (use -v to see invocation)
如何获得与工作示例中相同的结果,但需要单独编译我想让你看看这个问题的外观。
为了解决我的问题,谷歌/消毒液中以前的一个问题帮助了我。
Asan只传递具有消毒地址的仪器函数属性只有当-fsanitize=address为指定。因此,如果您拆分处理,您可能需要手动进行以某种方式
这意味着我坚持我的原始解决方案
$ clang -O0 -emit-llvm sanitize_cookie_path.c -S -o sanitize_cookie_path.ll
$ clang -O0 -emit-llvm fuzz_sanitize_cookie_path.cc -S -o fuzz_sanitize_cookie_path.ll
$ clang++ -O0 -g -fno-omit-frame-pointer -fsanitize=address,fuzzer -fsanitize-coverage=trace-cmp,trace-gep,trace-div sanitize_cookie_path.ll fuzz_sanitize_cookie_path.ll -o fuzzer
但在我链接sanitize_cookie_path.ll
和fuzz_sanitize_cookie_path.ll
(第三个命令(之前,我解决了C++名称篡改,删除了main
函数and在IR级别上为sanitize_cookie_path
函数添加了一个消毒地址属性。
现在,工作示例和单独的编译都是一样的。