googleprojectzero / winafl

A fork of AFL for fuzzing Windows binaries
Apache License 2.0
2.33k stars 532 forks source link

I'm getting unique crashes when in fact they are exceptions #60

Open doria90 opened 7 years ago

doria90 commented 7 years ago

Hey all, I could appreciate your help. I wrote a wrapper which uses PhotoViewer.dll to load and draw images using Windows Photo Viewer and Windows Imaging Component. Everything works great (really slow, as each image gets opened and closed using a another program which catches the Photo Viewer window and closes it, but I cant see any other solution) and I'm getting unique crashes and hangs. Here's the commandline: "C:\Users\john\Desktop\winafl-master\build32\Debug\afl-fuzz.exe" -m 2000 -i "C:\Users\john\Desktop\results\images" -o "C:\Users\john\Desktop\results\syncdir" -M fuzzer01 -D "C:\Users\john\Desktop\DynamoRIO-Windows-6.2.0-2\bin32" -t 20000 -- -coverage_module WindowsCodecs.dll -fuzz_iterations 100 -target_module PhotoViewerLoader.exe -target_offset 0x1040 -nargs 2 -- PhotoViewerLoader.exe @@

When examining these crashes, I get the same exception which probably leads to nowhere. I'm having trouble understanding what I'm missing.

When I open the files in the crash folder, Windows Photo Viewer does not crash but writes that the file is corrupt. Any ideas? I welcome them all! critics as well :)

Thanks, doria90

ivanfratric commented 7 years ago

What type of exception are you getting (what is the exception code)? WinAFL shouldn't report a crash unless it encountered one of the following 4 exception types: https://github.com/ivanfratric/winafl/blob/master/winafl.c#L181

doria90 commented 7 years ago

These are the codes I'm getting: C++ EH exception - code e06d7363 Unknown exception - code c0000002

The thing is that nothing crashes, I get Windows Photo Viewer to open and I can close it..

ivanfratric commented 7 years ago

Firstly, note that it is not needed for the app to crash in order for there to be a bug in it, the exception could be caught by the application, the only way to check is to run the app under WinDBG or other debugger (I assume you did this already and that's how you got the exception codes).

However other scenarios are also possible

  1. A bug that only manifests itself under certain conditions, e.g. a race condition or a bug that depends on a specific memory layout

  2. For complex applications it is also possible that DynamoRIO instrumentation interacts with the target in an unforseen way and the bug is going to manifest itself only when running under DR/WinAFL.

BTW any reason you're not calling Windows Imaging Component directly instead of using Windows Photo Viewer (assuming you just want to fuzz the image parser)? It would be much faster.

doria90 commented 7 years ago

I used a wrapper off Github to call on the WIC directly but it showed zero results so I assumed it needs to draw the image and that might get more traction. Maybe the wrapper wasn't right and I should write my own.. food for thought. Do you have any recommendations in the field of fuzzing WIC?

ivanfratric commented 7 years ago

Well, one way to force it to "draw" an image is to convert it to some other format.

bioid commented 6 years ago

I'm also seeing this. By running with -debug, and choosing a "crash" input, I can see WinAFL logging out the exception codes:

(...) Module loaded, MSCTF.dll Exception caught: e06d7363 Exception caught: e06d7363 Exception caught: e06d7363 In post_fuzz_handler In pre_fuzz_handler Exception caught: e06d7363 Exception caught: e06d7363 Exception caught: e06d7363 In post_fuzz_handler (...)

Edit: One thing to note is that the debug "crashed" print at https://github.com/ivanfratric/winafl/blob/master/winafl.c#L186 doesn't seem to fire on these exceptions, so that condition isn't being hit.

Here's what WinDbg says:

(ebc0.16368): C++ EH exception - code e06d7363 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0086f0c0 ebx=0086f201 ecx=00000003 edx=00000000 esi=690dada0 edi=002c3d70
eip=753ccbb2 esp=0086f0c0 ebp=0086f118 iopl=0         nv up ei pl nz ac pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00200216
KERNELBASE!RaiseException+0x62:
753ccbb2 8b4c2454        mov     ecx,dword ptr [esp+54h] ss:002b:0086f114=cf3bf1d0

And VS2013:

First-chance exception at 0x753CCBB2 in Win32Project1.exe: Microsoft C++ exception: IndexOutOfRangeException at memory location 0x00AFEBD8.

First-chance exception at 0x753CCBB2 in Win32Project1.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000.

First-chance exception at 0x753CCBB2 in Win32Project1.exe: Microsoft C++ exception: FileFormatException at memory location 0x00AFEC60.

Here is my test harness. When I load it up in VS and step through, it does appear that the exception is handled. I've also attached the crashing test-case, and the command used to run is at the bottom of this post.

#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <gdiplus.h>

#include "afl-staticinstr.h"

using namespace Gdiplus;

wchar_t* charToWChar(const char* text)
{
    size_t size = strlen(text) + 1;
    wchar_t* wa = new wchar_t[size];
    mbstowcs(wa,text,size);
    return wa;
}

int fuzz(int argc, char** argv) {

        GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR gdiplusToken;
        GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

        PrivateFontCollection m_fontcollection;
        Status results = m_fontcollection.AddFontFile(charToWChar(argv[1]));
        {
            FontFamily fontFamily;
            int nNumFound = 0;

            m_fontcollection.GetFamilies(1, &fontFamily, &nNumFound);

            if (nNumFound > 0) {
                Font font(&fontFamily, 28, FontStyleRegular, UnitPixel);
                printf("yeah");
            }
        }
        GdiplusShutdown(gdiplusToken);

    return 1;
}

int main(int argc, char** argv)
{
    if(argc < 2) {
        printf("Usage: %s <ttf>\n", argv[0]);
        return 0;
    }

    fuzz(argc, argv);

    return 0;
}

id_000013_00.zip Command line used to find this crash:

afl-fuzz.exe -i in -o sync_dir -D C:\lib\DynamoRIO\bin32\ -t 5000 -S slave0a -- -coverage_module gdiplus.dll -coverage_module run.exe -coverage_module DWrite.dll -coverage_module ntdll.dll -coverage_module kernel32.dll -fuzz_iterations 10000 -target_module run.exe -target_method fuzz -nargs 2 -- run.exe @@