Inspiration to create a fuzzing harness for FoxitReader’s ConvertToPDF function (targeting version 9.7) came from discovering Richard Johnson’s fuzzer for a previous version of FoxitReader.
(found here: https://www.cnblogs.com/st404/p/9384704.html).
Multiple changes have since been introduced in the way FoxitReader converts an image to a PDF, including the introduction of new Vtables entries, the necessity to load in the main FoxitReader.exe binary (including fixing the IAT and modifying data sections to contain valid handles to the current process heap) + more.
The source for my version of the fuzzing harness targeting version 9.7 can be found on my GitHub: https://github.com/Kharos102/FoxitFuzz9.7
Below is a quick walkthrough of the reversing and coding performed to get this harness working.
Firstly — based on the existing work from the previous fuzzers available, we know that most of the calls for the conversion of an image to a PDF occur via vtable function calls from an object returned from
ConvertToPDF_x86!CreateFXPDFConvertor, however this could also be found manually by debugging the application and adding a breakpoint on file read accesses to the image we supply as a parameter to the conversion function, and then walking the call stack.
To start our harness, I decided to analyse how the actual
FoxitReader.exe process sets up objects required for the conversion function by setting a breakpoint for the
Next, by stepping out and setting a breakpoint on all the vtable function pointers for the returned object, we can discover what order these functions are called along with their parameters as this will be necessary for us to setup the object before calling the actual conversion routine.
We know how to view the vtable as the pointer to the vtable is the first 4-bytes (32bit) when dumping the object.
During this process we can notice multiple differences compared to the older versions of FoxitReader, including changes to existing function prototypes and the introduction of new vtable functions that require to be called.
After executing and noting the details of execution, we hit the main conversion function from the vtable of our object, here we can analyse the main parameter (some sort of conversion buffer structure) by viewing its memory and noting its contents.
First we see the initial 4-bytes are a pointer to an offset within the
This means our harness will have to load the FoxitReader image in-memory to also supply a valid pointer (we also have to fix its IAT and modify the image too, as we discover after testing the harness).
Then we continue noting down the buffer’s contents, including the input file path at offset +0x1624, the output file path at offset +0x182c, and more (including a version string).
Finally after the conversion the object is released and the buffer is freed.
After noting all the above we can make a harness from the information discovered and test.
During testing, certain issues where discovered and accounted for, including exceptions in
FoxitReader.exe that was loaded into memory, due to imports being used, this was fixed by fixing up the process IAT when loaded.
Additionally, calls to
HeapAlloc were occurring where the heap handle was obtained via an offset in the
FoxitReader image loaded in-memory, however it was uninitialised, this was fixed by writing the current process heap handle into the
FoxitReader image at the offset
HeapAlloc was expecting.