Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Troubles with fuzzing a DLL #74

Open
doria90 opened this issue Oct 2, 2017 · 12 comments

Comments

@doria90
Copy link

@doria90 doria90 commented Oct 2, 2017

Hey all,
I've got this problem which I can't get around, maybe I'm missing something and you can help me spot it.
So I've written a wrapper to a DLL, Here's the code:

#include <windows.h> #include <stdio.h>

typedef void(__stdcall *ImageView_Fullscreen)(HWND hwnd, HINSTANCE hInst, LPCWSTR path, int nShow);

void fuzz(ImageView_Fullscreen ProcAdd, wchar_t* filename ) { (ProcAdd)(NULL, NULL, filename, 1); }

int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("Usage error: PhotoViewerLoader.exe ");
return 0;
}
HINSTANCE hinstLib;
ImageView_Fullscreen ProcAdd;
BOOL fFreeResult;

// Get a handle to the DLL module.
hinstLib = LoadLibrary(TEXT("shimgvw.dll"));

// If the handle is valid, try to get the function address.
if (hinstLib != NULL)
{
	ProcAdd = (ImageView_Fullscreen)GetProcAddress(hinstLib, "ImageView_Fullscreen");

	// If the function address is valid, call the function.
	if (NULL != ProcAdd)
	{
		wchar_t filename[4096] = { 0 };
		MultiByteToWideChar(0, 0, argv[1], strlen(argv[1]), filename, strlen(argv[1]));
		fuzz (ProcAdd, filename);
	}

	// Free the DLL module.
	fFreeResult = FreeLibrary(hinstLib);
}
return 0;

It is my intention to instrument the fuzz() function but I can't seem to get it working. this is my debug command:
"path/to/DynamoRIO/bin32/drrun.exe" -c winafl.dll -debug -target_module .\Fuzz\PhotoViewerLoader.exe -target_method fuzz -fuzz_iterations 10 -nargs 2 -- .\Fuzz\PhotoViewerLoader.exe .\1.png

When I build it as a Debug with symbols I'm getting:
Exception caught: 8001010d Exception caught: 80010108 Exception caught: 80010102 Exception caught: 80010102 Exception caught: 80010102 Exception caught: 80010102 Exception caught: 80010102 WARNING: Target function was never called. Incorrect target_offset?

When I use a Release build, the fuzz() function is wiped away(for optimization) leaving only the main function(which can be instrumented but not worth it). This raises the question - can I place an offset which is not a function entry? Because I tried that and it gave the same results across various offsets.
"path/to/DynamoRIO/bin32/drrun.exe" -c winafl.dll -debug -target_module shimgvw.dll -target_offset 0x504 -fuzz_iterations 10 -nargs 2 -- .\Fuzz\PhotoViewerLoader.exe .\1.png

image

I'm getting the same warning when running in debug mode with the DLL as the target:
"path/to/DynamoRIO/bin32/drrun.exe" -c winafl.dll -debug -target_module shimgvw.dll -target_offset 0x57d8 -fuzz_iterations 10 -nargs 2 -- .\Fuzz\PhotoViewerLoader.exe .\1.png

image

*Please notice that shimgvw.dll has his functions exported, which means I should have been able to use -target_method , but it doesn't work either.. same output as always.

I think it's important to note that shimgvw.dll opens a GUI window of "Windows Photo Viewer" when calling ImageView_Fullscreen. To close the window and avoid hangs, I wrote a listener that checks every new window for the "Photo Viewer" string in its title, if exists it will close the window.

Any tips or ideas regarding my situtation? any help would be appreciated!!

@ivanfratric

This comment has been minimized.

Copy link
Contributor

@ivanfratric ivanfratric commented Oct 2, 2017

Hi,

"path/to/DynamoRIO/bin32/drrun.exe" -c winafl.dll -debug -target_module .\Fuzz\PhotoViewerLoader.exe -target_method fuzz -fuzz_iterations 10 -nargs 2 -- .\Fuzz\PhotoViewerLoader.exe .\1.png

There is a bug here, -target_module flag takes just the name of the module, not the path.

You cannot target a middle of the function, but I assume you can tell the compiler not to optimize it away (would need to dig for syntax of that) and even to export its symbol as was done in this blog post: https://symeonp.github.io/2017/09/17/fuzzing-winafl.html.

You should be able to use a function inside the dll as the target, not sure why that is not working.

@doria90

This comment has been minimized.

Copy link
Author

@doria90 doria90 commented Oct 3, 2017

Yep, the combination of disabling compiler optimization and exporting the fuzz() symbol made it work (along with overcoming the dumb -target_module mistake I made). so Thanks!
Just so to make it easier to everyone, here's what you need to do:
To export the symbol of the function: extern "C" __declspec(dllexport)
To disable DLL optimization: https://stackoverflow.com/questions/4713320/is-there-any-way-to-disable-compiler-optimisation-for-a-specific-line-of-code

I still can't get the instrumentation to work within the DLL, but whatever I'll have a go like this for now.
Thanks!

@doria90

This comment has been minimized.

Copy link
Author

@doria90 doria90 commented Oct 3, 2017

Okay so I'm getting a new issue here which I'm not quite sure how to tackle.
After addressing the problems above, I was able to get a clean debug run with 10 iterations and an "Everything appears to be running normally" comment, this is the command:
"..\..\..\..\..\DynamoRIO-Windows-7.0.0-RC1\bin32\drrun.exe" -c winafl.dll -debug -coverage_module shimgvw.dll -coverage_module WindowsCodecs.dll -target_module PhotoViewerLoader.exe -target_method fuzz -fuzz_iterations 10 -nargs 2 -- PhotoViewerLoader.exe <file>

I've used the corpus distillation program and narrowed it down to 25 inputs:
python "..\..\..\winafl-cmin.py" -D "..\..\..\..\..\DynamoRIO-Windows-7.0.0-RC1\bin32" -t 10000 -i E:\jxr\ -o E:\jxr\distilled -covtype edge -coverage_module shimgvw.dll -coverage_module WindowsCodecs.dll -target_module PhotoViewerLoader.exe -target_method fuzz -nargs 2 -- PhotoViewerLoader.exe @@

And then started fuzzing using:
afl-fuzz.exe -i E:\jxr\distilled -o results -D "..\..\..\..\..\DynamoRIO-Windows-7.0.0-RC1\bin32" -t 20000 -- -coverage_module shimgvw.dll -coverage_module WindowsCodecs.dll -fuzz_iterations 100 -target_module PhotoViewerLoader.exe -target_method fuzz -nargs 2 -- PhotoViewerLoader.exe @@

I'm getting no new paths with an "odd, check syntax!" comment. Plus it finished a cycle wayyy to fast..
image

My wrapper pops-up the Windows Photo Viewer, which happened in the debug run but is not happening in the actual fuzzing run.. I can't say why but i guess they're related.
Any ideas?

@ivanfratric

This comment has been minimized.

Copy link
Contributor

@ivanfratric ivanfratric commented Oct 4, 2017

Hmm, sounds like it's running but the target function is returning too soon, without reaching the interesting parts. In the debug run, did you see the pop-up 10 times, or just once?

Also, will the "Windows Photo Viewer" in this case be a new process or running in the same process as your target. WinAFL can't collect coverage of a new process.

@doria90

This comment has been minimized.

Copy link
Author

@doria90 doria90 commented Oct 8, 2017

It's running in same process as my program simply loads the dll and call one of its methods.
When running in debug mode, I'm getting 10 distinct pop-ups, which suggests my function executed and returned so I'm not quite getting what's going on..
Here's my debug command and results:
"..\..\..\..\..\DynamoRIO-Windows-7.0.0-RC1\bin32\drrun.exe" -c winafl.dll -debug -coverage_module shimgvw.dll -coverage_module WindowsCodecs.dll -target_module PhotoViewerLoader.exe -target_method fuzz -fuzz_iterations 10 -nargs 2 -- PhotoViewerLoader.exe E:\jxr\distilled\hdphoto1.wdp
afl.PhotoViewerLoader.exe.08052.0000.proc.log

Any ideas?

EDIT: I've tried fuzzing the 'main' method as well and I'm getting the same issues.. Can anyone figure out what's going on? it all works so well when using the debug run.

EDIT2: If I let it run after 1 cycle is done, it goes on and crashes windows giving me a BSOD :\

@kciredor

This comment has been minimized.

Copy link

@kciredor kciredor commented Nov 19, 2017

Hi @ivanfratric, does your previous remark "WinAFL can't collect coverage of a new process." include child processes as well?

I'm trying to fuzz an application that launches it's own child process, which in turn loads the dll I want to fuzz. drrun -debug does not show the dll being loaded at all. :-)

@ivanfratric

This comment has been minimized.

Copy link
Contributor

@ivanfratric ivanfratric commented Nov 19, 2017

Yes, what I meant was "WinAFL can't collect coverage of a child process". In that case WinAFL only instruments the parent process, which is why you won't see the dll being loaded.

@1n598

This comment has been minimized.

Copy link

@1n598 1n598 commented Nov 19, 2017

@kciredor

This comment has been minimized.

Copy link

@kciredor kciredor commented Nov 20, 2017

From what I understand a thread loading DLL's should be fine, but child processes are off the grid.

The latter one hurts btw, took me days to find the proper offset for this app ;-) Any chance child processes will be supported in the future?

@1n598

This comment has been minimized.

Copy link

@1n598 1n598 commented Nov 20, 2017

@kciredor

This comment has been minimized.

Copy link

@kciredor kciredor commented Dec 27, 2017

Hi @ifratric,

So I just looked into winafl.c (core) and I'm not quite sure I fully understand what you ment with the PID/loading part.

From what I found out, DynamoRIO always covers child processes. It has been explicitly disabled for afl-fuzz.c / afl-tmin.c / afl-showmap.c, but not globally for winafl.c.

So I would expect running drrun.exe (like the example from winafl/README.md) to cover the child processes out of the box already. But it does not, ofcourse ;-)

Can I pick your brain, would you care to share your thoughts on this one please?

Best,
kciredor

@ivanfratric

This comment has been minimized.

Copy link
Contributor

@ivanfratric ivanfratric commented Dec 27, 2017

DynamoRIO does indeed instrument child processes by default, but this is disabled in WinAFL here: https://github.com/ivanfratric/winafl/blob/master/afl-fuzz.c#L2089
(note the -no_follow_children flag).

The main reason is communication of target process and afl-fuzz: Target process needs to connect to a pipe and shared memory exposed by afl-fuzz. IIRC this led to problems in the past when multiple processes attempted to connect to the same pipe/shared memory and I put -no_follow_children to fix that.

A possible alternative could be to only connect to pipe/shm once the target function is reached (and hope it's only going to get reached in 1 process). Not sure if this would result in some other problems, difficult to say off the top of my head.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.