lain/lib.rs
1//! This crate provides functionality one may find useful while developing a fuzzer. A recent
2//! nightly Rust build is required for the specialization feature.
3//!
4//! Please consider this crate in "beta" and subject to breaking changes for minor version releases for pre-1.0.
5//!
6//! [](https://crates.io/crates/lain)
7//! [](https://docs.rs/lain)
8//!
9//! ## Documentation
10//!
11//! Please refer to [the wiki](https://github.com/microsoft/lain/wiki) for a high-level overview.
12//!
13//! For API documentation: https://docs.rs/lain
14//!
15//! ## Installation
16//!
17//! Lain requires rust nightly builds for specialization support.
18//!
19//! Add the following to your Cargo.toml:
20//!
21//! ```toml
22//! [dependencies]
23//! lain = "0.2"
24//! ```
25//!
26//! ## Example Usage
27//!
28//! ```rust
29//! extern crate lain;
30//!
31//! use lain::prelude::*;
32//! use lain::rand;
33//! use lain::hexdump;
34//!
35//! #[derive(Debug, Mutatable, NewFuzzed, BinarySerialize)]
36//! struct MyStruct {
37//! field_1: u8,
38//!
39//! #[lain(bits = 3)]
40//! field_2: u8,
41//!
42//! #[lain(bits = 5)]
43//! field_3: u8,
44//!
45//! #[lain(min = 5, max = 10000)]
46//! field_4: u32,
47//!
48//! #[lain(ignore)]
49//! ignored_field: u64,
50//! }
51//!
52//! fn main() {
53//! let mut mutator = Mutator::new(rand::thread_rng());
54//!
55//! let mut instance = MyStruct::new_fuzzed(&mut mutator, None);
56//!
57//! let mut serialized_data = Vec::with_capacity(instance.serialized_size());
58//! instance.binary_serialize::<_, BigEndian>(&mut serialized_data);
59//!
60//! println!("{:?}", instance);
61//! println!("hex representation:\n{}", hexdump(&serialized_data));
62//!
63//! // perform small mutations on the instance
64//! instance.mutate(&mut mutator, None);
65//!
66//! println!("{:?}", instance);
67//! }
68//!
69//! // Output:
70//! //
71//! // MyStruct { field_1: 95, field_2: 5, field_3: 14, field_4: 8383, ignored_field: 0 }
72//! // hex representation:
73//! // ------00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
74//! // 0000: 5F 75 00 00 20 BF 00 00 00 00 00 00 00 00 _u...¿........
75//! // MyStruct { field_1: 160, field_2: 5, field_3: 14, field_4: 8383, ignored_field: 0 }
76//! ```
77//!
78//! A complete example of a fuzzer and its target can be found in the [examples](examples/)
79//! directory. The server is written in C and takes data over a TCP socket, parses a message, and
80//! mutates some state. The fuzzer has Rust definitions of the C data structure and will send fully
81//! mutated messages to the server and utilizes the `Driver` object to manage fuzzer threads and
82//! state.
83//!
84//! # Contributing
85//!
86//! This project welcomes contributions and suggestions. Most contributions require you to agree to
87//! a Contributor License Agreement (CLA) declaring that you have the right to, and actually do,
88//! grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
89//!
90//! When you submit a pull request, a CLA-bot will automatically determine whether you need to
91//! provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the
92//! instructions provided by the bot. You will only need to do this once across all repos using our
93//! CLA.
94//!
95//! This project has adopted the [Microsoft Open Source Code of
96//! Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of
97//! Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact
98//! [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or
99//! comments.
100
101#![feature(specialization)]
102#![feature(min_const_generics)]
103
104extern crate num;
105extern crate num_derive;
106extern crate num_traits;
107extern crate self as lain;
108
109pub extern crate byteorder;
110pub extern crate field_offset;
111pub extern crate lain_derive;
112pub extern crate lazy_static;
113pub extern crate rand;
114
115pub use lain_derive::*;
116
117#[macro_use]
118pub extern crate log;
119
120#[doc(hidden)]
121pub mod buffer;
122#[doc(hidden)]
123pub mod dangerous_numbers;
124pub mod driver;
125#[doc(hidden)]
126pub mod mutatable;
127pub mod mutator;
128#[doc(hidden)]
129pub mod new_fuzzed;
130pub mod prelude;
131pub mod traits;
132pub mod types;
133
134pub fn hexdump(data: &[u8]) -> String {
135 let mut ret = "------".to_string();
136 for i in 0..16 {
137 ret += &format!("{:02X} ", i);
138 }
139
140 let mut ascii = String::new();
141 for (i, b) in data.iter().enumerate() {
142 if i % 16 == 0 {
143 ret += &format!("\t{}", ascii);
144 ascii.clear();
145 ret += &format!("\n{:04X}:", i);
146 }
147
148 ret += &format!(" {:02X}", b);
149 // this is the printable ASCII range
150 if *b >= 0x20 && *b <= 0x7f {
151 ascii.push(*b as char);
152 } else {
153 ascii.push('.');
154 }
155 }
156
157 if data.len() % 16 != 0 {
158 for _i in 0..16 - (data.len() % 16) {
159 ret += " ";
160 }
161 }
162
163 ret += &format!("\t{}", ascii);
164 ascii.clear();
165
166 ret
167}