A reversing / analysis approach of FlexCrypt : Exploitation-one failed

- The following stuff is done in an environment of Win XP SP3 VM w/ .NET v2.0 .. Also tested in Win7x64 and Win7x86 -
- Tools used : Just ollydbg
- App can be found in :http://www.flexcrypt.com/flexcryptfree.html . 

Everything started when I firstly saw the security magazine “Hakin9” (http://hakin9.org/) presenting FlexCrypt .. I downloaded flexcrypt, and started to testing functionality etc… But I have a bad habit… after some minutes, instead of looking the functionality, i fired up Ollydbg and started exploring its code… I focused on every interface that was accepting user’s input. I wanted to check some BoF vulnerabilities. My attention was caught by the Registration Dialogbox. Fuzzing the input by hand (exception appears in string length > 452) I noticed that¬†the application throws an exception…! That needs examination..

First of all, we assume that the operation is simple : U press Validate -> some function (1) reads your input storing it to a buffer -> string manipulations and memory allocations happen -> some function (2) validates your input -> message for good or bad news ūüôā

So, hands on.. attaching Olly on the process, cause the application to overflow entering a long input. Olly shows up, and we land in KERNEL32 :

Kernel RtlRaiseException

From this point we are not able to go back, to a piece of code before the exception happens.. If we try to pass the exception to the program in order to let it continue run, we end up in an endless loop throwing the exception.. We forget this way: “to begin backwards from where the exception occured”. Only route now, is to guess and find some breakpoint and land near the function (1).

Started again flexcrypt, attached Olly, entering¬†short input and started guessing some breakpoints.. The old and good “GetWindowTextA/W” was not a solution.. neither “lstrlen/lstrcpy/strlen/memicpy” etc… there were lot of breaks and loosing time for nothing.. If you fuzz a bit the dialogbox, without having Olly attached! when you reach length 453 or more, you will get an error message from .NET handling the exception, reporting you in detail about where that exception came from..¬†a header of the error message looks like this.. :

System.IndexOutOfRangeException: Warning: A StringBuilder buffer has been overflowed by unmanaged code.  The process may become unstable.  Insufficient capacity allocated to the StringBuilder before marshaling it.
at InteractiveStudios.QlmLicenseLib.QlmLicense.QlmValidateLicense(IntPtr obj, String licenseKey, StringBuilder errorMsg)
at InteractiveStudios.QlmLicenseLib.QlmLicense.ValidateLicense(String licenseKey)
at NordicIS.LicenseManager.License.ValidateLicense(String LicenseKey)
at Management.LicenseWindow.buttonXValidate_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at DevComponents.DotNetBar.ButtonX.OnClick(EventArgs e)
at DevComponents.DotNetBar.ButtonX.OnMouseUp(MouseEventArgs e)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at DevComponents.DotNetBar.PopupItemControl.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

This make us earn lot of time, giving us some APIs to be used as breakpoints..! Notice the first one (last one before exception occurs) It is QlmLicence.ValidateLicence.. Looks like there is a custom library (DLL) which export some functions.. Searching a bit around the modules, i found out that the DLL we are searching is the IsLicence50.dll¬†which exports the function QlmValidateLicence¬†So we start app again, attach Olly, pressing ALT-E to select the module/dll IsLicence.dll, right click and select “Show Names” to get a list of all functions exported by that module.. Then Find the QlmValidateLicence and place a breakpoint on it pressing F2.. :

exports

bpx on QlmValidateLicence in IsLicence50.dll

You can press now ALT-B to see a dialog with the set breakpoints to validate that your bp is set. Now enter some dummy text in the app’s dialog, and press validate. Olly will break.. Guess what.. we are near the point of function (2).. or inside it.. we want to analyse the code before that.. we will first seek the function (1) to examine the whole code for flaws..

Seeking code near the function (1)

We have to trace back the code.. How we do that? with the old and trusted way… ūüėÄ reading the stack return addresses, following them, and placing bpx’s validating the program flow… That’s what we gonna do.. It’s a bit boring, but when u finally reach your goal, there is a cool feeling of satisfaction ūüėÄ ..But let’s see in this point (when Olly breaks in QlmValidateLicence)¬† how many times does our¬† input exists in the program’s memory space.. Pressing ALT-M¬† memory map dlg shows up. CTRL-B allows you to search as unicode or ascii or hex. Go to ASCII and type a part of your input (try always to use a bit uncomon inputs so you can search and know that each result from search is unique) and press enter.You find it in the stack area of the main thread.. press CTRL-L to search again, you find nothing (in the same window).. close the window, press CTRL-L again to search in the whole memory map,¬†and again you dont find it.. The application uses UNICODE string formats.. means that string, came in memory in the unicode format, and then converted to ascii (probably with the API WideCharToMultiByte) And really if you search with a similar way as before, for the unicode string u searched before, you’ll see several results within memory..Most of them in high memory addresses.. So let’s try bpx in WideCharToMultiByte, ALT-E find kernel32.dll, open exports (show names) and find that API and press F2 to set the breakpoint. Now start over again.. enter some dummy input (short in size.. about 15 chars or less)¬† and press the “validate” button.. Olly breaks on WideCharToMultiByte one time, then on ValidateLicence (press F9 to let it break on next), and then¬†several times again on WideCharToMultiByte.. this means that your input is stored in wideChar/unicode format¬†when first read from the textbox,¬†and then the app uses WideCharToMultiByte to¬†convert to¬†ascii string and bring it to¬†a local variable¬†and use it further..¬†If you¬†enter again some input and press “validate” again,¬†olly breaks on 1st call to WideCharToMultiByte and you see the arguments passed¬†to the function (looking at the stack) and in this way¬†we confirm that¬†this¬†call to the API has to do with¬†our input…¬†:

Arguments of WideCharToMultiByte

Now check the destination parameter of this API, which is the address in stack¬†I¬†highlighted in the image.. This is something like 0012Axxx which is near to the stack pointer register (ESP).. Remember this address, and press F9.. Next break is on ValidateLicence.. Looking at the stack we see that there is the string of our input there… Trying to increase the length of the string, we see that string taking more place in the stack.. The 1st thing we wonder is “it gonna overwrite the return addresses in the stack?” well the answere is NO… (how do i find that? by tracing back.. return addresses, bpx there, seek beginning of procedures, again bpx etc ..) ¬†if we input a string with length > 100h (256 chars) the string does not get stored in stack as local variable.. It is¬† stored in an allocated place, and just referenced via pointer ūüôā ok this is a safe mode.. nothing is gonna be overflown here… let’s go to the other function to see what’s going on…

Seeking code near the function (2)

Ah easy… we are there just by breaking in QlmValidateLicence.. this part is much easier and i’ll show some shots :

Just broke in QlmValidateLicence

As you see in the above shot, i commented the sub-calls inside the QlmValidateLicence in order to be clear if any of those will cause the exception.. Tracing (F8) we pass over it with no prob.. Then going to the end of the function… And damn yes..! Function completed successfuly.. ūüôā so exception is after that.. we trace till return and executing it. Now being in the code where the QlmValidateLicence was called, we see this

This is the call of the exception inside..

This is the call of the exception inside..

We enter the call with F7 ..and here is a bit more interesting.. look at the shot :

Code checking to throw exception or not

Code checking to throw exception or not

This piece of code checks the input buffer in a specific length (3E1h till 3E4) to see if there are null terminated chars.. My buffer in the example, consists of 452*A + 1*i .. If it finds something else (meaning your buffer is too big) , it throws exception.. Notice in the dump.. out buffer is in UNICODE format.. means that the length is *2.. Means 453*2=906.. And also take a look there, right after our buffer there is a text appended.. Look at the shot, it is commented.

I go deeper, in the call that throws the exception( on address 7A0AC037), to see when KERNEL32 is called.. and i see more details…

Code to CxxThrowException

Code to CxxThrowException

We see here the call to CxxThrowException from the module MSVCR80.. Going deeper in that call :

KERNEL32.RaiseException

And the CxxThrowException, calls the KERNEL’s RaiseException with the arguments you can see in the stack… (code of exception, continuable or not etc..) well i wanted to see the arguments and play a bit with them, that’s why¬†I went so deep ūüėõ Notice the arguments and the Code number.. this is the number of exception thrown, and Olly informs you for that (in status bar) if you press F9..

Well, is that buffer that we just saw,¬†secure? hmmm.. if we examine the memory map, we will see that the memory space 001Exxxx is far away from the top of our stack (0012xxxx) so we’ll not gonna have a stck based buffer overflow!

I plan to examine this app a bit more… maybe in a future post..

Tagged , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *