libfuzzer新手入门

题外话

现在搜索引擎已经很少搜到技术博客了,搜到的技术文章也都是2020年左右的,前几年个人建站的博客非常火,但是现在落寞了,思考了下原因,个人博客是没有正反馈,不像csdn有创作激励,有流量等等。

今年7月份我也转向了csdn写博客,用流量券曝光,有点赞、收藏、关注,这些正反馈,是我创作的动力,respect!

libfuzzer

libFuzzer 是一个由 LLVM 项目提供的功能强大的模糊测试工具,它是一个内置于 LLVM 编译器中的覆盖引导的进化模糊测试引擎

前置

安装部署LLVM

编写用例

可以看到FuzzMe函数,如果DataSize =3并且data=“FUZ”时,调用Data[3],会发生内存越界错误

#include <iostream>
#include <cstdint>
#include <cstddef>
using namespace std;

// clang++ -fsanitize=fuzzer,address fuzz_target.cc -o fuzz_target
// ./fuzz_target corpus -max_total_time=30
bool FuzzMe(const uint8_t *Data, size_t DataSize) {
  return DataSize >= 3 &&
      Data[0] == 'F' &&
      Data[1] == 'U' &&
      Data[2] == 'Z' &&
      Data[3] == 'Z';  
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
  FuzzMe(Data, Size);
  return 0;
}

编译

clang++ -fsanitize=fuzzer,address fuzz_target.cc -o fuzz_target

创建初始种子 corpus (corpus 目录)

创建一个包含一些初始输入样本的目录,这些样本将被 libFuzzer 用来开始模糊测试。

mkdir corpus
# 将一些初始样本放入 corpus 目录。
# 例如,你可以使用一些简单的文本文件或二进制文件。

运行

./fuzz_target corpus -max_total_time=30

如果不设定时间和次数,程序会一直运行下去直至崩溃

使用 -max_total_time=N 来设置 libFuzzer 运行的总时间(秒)。

使用 -runs=N 来设置 libFuzzer 执行的测试用例次数。

打印结果

[root@pekphis94681:jishufenxiang]# ./fuzz_target corpus -max_total_time=30
INFO: Seed: 1131142770
INFO: Loaded 1 modules   (9 inline 8-bit counters): 9 [0x5a7f00, 0x5a7f09), 
INFO: Loaded 1 PC tables (9 PCs): 9 [0x56b1b8,0x56b248), 
INFO:       27 files found in corpus
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 32720 bytes
INFO: seed corpus: files: 27 min: 1b max: 32720b total: 107413b rss: 28Mb
#28     INITED cov: 7 ft: 7 corp: 5/14b exec/s: 0 rss: 29Mb
=================================================================
==1776595==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000010573 at pc 0x000000550593 bp 0x7fffa7186990 sp 0x7fffa7186988
READ of size 1 at 0x602000010573 thread T0
    #0 0x550592 in FuzzMe(unsigned char const*, unsigned long) (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x550592)
    #1 0x550634 in LLVMFuzzerTestOneInput (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x550634)
    #2 0x458771 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x458771)
    #3 0x457eb5 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x457eb5)
    #4 0x45a157 in fuzzer::Fuzzer::MutateAndTestOne() (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x45a157)
    #5 0x45ae55 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x45ae55)
    #6 0x44980e in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x44980e)
    #7 0x472652 in main (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x472652)
    #8 0x7f7b714f7082 in __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:308:16
    #9 0x41e5ad in _start (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x41e5ad)

0x602000010573 is located 0 bytes to the right of 3-byte region [0x602000010570,0x602000010573)
allocated by thread T0 here:
    #0 0x51e2dd in malloc (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x51e2dd)
    #1 0x432997 in operator new(unsigned long) (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x432997)
    #2 0x457eb5 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x457eb5)
    #3 0x45a157 in fuzzer::Fuzzer::MutateAndTestOne() (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x45a157)
    #4 0x45ae55 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x45ae55)
    #5 0x44980e in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x44980e)
    #6 0x472652 in main (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x472652)
    #7 0x7f7b714f7082 in __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: heap-buffer-overflow (/mnt/mount_data2/k30056123/jishufenxiang/fuzz_target+0x550592) in FuzzMe(unsigned char const*, unsigned long)
Shadow bytes around the buggy address:
  0x0c047fffa050: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
  0x0c047fffa060: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
  0x0c047fffa070: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
  0x0c047fffa080: fa fa fd fa fa fa fd fd fa fa fd fd fa fa fd fd
  0x0c047fffa090: fa fa fd fa fa fa fd fa fa fa fd fd fa fa fd fa
=>0x0c047fffa0a0: fa fa fd fa fa fa fd fa fa fa fd fa fa fa[03]fa
  0x0c047fffa0b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fffa0c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fffa0d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fffa0e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fffa0f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==1776595==ABORTING
MS: 1 EraseBytes-; base unit: de3a753d4f1def197604865d76dba888d6aefc71
0x46,0x55,0x5a,
FUZ
artifact_prefix='./'; Test unit written to ./crash-0eb8e4ed029b774d80f2b66408203801cb982a60
Base64: RlVa

报错:heap-buffer-overflow内存越界错误

查看种子文件crash-0eb8e4ed029b774d80f2b66408203801cb982a60内容为FUZ

查看代码覆盖率

clang++ -fsanitize=fuzzer,address -fprofile-instr-generate -fcoverage-mapping fuzz_target.cc -o fuzz_target

加上fprofile-instr-generate -fcoverage-mapping 这两个编译选项

创建目录

mkdir CORPUS

运行:

echo -n F > CORPUS/A && ./fuzz_target CORPUS/* &&              llvm-profdata merge -sparse *.profraw -o default.profdata &&              llvm-cov show fuzz_target -instr-profile=default.profdata -name=FuzzMe

其中FuzzMe是函数名

打印信息:

红色行表示代码没有被运行

参考:

kimi大模型

libFuzzer Tutorial

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值