In most time the question(s) you're asking me via blog or twitter is: "how to prepare a fuzzing lab" or "how to perform an analysis of the crash we found". I decided to spent last few days for preparing a small example for you to give you the answer(s) for both of the questions. Below you will find the details. Here we go...
We will start here:
As you can see I started the fuzzer against the application called Free Photo Viewer. As far as I remember I found it here. But first things first...
PREPARING THE LAB:
Depends on what you would like to do (/"fuzz") ;)
In case of webapps or web servers - sometimes I'm using Burp Suite [1, 2]. But for cases similar to the one we have here (FreePhotoViewer) I will recommend you to install:
- clean Windows 7 (I used 32bit)
- Immunity Debugger
- mona.py from Corelan Repository
- HxD (but you can use any hex editor you like)
- target app (in our case - FreePhotoViewer)
- FOE2 - "Failure Observation Engine".
Installation of FOE2 should be easy but remember to read the funky manual anyway! ;)
For example: you will find the place to edit in the source code to get some more detailed results:
As you can see (red frame - cdb_command): here you can put your favourite (Windbg) commands.
I like to add there also: u eip-1; u eip; kb and other similar commands. ;)
I assume that your VM LAB is prepared and FreePhotoViewer is installed. So it's time to prepare a config for the FOE2 fuzzer.
FUZZING TARGET APP:
Installed (target) app is located in "C:\Program Files\Free Photo Viewer":
We will need it soon. Foe2 default installation directory is c:\FOE2\. There you will find config, seeds and results:
Let's copy default config file (foe.yaml) to 01-freephotoviewer.yaml. Next open it and edit like it is presented on the screens below:
As you can see we are changing the name of our 'fuzzing campaign'. Next (red frame) is to place a full path to the target we want to fuzz. 3rd red frame - I just deleted NUL because we will not use any other argument.
Next thing to check in the config - location of our files. In default FOE will store all files (seeds, results) in C:\FOE2\ directory. Edit the location (path) of your 'sample' (seed) file(s):
Next thing nice to check in the config is called 'Fuzzer options'. We will not discuss it today (to keep it simple;)) but you should definitely try to play the options available:
So config file is ready. Now it's time to prepare a sample file. :)
In c:\foe2\seedfiles\example\ you will find a lot of files to try with FOE2. I like to get 2 or 3 (or 8 ;)) and change it a little bit in HxD. In most cases - for example I will take BMP file - I will:
- leave one original BMP file
- take a copy of it and add (for example a lot of) AAAAAA...AAAA in the end of the file
- copy original file but only header (few first lines in HxD) and then I'm adding "a lot of A's" ;)
In this case from 1 sample seed file I will have a 3 files:
Example file (roughly;)) changed:
Save the seedfile(s and your config) and run FOE2 in cmd.exe, like this:
3 DAYS LATER:
In usual it should take no longer than few hours to find 'first crash'. But for example for Outlook[1, 2] or Access[3] it took 2 months on my small laptop to finally crash the application. ;)
Anyway... after let's say "3 days"... "you found it! There is a crash!" ;] Cool but what to do next?
Of course "depends on the crash". ;) But for most Windows cases (read: as far as I saw so far) it will be: malformed heap, SEH overflow or Unicode (SEH) overflow. Let's try to identify "the one" from our target app:
As you can see there are 'few' bugs to check... I believe you will have some fun. ;)
Now let's open our target app in ImmunityDbg. As an argument we will use the path to the poc-file generated by FOE2. We should be somewhere here:
As we can see SEH is malformed, so probably we will have to exploit SEH overflow bug. Cool. :)
I used HxD to open the poc file to (hopefully) see if there will be our value from SEH chain:
Great! Next step: change nSEH, right?
So far, so good. ;) Next I used mona.py to get POP, POP, RET:
Next I restarted the target app and after initial run (F7) I added a breakpoint on the location found with "!mona seh" (ppr), for example:
(After the jump to ppr value asm will change, so don't worry ;))
This was a time when the 'tricky part' started. I was sure it is 'easy overflow' and I need to change the 'poc file' simply by adding more AAAA letters... Well, nope. ;] If I added new letters - file structure was changed. :|
So the only way was to create a 'valid shellcode' with 39 characters. :)
First of all I tried to use some MsgBox shellcodes I found online but almost all of them were 'bigger than 39characters', so I failed again.
Next day ;) I realized that one time during some private talk mzer0 and @M4tisec already told me what can I do to exploit bug(s) like this one.
TL;DR: We will create a small shellcode ;] to:
- put calc.exe in memory
- run it using WinExec
Simple enough? "We gotta try":
I played a little bit more with the target app to see what shoud I do to manipulate the flow:
As you can see below, the file is not so long so there is a small space to put our shellcode:
I changed 43434343 to poppopret. Next we can see that we can jump to our NOP's and CCCC-shellcode:
So after a while (and a lot of reading and searching online) I created this nasty shellcode ;P
In 2nd and 3rd PUSH you will find ".exe" and "calc" (see ESP below), next is WinExec function.
Final results you will find on the screen below:
That's all ;)
I hope now it will be easier to find some new bugs. In case of any questions - feel free to mail me or ping me @twitter. ;)
If you like the post and you would like to donate (or just buy me a coffee;)) - on the top (right) you will find a Paypal button.
See you next time! ;)
Cheers
"TL;DR: We will create a small shellcode ;] to:
OdpowiedzUsuń- put calc.exe in memory
- run it using WinExec"
I assume that WinExec function was in 39bytes shellcode.
But how did you put calc.exe in memory?
Hi, in a very same way: as you can see (on screens) winexec was 'added' by editing asm in immunitydbg. so preparing a file (contains the same shellcode) should do the job.
Usuń2nd: thanks for watching! ;)
cheers