• Home
Name Date Size #Lines LOC

..--

cmake/external/03-May-2024-241208

examples/03-May-2024-960646

port/03-May-2024-5919

src/03-May-2024-3,6672,763

.clang-formatD03-May-202422 21

.gitignoreD03-May-20247 21

.travis.ymlD03-May-20241.8 KiB6756

AUTHORSD03-May-2024329 96

Android.bpD03-May-20241.8 KiB6156

CMakeLists.txtD03-May-20245.8 KiB163133

CONTRIBUTINGD03-May-20241.4 KiB2824

LICENSED03-May-202411.1 KiB203169

METADATAD03-May-2024427 1615

MODULE_LICENSE_APACHE2D03-May-20240

OWNERSD03-May-2024127 64

README.mdD03-May-20246.8 KiB166133

libprotobuf-mutator.pc.inD03-May-2024302 108

libprotobuf-mutatorConfig.cmake.inD03-May-2024141 63

README.md

1# libprotobuf-mutator
2
3[![TravisCI Build Status](https://travis-ci.org/google/libprotobuf-mutator.svg?branch=master)](https://travis-ci.org/google/libprotobuf-mutator)
4[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/libprotobuf-mutator.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html#libprotobuf-mutator)
5
6## Overview
7libprotobuf-mutator is a library to randomly mutate
8[protobuffers](https://github.com/google/protobuf). <BR>
9It could be used together with guided fuzzing engines, such as [libFuzzer](http://libfuzzer.info).
10
11## Quick start on Debian/Ubuntu
12
13Install prerequisites:
14
15```
16sudo apt-get update
17sudo apt-get install protobuf-compiler libprotobuf-dev binutils cmake \
18  ninja-build liblzma-dev libz-dev pkg-config autoconf libtool
19```
20
21Compile and test everything:
22
23```
24mkdir build
25cd build
26cmake .. -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Debug
27ninja check
28```
29
30Clang is only needed for libFuzzer integration. <BR>
31By default, the system-installed version of
32[protobuf](https://github.com/google/protobuf) is used.  However, on some
33systems, the system version is too old.  You can pass
34`LIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON` to cmake to automatically download and
35build a working version of protobuf.
36
37Installation:
38
39```
40ninja
41sudo ninja install
42```
43
44This installs the headers, pkg-config, and static library.
45By default the headers are put in `/usr/local/include/libprotobuf-mutator`.
46
47## Usage
48
49To use libprotobuf-mutator simply include
50[mutator.h](/src/mutator.h) and
51[mutator.cc](/src/mutator.cc) into your build files.
52
53The `ProtobufMutator` class implements mutations of the protobuf
54tree structure and mutations of individual fields.
55The field mutation logic is very basic --
56for better results you should override the `ProtobufMutator::Mutate*`
57methods with more sophisticated logic, e.g.
58using [libFuzzer](http://libfuzzer.info)'s mutators.
59
60To apply one mutation to a protobuf object do the following:
61
62```
63class MyProtobufMutator : public protobuf_mutator::Mutator {
64 public:
65  // Optionally redefine the Mutate* methods to perform more sophisticated mutations.
66}
67void Mutate(MyMessage* message) {
68  MyProtobufMutator mutator;
69  mutator.Seed(my_random_seed);
70  mutator.Mutate(message, 200);
71}
72```
73
74See also the `ProtobufMutatorMessagesTest.UsageExample` test from
75[mutator_test.cc](/src/mutator_test.cc).
76
77## Integrating with libFuzzer
78LibFuzzerProtobufMutator can help to integrate with libFuzzer. For example
79
80```
81#include "src/libfuzzer/libfuzzer_macro.h"
82
83DEFINE_PROTO_FUZZER(const MyMessageType& input) {
84  // Code which needs to be fuzzed.
85  ConsumeMyMessageType(input);
86}
87```
88
89Please see [libfuzzer_example.cc](/examples/libfuzzer/libfuzzer_example.cc) as an example.
90
91### Mutation post-processing (experimental)
92Sometimes it's necessary to keep particular values in some fields without which the proto
93is going to be rejected by fuzzed code. E.g. code may expect consistency between some fields
94or it may use some fields as checksums. Such constraints are going to be significant bottleneck
95for fuzzer even if it's capable of inserting acceptable values with time.
96
97PostProcessorRegistration can be used to avoid such issue and guide your fuzzer towards interesting
98code. It registers callback which will be called for each message of particular type after each mutation.
99
100```
101static protobuf_mutator::libfuzzer::PostProcessorRegistration<MyMessageType> reg = {
102    [](MyMessageType* message, unsigned int seed) {
103      TweakMyMessage(message, seed);
104    }};
105
106DEFINE_PROTO_FUZZER(const MyMessageType& input) {
107  // Code which needs to be fuzzed.
108  ConsumeMyMessageType(input);
109}
110```
111Optional: Use seed if callback uses random numbers. It may help later with debugging.
112
113Important: Callbacks should be deterministic and avoid modifying good messages.
114Callbacks are called for both: mutator generated and user provided inputs, like
115corpus or bug reproducer. So if callback performs unnecessary transformation it
116may corrupt the reproducer so it stops triggering the bug.
117
118Note: You can add callback for any nested message and you can add multiple callbacks for
119the same message type.
120```
121DEFINE_PROTO_FUZZER(const MyMessageType& input) {
122  static PostProcessorRegistration reg1 = {
123      [](MyMessageType* message, unsigned int seed) {
124        TweakMyMessage(message, seed);
125      }};
126  static PostProcessorRegistration reg2 = {
127      [](MyMessageType* message, unsigned int seed) {
128        DifferentTweakMyMessage(message, seed);
129      }};
130  static PostProcessorRegistration reg_nested = {
131      [](MyMessageType::Nested* message, unsigned int seed) {
132        TweakMyNestedMessage(message, seed);
133      }};
134
135  // Code which needs to be fuzzed.
136  ConsumeMyMessageType(input);
137}
138```
139## UTF-8 strings
140"proto2" and "proto3" handle invalid UTF-8 strings differently. In both cases
141string should be UTF-8, however only "proto3" enforces that. So if fuzzer is
142applied to "proto2" type libprotobuf-mutator will generate any strings including
143invalid UTF-8. If it's a "proto3" message type, only valid UTF-8 will be used.
144
145## Users of the library
146* [Chromium](https://cs.chromium.org/search/?q=DEFINE_.*._PROTO_FUZZER%5C\()
147* [Envoy](https://github.com/envoyproxy/envoy/search?q=DEFINE_TEXT_PROTO_FUZZER+OR+DEFINE_PROTO_FUZZER+OR+DEFINE_BINARY_PROTO_FUZZER&unscoped_q=DEFINE_TEXT_PROTO_FUZZER+OR+DEFINE_PROTO_FUZZER+OR+DEFINE_BINARY_PROTO_FUZZER&type=Code)
148* [LLVM](https://github.com/llvm-mirror/clang/search?q=DEFINE_TEXT_PROTO_FUZZER+OR+DEFINE_PROTO_FUZZER+OR+DEFINE_BINARY_PROTO_FUZZER&unscoped_q=DEFINE_TEXT_PROTO_FUZZER+OR+DEFINE_PROTO_FUZZER+OR+DEFINE_BINARY_PROTO_FUZZER&type=Code)
149
150## Bugs found with help of the library
151
152### Chromium
153* [AppCache exploit](http://www.powerofcommunity.net/poc2018/ned.pdf) ([Actual still restricted bug](https://bugs.chromium.org/p/chromium/issues/detail?id=888926))
154* [Stack Buffer Overflow in QuicClientPromisedInfo](https://bugs.chromium.org/p/chromium/issues/detail?id=777728)
155* [null dereference in sqlite3ExprCompare](https://bugs.chromium.org/p/chromium/issues/detail?id=911251)
156### Envoy
157* [strftime overflow](https://github.com/envoyproxy/envoy/pull/4321)
158* [Heap-use-after-free in Envoy::Upstream::SubsetLoadBalancer::updateFallbackSubset](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8028)
159* [Heap-use-after-free in Envoy::Secret::SecretManagerImpl](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11231)
160* [Heap-buffer-overflow in Envoy::Http::HeaderString](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10038)
161
162## Related materials
163* [Attacking Chrome IPC: Reliably finding bugs to escape the Chrome sandbox](https://media.ccc.de/v/35c3-9579-attacking_chrome_ipc)
164* [Structure-aware fuzzing for Clang and LLVM with libprotobuf-mutator](https://www.youtube.com/watch?v=U60hC16HEDY)
165* [Structure-Aware Fuzzing with libFuzzer](https://github.com/google/fuzzer-test-suite/blob/master/tutorial/structure-aware-fuzzing.md)
166