-
-
Notifications
You must be signed in to change notification settings - Fork 372
Make havoc_mutations Available for Custom Inputs #2202
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
can you do this by,
|
Theoretically yes but practically no. I would like to have the system mutate both parts of the input in all the ways the havoc mutators would. So yes, I can define two mutators, one for each part, but they'd have to wrap the logic of all the havoc mutators. This would lead to lots of code duplication, since I'd essentially have to copy all the havoc mutators' logic into the mutate function of these two new mutators and select randomly which one to use. Plus it may be better to have one large list of mutators for the mutation scheduler to work better instead of having only two which consist of randomness opaque to the mutation scheduler. |
ok. i understand. i think what you want is a mutator that takes closure to extract ranges (or some parts of the input), and do the mutations. then you put plug this mutator with the existing havoc_mutation |
That's exactly the issue. How would I do this? The existing havoc_mutations don't seem to have an interface for dynamic insertion of data. |
i still don't get what you want to achieve. |
Alright, let me start from the beginning. I have an struct that looks as follows (with only two parts for simplicity's sake, but this should work with n parts in the end): struct MyComplexCustomInput {
part1: Vec<u8>,
part2: Vec<u8>,
...
} I want to end up with a system where the operations defined in the /// Contains an internal bytes Vector
pub trait HasBytesVec {
/// The internal bytes map
fn bytes(&self) -> &[u8];
/// The internal bytes map (as mutable borrow)
fn bytes_mut(&mut self) -> &mut Vec<u8>;
} This is no issue if my Input has only one struct MySimpleCustomInput {
part1: Vec<u8>,
}
impl HasBytesVec for MySimpleCustomInput {
fn bytes(&self) -> &[u8] {
&self.part1
}
fn bytes_mut(&mut self) -> &mut Vec<u8> {
&mut self.part1
}
}
...
let mut stages = tuple_list!(StdMutationalStage::new(StdScheduledMutator::new(havoc_mutations())));
... This works. It mutates My proposal would be to add something like this: fn havoc_mutations_on_input_part<I>(extractor: FnMut(I) -> &mut Vec<u8>) -> HavocMutationsType<I> {
BitFlipMutator::new(extractor),
ByteFlipMutator::new(extractor),
...
}
fn havoc_mutations<I>() -> HavocMutationsType<I> where I: HasBytesVec {
havoc_mutations_on_input_part(|input: I| input.bytes_mut())
}
let mut stages = tuple_list!(StdMutationalStage::new(StdScheduledMutator::new(
havoc_mutations_on_input_part(|input| &mut input.part1)
.merge(havoc_mutations_on_input_part(|input| &mut input.part2))
)));
// stages now contains mutators to mutate part1 and part2 in all the ways havoc_mutations would I might just fundamentally miss something. If there is a simpler solution, please let me know! |
so what you actually wants to do is to make each of the |
first, there are 3 things
now, can you not just extract the parts you want in the Mutator, make it as the |
For example; can you do like this to implement your goal?
|
I want to find a solution that is transparent to the wrapping mutation scheduler, so that it has full control over all mutators on all parts of the input (i.e. no further random selection opaque to the main scheduler). I've got an idea, will report back once I know more. Thank you for your ideas so far, they really helped! |
Alright, I've implemented what I think you suggested: use std::borrow::Cow;
use libafl::{
inputs::{BytesInput, HasBytesVec, Input, UsesInput},
mutators::{MutationResult, Mutator},
Error,
};
use libafl_bolts::Named;
pub struct MappingMutator<IO, S> {
extractor: for<'a> fn(&'a mut IO) -> &'a mut Vec<u8>,
injector: for<'b> fn(&'b mut IO, &'b [u8]),
inner: Box<dyn Mutator<BytesInput, S>>,
}
impl<IO, S> MappingMutator<IO, S> {
pub fn new(
extractor: for<'a> fn(&'a mut IO) -> &'a mut Vec<u8>,
injector: for<'b> fn(&'b mut IO, &'b [u8]),
inner: Box<dyn Mutator<BytesInput, S>>,
) -> Self {
Self {
extractor,
injector,
inner,
}
}
}
impl<S, IO> Mutator<IO, S> for MappingMutator<IO, S>
where
S: UsesInput<Input = IO>,
IO: Input,
{
fn mutate(&mut self, state: &mut S, input: &mut IO) -> Result<MutationResult, Error> {
let extracted = (self.extractor)(input).clone();
let mut mapped_input = BytesInput::new(extracted);
let res = self.inner.mutate(state, &mut mapped_input);
(self.injector)(input, mapped_input.bytes());
res
}
}
impl<IO, S> Named for MappingMutator<IO, S> {
fn name(&self) -> &Cow<'static, str> {
&Cow::Borrowed("MappingMutator")
}
} Used like this: let mut stages = tuple_list!(StdMutationalStage::new(StdScheduledMutator::new(
tuple_list!(MappingMutator::new(
|input: &mut Base64Input| &mut input.raw_data,
|input, bytes| { input.raw_data = bytes.to_vec() },
Box::new(BitFlipMutator::new())
))
))); However, I really don't like the copying the vector back and forth. But I also couldn't get this to work with just passing around references, no matter how I implemented a custom So:
|
yes
you can make each of the
i think you have to do it manually. (i'd ask chatgpt4/claude to write it for me) @addisoncrump you have an idea? |
also @domenukk |
these the code in |
For the copying part, I'm working on a |
you mean |
BytesSubInput, sorry. It can be used with any input then |
See #2220 for |
Alright, I've had another play around. And I'm pretty sure what I'm trying to do is still not possible without reimplementing all mutators in
I'm still thinking that a wrapper mutator, which extracts the specified part of the Am I still missing something? |
I don't fully understand why you want a mapping closure? Just implement the trait for your input - I mean, you need your input to implement
Other option would be to add the option to skip parts of the input to MultipartInput mutators? I feel like an example would help (IIRC there was an example in the PR?) |
I'm sorry for the confusion. I'll try to summarise my requirements for this custom Conceptually, I'm doing differential fuzzing on two implementations of the same command line utility (in my case GNU coreutils vs. uutils coreutils). I want to ensure they behave the same, no matter what combination of command line arguments they are presented with. Manual testing could look something like this (from #2220): echo "This is a stdin byte array" | binary_under_test --arg1_with_param "value of param for arg1" --arg2_without_param --arg3_without_param --arg4_with_param "some value"
echo "This is another byte array for stdin" | binary_under_test --arg1_with_param "mutated value of param for arg1"
echo "More stdin" | binary_under_test --arg2_without_param --arg3_without_param I have a few types of parts that I need to have between
I would like to mutate this custom
|
Hey, that's what I needed! What I've currently got: use std::borrow::Cow;
use libafl::{
inputs::{MutVecInput, UsesInput},
mutators::{MutationResult, Mutator},
Error,
};
use libafl_bolts::Named;
pub struct MappingMutator<S, M>
where
S: UsesInput,
for<'a> M: Mutator<MutVecInput<'a>, S>,
{
extractor: for<'a> fn(&'a mut S::Input) -> &'a mut Vec<u8>,
inner: M,
}
impl<S, M> MappingMutator<S, M>
where
S: UsesInput,
for<'a> M: Mutator<MutVecInput<'a>, S>,
{
pub fn new(extractor: for<'a> fn(&'a mut S::Input) -> &'a mut Vec<u8>, inner: M) -> Self {
Self { extractor, inner }
}
}
impl<S, M> Mutator<S::Input, S> for MappingMutator<S, M>
where
S: UsesInput,
for<'a> M: Mutator<MutVecInput<'a>, S>,
{
fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result<MutationResult, Error> {
let mut mut_vec_input: MutVecInput = (self.extractor)(input).into();
self.inner.mutate(state, &mut mut_vec_input)
}
}
impl<S, M> Named for MappingMutator<S, M>
where
S: UsesInput,
for<'a> M: Mutator<MutVecInput<'a>, S>,
{
fn name(&self) -> &Cow<'static, str> {
&Cow::Borrowed("MappingMutator")
}
} which is then used like this: let mut stages = tuple_list!(StdMutationalStage::new(StdScheduledMutator::new(
tuple_list!(
MappingMutator::new(
|i: &mut Base64Input| i.extract_stdin(),
BitFlipMutator::new()
),
Base64FlipDecodeMutator,
Base64FlipIgnoreGarbageMutator,
Base64WrapContentMutator,
Base64FlipWrapMutator,
)
))); The only thing I need now is a way to map this new |
(Even better, it's very easy to write something similar for optional args, as in where the extractor returns an |
I have just copy-pasted the entire list of |
Happy you're getting somewhere! :) Yes, splicing on your custom type cannot "just work", you could for example wrap these mutators with your own that grabs a parameter from the other input and just splices that part (or something). Or just levae them all. /edit: BTW: you can do |
I will try to at some point create a PR with all this logic, with an interface which should make it very easy to mutate byte vector parts of custom inputs. I'd maybe also include a baby fuzzer example with a simple custom Would you be interested in such a PR? |
Definitely sounds useful! The only question that remains (probably for @addisoncrump ) is if this cannot already be done with Multipart inputs, it still feels very closely related.. |
@addisoncrump If you can't be bothered to read the entire thread, here's the gist: Requirements and Problem |
It is definitely possible to perform a mapping operation as you describe across a tuple. I'll implement the machinery for this real quick. You will need to implement a custom version of crossover. That's just gotta happen, sorry! Multipart is almost equipped to handle this, except for the no argument case. To handle this, I propose the following PR:
Then, we can implement what you describe here very easily with
And then the mapper would simply transform the stdin or Arg to a mutable slice as needed. |
Awesome, thank you!
Fair enough. For your proposal: I'm not sure where I'm also not sure if the approach outlined here might not be better (at least it would certainly be more flexible, and I don't think it would be any less performant). This would not use let mut stages = tuple_list!(StdMutationalStage::new(StdScheduledMutator::new(
havoc_mutations_mapped(|i: MyCustomInput| -> Vec<u8> {i.extract_required_input_part()})
.extend(havoc_mutations_mapped_optional(|i: MyCustomInput| -> Option<Vec<u8>> {i.extract_optional_input_part()})
.extend(havoc_mutations_mapped_optional(MyCustomInput::exteract_optional_input_part2) // more concise
.append(MyCustomInputToggleOptionalInputPartMutator::new()) // or any other futher mutators
))); |
Here's the tuple mapping trait: #2247 |
You can directly return the |
Can this issue be closed? |
I'll try to finish the implementation properly of this and create a PR, but it'll be a few more weeks, so maybe leave it open for now? |
Uh oh!
There was an error while loading. Please reload this page.
I have a custom
Input
type I'm doing fuzzing with. It contains two fields in the shape of aVec<u8>
. I'd love to be able to use havoc mutations on both separately, in addition to further custom mutators. Currently, all havoc mutators rely on theInput
implementingHasBytesVec
, which means that I can't apply them to two parts separately.I'd love to have, next to the now default
havoc_mutations()
, a method which takes a closure mapping between theInput
type and the (mutable) bytes slice used by the mutators.havoc_mutations()
could then just restrict itsInput
s toHasBytesVec
and call the new method with the extraction methods defined in its trait.The text was updated successfully, but these errors were encountered: