Fuzz BitField of various sizes

418 views
Skip to first unread message

Zero Lockout

unread,
Sep 23, 2016, 5:15:25 AM9/23/16
to boofuzz
Hello,

As the next challenge I am facing is with fuzzing protocol header fields of various bit lengths.
For example IPv6 header version field is 4bits long and should contain 0b0110 (0x6), and after that follows a 8bit long field specifying the traffic class.
However, Boofuzz in primitives/bit_field.py will pad the bit stream to the next byte boundary by appending zeroes, therefore introducing additional bits and making test case incompatible with IPv6 header specification.

My current fuzzing test case is as follows:
s_bit_field(0b0110, 4, fuzzable = False, name = "Version")
s_bit_field(0b00000000, 8, name = "Traffic_Class")
s_bit_field(0b00000000000000000000, 20, name = "Flow_Label")
s_bit_field(0b0000000000100000, 16, name = "Payload_Length")
s_bit_field(0x06, 8, name = "Next_Header")
s_bit_field(0xff, 8, name = "Hop_Limit")
s_binary("0x2a071180000200000000000000bb0001", name = "Source_Address")
s_binary("0x2a071180000200000000000000bb0002", name = "Destination_Address")

Q: Is there some other way in order to specify exact length binary fields that would not get tampered or modified by the fuzzing framework?

Currently I see that Boofuzz deals with raw byte (8bits) as a smallest unit, meaning that potentially either the framework would require to be in some parts to be modified, or the test case should be adapted to meet the limitations of the framework.
Please let me know if my considerations are correct.

Best,

Josh Pereyda

unread,
Sep 23, 2016, 12:51:31 PM9/23/16
to Zero Lockout, boofuzz
There is no direct support for this yet. There is an issue open on the Sulley repo:https://github.com/OpenRCE/sulley/issues/101

To quote from my answer there: 
> I ran into the same problem. AFAIK there is no such functionality yet. 

>A lot of protocols align bit fields on byte boundaries. If you have, say, a 1-bit field, followed by a 3-bit field, followed by a 4-bit field, your easy solution may be to create a byte field and fuzz all combinations. Thankfully there are only 256 combos for a single byte. 

This workaround has been fine for me so far, but it looks trickier in your case, since you would need to conflate the first 4-bit, 8-bit, and 20-bit fields to get back on the byte boundary. 

Would you open an issue for this feature request and link to this thread? It is something I would like to see, but it will be a big change. 

The change would likely center around IFuzzable.render(). Right now it basically returns a bytes string.  See `sessions.py` Session.transmit() line 731:https://github.com/jtpereyda/boofuzz/blob/ce5aabfb122caa7a700ea12e9e9a76d57d05dcce/boofuzz/sessions.py#L731 

This call to node.render() calls render on the Request object, which starts a recursive call to all of the Request's blocks:https://github.com/jtpereyda/boofuzz/blob/ce5aabfb122caa7a700ea12e9e9a76d57d05dcce/boofuzz/blocks/request.py#L133 

Some options for implementation: 
1. Have IFuzzable.render() return a bit string. 
2. Create a new object (I'll call it RenderedData, but hopefully it will have a better name). It would need to: 
 - Store a bit array (there is a bitarray package, but it looks like it's not currently maintained). 
 - Override __add__ and __radd__, and support adding bytes objects as well. In this case, the bytes objects would be translated to bits and appended/prepended. That way, adding the results of IFuzzable.render() works whether render() returns a bytes or a RenderedData. 
 - This will mean touching the recursive-calling blocks, which include at least: Request, Block, Checksum, and Size. In Request, this would mean changing line 130 to: 
        self._rendered = RenderedData() 
    The addition on line 133 should then work automatically. 
 - Finally, at some point it must be converted back to bytes for sending to a connection. 

Option 1 requires changing every implementation of IFuzzable.render(), and locks us in to a slightly clunky interface. 

Option 2 is a bit more conceptually involved, but I think would be cleaner in the end. The bitarray package would almost meet all these requirements, but I don't think it supports adding bytes and bitarrays together by default. 

Neither is super-clean, but that's all I have for now.

By the way, if you do this, make sure to use a nice IDE like PyCharm if you're not already. :)


--
You received this message because you are subscribed to the Google Groups "boofuzz" group.
To unsubscribe from this group and stop receiving emails from it, send an email to boofuzz+u...@googlegroups.com.
To post to this group, send email to boo...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/boofuzz/104753c7-ae8f-4a1c-8705-fe97a0cf43d2%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Josh Pereyda

unread,
Sep 23, 2016, 1:11:57 PM9/23/16
to Zero Lockout, boofuzz

Actually the bitstring package seems to work well 

>>> from bitstring import BitArray 
>>> b = BitArray(bin='1111') 
>>> b2 = 'ABCD' 
>>> b + BitArray(bytes=b2) 
BitArray('0xf41424344') 

So you can just modify all code spots that use .render() to use this strategy of concatenation. I don't know, maybe there's something cleaner that can be done.

Zero Lockout

unread,
Sep 26, 2016, 3:38:41 AM9/26/16
to boofuzz
Josh,

Thanks for looking into this issue!
I was aware that this might be a fairly fundamental change in how the Boofuzz operates. And I will create a feature request for on Boofuzz GitHub page.

Bitstring package looks as if could provide a clean way on how to work with binary data and produce a binary data as a result. And bitstring is well maintained.
Have not yet looked into this, but I thought on how does Boofuzz handle the mutations would that part also needs an additional review/development in order to meet the requirement that also the newly created mutated test cases do not go beyond the specified field bit length. Which Boofuzz module is the one responsible for mutating the test cases on the stack?

Nevertheless I reckon this will fill in the void and provide unique features that, to my best knowledge, no other open-source fuzzing framework provides.
Over the past days I was looking in what other frameworks/projects (e.g. Peach-community, Netcov, Spike) offer in this area, to see how they have implemented that, and I identified that this is a major issue everyone is attempting to tackle in one way or another.

Just additional personal thoughts on this topic follow (no mandatory requirement to read them :) )....
It would be awesome if there would be a Python library just for fuzzing test case creation as there is awesome powerful Python bindings oriented towards just (dis)assembly (e.g. Capstone, Keystone).
Meaning, that everyone who wants to build a fuzzer can do so by creating and handling just the required interface (e.g. protocol sockets, application inputs). But the main heavy lifting is done by the library ensuring proper test case mutations (e.g. known bad inputs, bit-flips, random input, and other modifications) to ensure that the test-cases would have mathematically-proven best candidates for input coverage or code/functional coverage of the target (if proper instrumentation and watch-dog service is in place). Because at this point I was considering to write a quick fuzzer, but I do not have the skills/knowledge on how a proper test cases should be generated and what are the algorithms therein. Of course a dumb-fuzzer can just use /dev/urandom to try to break the target, but that is not efficient and might take more time and resources.

Best,

Zero Lockout

unread,
Sep 26, 2016, 4:19:10 AM9/26/16
to boofuzz
Besides, I use VIM with a set of my own scripts to turn it into a Python/C++ IDE, since most of my coding happens on CLI :)
Nevertheless, PyCharm looks really nice and I have seen Sublime-text also being fast and feature-rich.

Joshua Pereyda

unread,
Sep 26, 2016, 9:48:11 AM9/26/16
to boofuzz

ZL,

Bit-based fuzzing would be a very cool feature. Check out boofuzz/ifuzzable.py. This is the interface for fuzz types. All the data types are in boofuzz/blocks and boofuzz/primitives. boofuzz/primitives/string.py is a good example to check out.

Basically, render() is the method used to render the element, whether it is the "normal" version or the fuzzed version. The usage is essentially: call mutate() to move to the next fuzz case, then call render() to get the value.

Finally, boofuzz/sessions.py is the module that actually does the mutating. I'd start at Session.fuzz() to see how it works.

Boofuzz is still in a state of recovery from spaghetti-fied code. So my apologies in advance. I've been trying to make sure every change makes things cleaner, but it's a slow process.

I'm a VIM fan as well, but have found PyCharm to be worth its overhead. Yet far be it from me to tell a programmer to change his IDE! :)


Joshua

Joshua Pereyda

unread,
Sep 26, 2016, 9:49:35 AM9/26/16
to boofuzz
I think boofuzz might do what the library you're describing does. The idea is that you describe what the data looks like, and boofuzz actually generates the test cases.

An advantage of open source is that the test cases themselves are open to contributions. For example, boofuzz/primitives/string.py could probably use a lot more test cases!

Joshua

Zero Lockout

unread,
Sep 27, 2016, 6:37:09 AM9/27/16
to boofuzz
Josh,
Yes I found the modules responsible for mutating and placing them on the stack, already quite some time ago.
Currently, I am trying to understand the overall structure and concepts of Boofuzz. It is not that straightforward task to grasp the coding style and philosophy of someone else's code.
But I am nearly already there. Hopefully soon there would be some contribution attempts from my side.

Best,

Joshua Pereyda

unread,
Nov 1, 2016, 12:46:36 PM11/1/16
to boofuzz
0,
You are certainly right that it is not easy to understand! If boofuzz becomes popular, I hope that it will become simpler as time goes on. This will take a lot of hard refactoring work though. Working with Sulley/boofuzz has been the biggest object lesson for clean code I've experienced so far.

If you have any suggestions at all, I am more than interested!

Regards,
Joshua

Jannik

unread,
Mar 22, 2017, 12:42:04 PM3/22/17
to boofuzz
Hi,

I had a similar problem with a bit oriented protocol. During my research I found a modified version of Sulley which has this feature. I don't know, if it is interesting for you: https://www.ernw.de/download/l2_fuzzing_shmoo08.pdf

Best wishes
Jannik
Reply all
Reply to author
Forward
0 new messages