Trouble on fuzzing test.exe from examples
I'm completely new on this topic and want to get some examples running first. My setup:
- Windows 11 running in Hyper-V (cannot use my machine directly due to security controls)
- DynamoRIO 11.3.0
- WinAFL 1.17
I build WinAFL with
cd \[WINAFLDIR]
mkdir build
cd build
cmake -G "Visual Studio 17 2022" -A x64 -DDynamoRIO_DIR=%DYNAMORIO%\cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build . --config Release
winafl.dll was present after build.
Verify DynamoRIO
drrun.exe -c C:\fuzzing\winafl\build\bin\Release\winafl.dll -- notepad.exe
Here I already get an error dialog:
I was able to workaround with adding the -debug flag. Maybe the issue is already present in DynamoRIO.
Verify WinAFL with provided test.exe I put some text files into a created in directory inside of the bin directory, where afl-fuzz.exe and test.exe are present.
I used the command from the documentation with updated values for dynamorio path and target_offset. The offset I determined via Ghidra:
afl-fuzz.exe -i in -o out -D %DYNAMORIO%\bin64 -t 100+ -- -coverage_module test.exe -fuzz_iterations 5000 -target_module test.exe -target_offset 0x1780 -persistence_mode in_app -- test.exe @@
Now I get:
I added the debug argument. It still fails, but the message is different:
Three files afl.test.exe.GUID.proc are present. I attached one as example: afl.test.exe.09436.0000.proc.log
In addition, the output was created. Content in queue shows files id_NUM corresponding to my input.
I tried everything with and without elevated privileges.
Any ideas? I stuck on that since few days.
winafl.dll can't be used without afl-fuzz, unless it's in debug mode, in which case it must be used without afl-fuzz. So that explains the "error connecting to pipe" as well as error when using afl-fuzz with the -debug flag. Please see usage examples for the -debug flag in https://github.com/googleprojectzero/winafl/blob/master/readme_dr.md
Otherwise, if the DynamoRIO mode does not work, I suggest trying TinyInst backend. See https://github.com/googleprojectzero/winafl/blob/master/readme_tinyinst.md for more info. The TinyInst error messages can also sometimes give you better indication on what's wrong with the setup.
Additionally, you seem to be using -persistence_mode in_app incorrectly. It's only meant to be used if your target already loops on its own over the target function. WinAfl's test.exe can do that, but it needs an additional loop argument (as seen in https://github.com/googleprojectzero/winafl/blob/master/readme_dr.md)
Thank you for all your suggestions. I tried with tinyinst, but also here no success. In addition I also disabled all security settings on W11 and used the VS 2019 instead of the 2022 toolset for the build, as it was mentioned on other sources.
I run tinyinst without the fuzzer. From my understanding, everything looks good:
When It run winafl, still no success:
Just in case, here are my build steps:
cmake -G"Visual Studio 16 2019" -A x64 .. -DTINYINST=1 -DUSE_COLOR=1
cmake --build . --config Release
The run with litecov also seems wrong, you are getting process exit during target method which is unexpected. I suggest trying with -target_method main instead of -target_offset. If it still doesn't work then also try adding -generate_unwind.
With afl-fuzz, the error seems to be that the executable path doesn't exist.
target_method wasn't working. It couldn't be resolved (I used the example from https://github.com/googleprojectzero/winafl/blob/master/readme_tinyinst.md), so I moved to the offset. From my point it should be correct. I set log level to debug and with incorrect offset the messaging is different.
With target_method / message with incorrect offset is similar:
With target_offset + different log level & generate_unwind
Does it work by any chance if you replace -generate_unwind with -patch_return_addresses?
Also, -target_method main should work if you create a RelWithDebInfo build (of test_gdiplus) instead of Release.
Obviously the offset I use is not working for me. RelWithDebInfo is working now, but only with TinyInst. I tried same with DynamoRio - it still fails.
Any idea about any compiler settings or os security settings, that could prevent usage of the address offset?
Is there a way to dump out the address when calling with target_method?
Under the hood -target_method <name> computes the offset and then uses that. So in a sense offset is always used. However note that the offset could change when the target gets rebuilt. It doesn't get printed out but this is the relevant code: https://github.com/googleprojectzero/TinyInst/blob/master/Windows/debugger.cpp#L988