Providing config data to test binary?

64 views
Skip to first unread message

BlackMage

unread,
Aug 11, 2022, 4:20:54 PM8/11/22
to afl-users
I'm working on my masters thesis and exploring how AFL could be beneficial to RE/Fuzzing of a specific binary (comparing to a different system we're currently using).  The binary accepts networked based inputs and I understand that the general idea is to either change the source code (not an option as we don't have source code) or to modify AFL++ to fuzz over the network (which is the option we're exploring).  

I'm running this with a test binary (in lieu of the actual binary) that can accept input via stdin.  This is acceptable for the work that I actually need to perform for my research (while annotating AFL++ modifications for network support).

My question is, if my binary of interest accepts a configuration from another unit on port A but all of our fuzzing data will go over port B *AFTER* the config is sent over.... is there a built in method to sending configuration data before fuzzing with AFL?  With my test binary,  it would be acceptable to send config data and then the fuzz string as a second input over stdin.

Thanks in advance.

BlackMage

unread,
Aug 11, 2022, 4:23:09 PM8/11/22
to afl-users
I forgot to mention, our idea would be to send the config data and use the persistence mode to speed things up if possible.  We're currently fuzzing with persistence mode (saving registers and memory) but were unable to find documentation about providing the initial input to get us to the START address.

Marc

unread,
Aug 12, 2022, 2:11:31 AM8/12/22
to afl-...@googlegroups.com, BlackMage
Hi,

the best is to AFL_PRELOAD desock or desock2 from preeny - if that
works. if they work they will change networking to read from stdin
instead from tcp/udp, making fuzzing easy and fast.
note that you might need to expand on the hooked functions if the target
also uses getpeername() etc. functions and bails if they are not
producing expected data.

for the config push - is that a one-time thing, a regular thing, or
something that has to be done for every single fuzz attempt?
if it is a one time thing - just send it before starting the fuzzer. for
regular or one time things you could abuse afl++'s custom mutators. e.g
post_process for single fuzz config sends and
afl_custom_havoc_mutation_probability for regular config sends.

note that there is also a very outdated branch that has networking which
might help you a lot to integrate networking in the current afl++ state:
https://github.com/AFLplusplus/AFLplusplus/tree/networking

Regards,
Marc
--
Marc Heuse
www.mh-sec.de

PGP: AF3D 1D4C D810 F0BB 977D 3807 C7EE D0A0 6BE9 F573

Connor Shugg

unread,
Aug 12, 2022, 7:59:37 AM8/12/22
to afl-...@googlegroups.com, BlackMage
Hi Mage,

To add to what Marc said about fuzzing over network protocols - Preeny accomplishes this but with some limitations. IIRC, it only supports a few networking system calls (I don’t believe it supports ‘send’ and ‘recv’ with the file descriptor dancing it does - only the lower-level ‘write’ and ‘read’). It also isn’t thread safe and doesn’t do well if your target program is multithreaded (such as, say, a multithreaded web server).

I have yet to try this out, but libdesock was developed earlier this year by a research team. They emulate the entire networking stack in user space and claim to have better speeds and full support for fuzzing via network protocols. So while it may be more expensive to run, it should give you a better network-fuzzing experience. Here’s a link to the repo: https://github.com/fkie-cad/libdesock

- Connor

--
You received this message because you are subscribed to the Google Groups "afl-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to afl-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/afl-users/1745c1d2-11fa-3275-ff46-0d58f506bf82%40mh-sec.de.

BlackMage

unread,
Aug 12, 2022, 9:47:38 AM8/12/22
to afl-users
First off, thanks for the quick replies. 

Just a tidbit to clarify things.... 
1. The CONFIG is sent to the binary every time it boots up.  Once the binary receives the CONFIG, I can do its thing and we could even shut off the program that sends the configs.  It could also be transmitted by saving the data in a file or variable and sending it over UDP to our target ( cat config_file > /dev/udp/IP_ADDR/PORT).
2. As far as getpeername()... my test binary does not use it and I'm almost 100% positive that the target binary doesn't either.

For the CONFIG question:
1. Is there a way to sent a config, wait XX milliseconds (for program to process config) and then send the fuzz data?
2. How could I go about sending the config data and then create a snapshot of the memory/registers/IP at that time? I'm not sure Qemu's  Persistent Mode is right for this but it's where we were looking.
3. Marc mentioned " if it is a one time thing - just send it before starting the fuzzer".  I thought we leave AFL to start the binary?  If I start the binary manually, will AFL be working with my manually loaded instance or create new instances to fuzz??  I can see that happening with stdin/file inputs but on a networked binary, it should error due to not being able to bind to the same port.

For the NETWORKING 
1. I'm going to look into Preeny in just a moment.  If desock can shift from network to stdin inputs (which is how it appears at a cursory glance), it could be another option as well for general use, especially outside of my thesis.  
2. For my testing, I can use it since I'm using Ubuntu 18, but I'm not sure if the target binary would benefit from Preeny  (older embedded ARM system and might have incompatibility issues).  I saw ARM mentioned in comments in the MAKEFILE but since I'm not directly working on the embedded system, I can't verify this.  This is why advisor mentioned modifying AFL++ (he did for the other system) to send over tcp/udp instead of stdin/file.  I wouldn't actually have to do this modification for my thesis, merely discuss it.

Thanks again guys...
BlackMage

Connor Shugg

unread,
Aug 12, 2022, 10:51:26 AM8/12/22
to afl-...@googlegroups.com
Hi Mage,

Since the config must be sent *every* time the program is executed, you could potentially write a custom mutator module for AFL++ to prepend the config onto the current fuzzer test case such that it arrives first. It sounds like you need to have a short delay between the config and the test case's delivery, though, so this may not accomplish everything you need.

Another alternative is something I did for my Master's thesis, and others have done for specific use-cases like yours: write a custom LD_PRELOAD C library that intercepts AFL++ input (from stdin) at runtime and handles everything in a separate thread/process. (Shameless plug: take a look at my MS thesis repo, specifically src/preload.c. I did this by intercepting a few important networking system calls using dlsym() and adding some extra code that spawned my own thread to do all my dirty work.) With a custom library, you can have it spawn a separate thread or process within the target program's execution that controls:
  • Sending the config to the program (via a network connection, if I understand correctly)
  • How long to wait before sending the fuzzer's test case
  • Sending the fuzzer test case (via that same network connection)
  • Lots more (forcing the program to exit, writing details into a log, etc.)
Just my two cents - let me know if you have any more questions.
- Connor

BlackMage

unread,
Aug 12, 2022, 11:06:39 AM8/12/22
to afl-users
Connor,

Thanks for that feedback.  It leans heavily to what we were thinking in that some "heavy lifting" needed to be added in some way or another.  Most of my thesis work was in the reverse engineering side of this process. This last bit is just a comparison of "how we would do similar research without the use of the toolchain we used for most of the research".  The basis of our work uses the repo @ https://github.com/mfthomps/RESim but it requires a license for SIMICS (by WindRiver).

With that said, it seems like a LOT more would be involved than I needed to do for my thesis.  I've got a couple folks behind me and it gives them some opportunities to expand on my work.  However, not sure if they will pursue it simply because we have a solution that handles ALL of this already.  BUT due to the licensing requirement, it could be something beneficial to have this in a fork of AFL without being tied to SIMICS.

Thanks a bunch for the insight and I'll definitely peek at your work as well.  Might give some specifics that could apply in my written work.

BlackMage

Marc

unread,
Aug 14, 2022, 6:30:15 AM8/14/22
to afl-...@googlegroups.com, BlackMage

> Just a tidbit to clarify things....
> 1. The CONFIG is sent to the binary*_every time_* it boots up.  Once the
> binary receives the CONFIG, I can do its thing and we could even shut
> off the program that sends the configs.  It could also be transmitted by
> saving the data in a file or variable and sending it over UDP to our
> target ( cat config_file > /dev/udp/IP_ADDR/PORT).

so on any event that resets or has to reset the target the config has to
be pushed again.

the question is then in what occasions you have to resend the config.
if thats only for a crash then use the afl-fuzz -I command line option
to initiate a restart and push of the config.

if that is also required for timeouts, then you have to patch afl-fuzz
to act also on that for the -I option.

For how to send the config when the target is started I am not sure what
the best way is. mabyw another hack for afl-fuzz -I to run this commmand
before calibration starts.

> 2. As far as getpeername()... my test binary does not use it and I'm
> almost 100% positive that the target binary doesn't either.

that was just an example. the target might use some socket functions on
the accept filedescriptor which will fail as it is not a socket if you
use preeny. follow that with strace, and hook them too in the ld_preload
lib.

> 2. How could I go about sending the config data and then create a
> snapshot of the memory/registers/IP at that time? I'm not sure Qemu's
> Persistent Mode is right for this but it's where we were looking.

in afl++'s user qemu_mode only the registers can be snapshotted and
restored, nothing else.

> For the NETWORKING
> 1. I'm going to look into Preeny in just a moment.  If desock can shift
> from network to stdin inputs (which is how it appears at a cursory
> glance), it could be another option as well for general use, especially
> outside of my thesis.
> 2. For my testing, I can use it since I'm using Ubuntu 18, but I'm not
> sure if the target binary would benefit from Preeny  (older embedded ARM
> system and might have incompatibility issues).  I saw ARM mentioned in
> comments in the MAKEFILE but since I'm not directly working on the
> embedded system, I can't verify this.  This is why advisor mentioned
> modifying AFL++ (he did for the other system) to send over tcp/udp
> instead of stdin/file.  I wouldn't actually have to do this modification
> for my thesis, merely discuss it.

well you will have to cross compile preeny to arm to make this work.

Regards,
Marc

BlackMage

unread,
Aug 14, 2022, 10:19:35 AM8/14/22
to afl-users
Thanks Marc!

1. The config will need to be pushed EVERY time the program starts.  It'll need some mechanism to do this before fuzzing can begin.  We could fuzz the config but it's not specific target for this research.  With Persistent mode, it could be pushed once as it's not used at the time our target data is actually ingested over the network.
2. Tracking on the networking stuff that could mess with preeny.  
3. The github page shows MEMORY can also be restored using AFL_QEMU_PERSISTENT_MEM=1.  As far as IP... that would be controlled with START and RET addresses.  Not specifically restoring the IP register.. but effectively..lol
4. Got it for cross-compilation.  This target is ARM... but the general idea for my research could be applicable to other architectures as well (including X86_64).

 I think that my final answer is "there's a bunch of lifting needed".  For what we aim to do, there isn't any "out of the box" solution outside of the toolchain I used for most of the work I've put in.  Yay for justifying the funding! haha...  Anyway, thanks again for all the insight.  I'm going to wrap it up with a "future work"  item to include extending AFL to do all this stuff.  

BlackMage

mfthom

unread,
Nov 12, 2022, 7:24:29 PM11/12/22
to afl-users
BackMage,
I am curious whether you looked into the free version of Simics that Intel offers for use by researchers.  Use of RESim is certainly limited by the licensing fees from Wind River, but the Intel offer might be a viable alternative.
--Mike

Reply all
Reply to author
Forward
0 new messages