Showing posts with label RE. Show all posts
Showing posts with label RE. Show all posts

Sunday, October 23, 2016

The case for reinventing the wheel

I really like to use IDA Pro as my debugger, and shellcode is no exception. Initially I couldn't see why anyone would ever write their own loader for analyzing shellcode. Siko et al released shellcode_launcher.exe along with the Practical Malware Analysis labs, so why rewrite that code? shellcode_launcher.exe does the work of ReadFile / VirtualAlloc / VirtualProtect, et cetera, so I just make that my database and pull in the VirtualAlloc'd memory using IDA Pro's memory snapshot facilities. Then, I go to town.

Well, I changed my tune when I discovered that VirtualAlloc was not receptive to my suggestions for where to allocate memory. (WinDbg: bp <callsite>; g; ed esp <lpAddress>; p). Without a consistent shellcode base address, none of my annotations from the IDA memory snapshot I took were lining up with the actual shellcode in subsequent debug sessions.

Edit January 14th, 2018: At this point, we have a choose-your-own-adventure on our hands:

  • If you use remote debugging, and/or you like to see IDA Pro annotations superimposed over your debugger session, and your shellcode itself allocates additional memory and executes code there, then you might be better off reading my fireeye.com blog article titled Debugging Complex Malware that Executes Code on the Heap.
  • If you don't use remote debugging, then you might be satisfied capturing snapshots of your debugging VM at critical points in the debug session so you can iteratively debug and understand the shellcode.
  • Finally, if your shellcode does not execute additional code on the heap and you just want to give it a uniform memory map in which to iteratively debug it, then read on...
For simple cases, you can reinvent the wheel and write your own shellcode loader to force shellcode to live at the same virtual address each time you debug it. But no need to start from scratch; here's the path of least resistance...

Assuming you have the shellcode as a raw binary, use xxd's feature of outputting shellcode as a C include file:

xxd -i myshellcode > myshellcode.c

That gives you a hexdump in C form:

unsigned char myshellcode[] = {
    0x55, 0x8b, 0xec, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67,
    ...
    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67,
};
unsigned int myshellcode_len = 4242;

So now, write your loader:

#include "myshellcode.c"

typedef void (*fptr)(void);

int
main(void)
{
    fptr sc = (fptr) myshellcode;
    __asm int 3 ; Safety - so I don't execute this on my analysis box (or worse!)
    sc();
}

Then do this (in an SDK prompt):

cl.exe loader.c

If you don't have Visual Studio, just get Microsoft's compiler for Python 2.7.

After compiling and linking, you'll get this:


I was worried about execute permissions when calling into my shellcode, but happily, it Just Works, perhaps because I ran cl.exe directly without using Visual Studio to specify its usual flags. The program loads in IDA as a PE-COFF, it can be debugged using IDA's debugging plugins, and the shellcode is always at the same address (in my case, unk_40A000). Therefore, you can annotate the shellcode without using the IDA Pro memory snapshot facilities to save it from a debugger session, and (this is the important part) without worrying that VirtualAlloc will return a different address during the next debug session, rendering your annotations less useful to you. The same applies to breakpoints: they will actually work, from session to session. That makes life easier.

Thursday, October 20, 2016

This one weird trick for decoding DLL malware strings

TL;DR: argtracker and ctypes. It's the ctypes part that surprised me. Read on to see why.

This procedure can make light work of decoding strings in a DLL that has a horrifying string decoder or contains a metric ton of strings. The first stage leans on code that's already out there, with a bit of duct tape to get to the second stage; the second stage is to load your malware and call into it. There's just one stick-in-the-mud limitation: it has to be a file you can load into your address space using LoadLibrary, such as a DLL. Otherwise, you have to use a different kind of tool (I'll discuss this later).

First of all, gather all the strings you want to decode. Jay Smith wrote a very cool tool for this that uses Vivisect to emulate code and locate arguments. It's called argtracker. Don't duplicate it like I was starting to do with idaapi. Please, for the love of all that is lazy, just download it and get it installed.

The IDA Python script below is basically the code from the FireEye blog with a second function added to print all the encoded strings out so you can feed them to the second stage of this procedure. If your strings aren't printable prior to decoding, then you'll need to change this up a bit.

import vivisect
import flare.argtracker as c_argtracker
import flare.jayutils as c_jayutils

# Obtain the address where each argument is referenced by the decoder along
# with the offset that was referenced
def get_first_push_arg(decoder):
    ret = []
    vw = c_jayutils.loadWorkspace(c_jayutils.getInputFilePath())
    tracker = c_argtracker.ArgTracker(vw)
    xrefs = idautils.CodeRefsTo(decoder, 1)
    for xref in xrefs:
        argslist = tracker.getPushArgs(xref, 1)
        for argdict in argslist:
            va_at, offset = argdict[1]
            ret.append(argdict[1])
    return ret

# Now go get each string
def print_va_off_and_contents(pushed_args):
    print('refva, off, argcontents')
    for (va_at, offset) in pushed_args:
        print(hex(va_at) + ', ' + hex(offset) + ', ' + GetString(offset, -1, 0))
        # https://www.hex-rays.com/products/ida/support/idadoc/283.shtml
        # 0 <= ASCSTR_C
        # 3 <= ASCSTR_UNICODE

Provide your decoder's virtual address to get_first_push_arg, and then supply the returned list to print_va_off_and_contents to get something you can massage into shape for the second stage. Yes, I know, I'm using print instead of Python's logging module. The title of this blog was actually going to have the word "lazy" in it. Maybe it still should. Anyway...

Second and final step: load the malware and call its decoder. The interesting thing I learned is that Python ctypes can call non-exported functions. What a happy surprise! First, you have to define a function prototype, then you obtain a callable by hooking that prototype to an address in your binary where the function lives. There are prototypes for stdcall (WINFUNCTYPE) and cdecl (CFUNCTYPE). We're using stdcall. Here's a convenient snippet along with the string decoding goodness.

from ctypes import *

# Modify all this
offset = 0x4321                             # Decoder offset in your mal DLL
strings = [                                 # Populate from stage 1 (above)
    [0x10001234, "ABCdef"],
    [0x10005678, "ZYX990"],
    ...
]
dll = cdll.my_malware_dll                   # Modify to load your DLL
prototype = WINFUNCTYPE(c_char_p, c_char_p) # Stdcall, accepts & returns char*

# Leave this alone
string_decoder_addr = dll._handle + offset
decode = prototype(string_decoder_addr);

for (va, s) in strings:
    print(hex(va) + ' ' + s + ' -> ' + decode(s))

Simple, dimple. Paste the strings from IDA Pro into this script, ctypes loads and calls into the malware, and Bob's your uncle. For extra credit, you can update this script to emit another script that will create the appropriate comments or bookmarks in IDA Pro. This ctypes procedure works great for DLLs. Unfortunately, next time, it'll probably be an EXE and not a DLL. For those cases, you'll have to adapt this to a different tool, such as flare-dbg, to control malware execution and feed it the strings you want to decode. I'll talk more about tools and techniques for this another time.

Thursday, October 13, 2016

Script Kitties Early Trick or Treat, Part 2


I promised a treat. Well, as scripts go, this will probably be like the time you went trick-or-treating as a kid and the old couple gave you three pennies and then you walked down the street and realized the pennies seemed to smell bad, but hey, it's money you didn't have before, so what the hay. It's not quite that bad, it's just I wrote it in 2006 and I didn't do much to bring it into modern times. But, here we go...

In 2006, PowerShell was just about to be released and around the same time I was thinking, darn it, wouldn't it be easier to experiment with VBScript if they had given me a command line? So I made one.

As it turns out, some malware is written in VBScript, so this came in handy a while back for me to decode a few lazily "encoded" strings that were assembled using the VBScript Chr() function and string concatenation. It let me figure out what COM objects were being created and move on with my life, so maybe it'll be useful to you.

I also added the ability to switch to JScript, because people also write malware in JScript, so hell, why not.

Here's a little demo:

You're wishing I just gave you the pennies now, aren't you.

Yeah, that's it. If you look at the code, you'll find out why it stinks just like those pennies. But it serves its purpose. So, enjoy!

Here's the code: https://github.com/strictlymike/eval-hta

Wednesday, September 14, 2016

Script Kitties Early Trick or Treat, Part 1

Some of my old sysadmin tricks became useful again when I analyzed some malware targeting Windows Scripting Host (WSH). In this article I'll share a trick, and in the next, I'll share a treat.

When logic gets hairy, both developers and malware analysts open a debugger to get more information. But what can be done when the target platform is WSH? As it happens, there are debuggers for this, too, and they can be had by installing either Microsoft Office or Microsoft Visual Studio in your dynamic analysis VM. To invoke the debugger, use the /X switch of either cscript.exe or wscript.exe, e.g.:

wscript.exe /X rat3ie.vbs

Here's the Visual Studio debugger, halting on line 1 of a craptacular VBScript RAT:


This gives the ability to view local variables in the Locals tab (at bottom), set breakpoints, and step through code.

That's all for this little nugget. Next time, I'll post a tool I wrote in 2006 that came in handy for conveniently and interactively evaluating VBScript and JScript to de-obfuscate strings and experiment with malware functionality.

Tuesday, September 6, 2016

"Advanced" OllyDbg Scripting

Alternative possibilities:
  • I'm daft;
  • OllyDbg's "Warn when breakpoint is outside the code section" option can't (always?) be truly disabled in odbg110; or,
  • This is not the droid (i.e. option) that I'm looking for.
In any case:

Set sh = CreateObject("WScript.Shell")

While True
    Call sh.SendKeys("%Y")
    Call WScript.Sleep(100)
Wend

And goodbye to this dialog when attempting to find the OEP by tracing into:

Next episode, we answer the question: did OllyDump ever finish? ;-)

Edit 10/14/2016: It never finished, so I ended up doing it manually by catching the unpacker in a memcpy and dumping its payload from poi(esp+4). You live, you learn.

Sunday, February 28, 2016

Snooping on Myself for a Change

Premise

When I started red teaming, I would often want to know the answers to impossible questions while writing my post-assessment report:
  • What was that command I used that I didn't think would be important to making my point, but now I realize it is?
  • The output indicated a Windows error message - which error was it?
  • Which IP address was leased to me when I did that?
Naturally a red teamer should always be taking copious screenshots, recording IP addresses frequently, and incrementally reporting in tandem with the engagement. But knowing what will be significant later is sometimes a challenge. It would be nice to have a backup.

In this post, I talk about researching and constructing a tool for logging 32-bit cmd.exe commands and output local to one's Windows attack VM. Then I discuss limitations and post source code. I've wanted to do this for a while, but I recently had a project that gave me an excuse to use Detours, so while I was at it, I decided to quickly knock out this project.

Tools

Microsoft Research produced a very useful tool for both investigating this problem and developing a solution, called Microsoft Detours. Detours is a library for hooking Win32 APIs, which allows one to instrument and extend binary applications. The non-commercial version can be downloaded for free, but only covers 32-bit architectures. This will suffice for our proof of concept. These techniques are older than 1999, so I leave it as an exercise for the student to extend this to 64-bit.

One of the Detours samples, named traceapi, hooks 1,401 Windows API functions, and can provide detailed insight into how an application works. Meanwhile, another Detours sample, named simple, shows an example of hooking and extending the Windows SleepEx API. This is all we need to get started.

Investigation

To use the traceapi sample, you must copy the Detours root to a writable directory, open a 32-bit Windows SDK Prompt, and invoke nmake from the samples directory. The bin.x86 Detours sub-directory will contain many files, including the following tools necessary to this exercise:
  • traceapi.dll (or trcapi32.dll - I seem to recall getting different results depending upon how I built this)
  • withdll.exe - for loading an application with a DLL in its address space
  • syelogd.exe - for logging trace output from Detours tools
When using traceapi, I expected to find patterns including CreateFile(CONIN$) / ReadFile, or some such. Then I anticipated hooking functions to record which handles corresponded to CONIN$, CONERR$, and CONOUT$ so that I could know which ReadFileW and WriteFileW activity corresponded to console input and output.

To begin the investigation, I launched syelogd.exe to log to a file, as follows:

C:\Users\someone\Detours\bin.x86> syelogd.exe trace_cmd.log

I then launched the 32-bit cmd.exe with traceapi.dll in its address space to begin tracing:

C:\Users\someone\Detours\bin.x86> withdll.exe /d:traceapi.dll C:\Windows\SysWOW64\cmd.exe

At this point, I typed a few commands like DIR and EXIT, and then terminated syelogd.exe.

Ah, beautiful trace output

What I found was happily contrary to my expectations...

Found the "Easy" button

The Windows command interpreter uses the ReadConsole and WriteConsole APIs for reading to and writing from the console. All the easier to hook, with no state tracking required.

Development and Features

The Detours sample named simple contains all you need to get started. Copy that folder, name it something else, update the Makefile, and get cooking. One bump I ran into and hacked up a fix for was that the 32-bit rc.exe crashed when executing it within my 32-bit Windows SDK Prompt. This is why my own Makefile (not uploaded) directly references the 64-bit rc.exe.

Logging

To customize the sample code to do my bidding, I followed the simple example's hooking pattern to first hook ReadConsoleW and WriteConsoleW. My initial logging hooks simply returned the value of the real functions just for testing purposes. I then tried printf("WriteConsole: %S", lpBuffer) to test whether I could output the data, and finally opened a file within the DllMain function.

Here is an example of the logging for a call to net.exe:
Logs for days
Why is there a separate log for each process? Because my DLL creates a new, unique log every time it is loaded. See the Limitations section below for discussion.

Why does net.exe create two logs? Because net.exe calls out to net1.exe to do its work.

IP Address Logging

I expected to have to use some sort of COM API, but instead there's this convenient GetAdaptersInfo API. Easy-peasy :)

Status Command

I wanted a way of knowing for sure that logging was enabled, without typing EXIT and having my parent prompt close on me. So, I implemented a secret command, REM status. Because my command begins with the REM command, it will be ignored by the command interpreter but intercepted by my hook on its way to the application.

BOOL WINAPI
LogReadConsoleW(
  HANDLE  hConsoleInput,
  LPVOID  lpBuffer,
  DWORD   nNumberOfCharsToRead,
  LPDWORD lpNumberOfCharsRead,
  PCONSOLE_READCONSOLE_CONTROL pInputControl
)
{
    BOOL ret = pReadConsoleW(
        hConsoleInput,
        lpBuffer,
        nNumberOfCharsToRead,
        lpNumberOfCharsRead,
        pInputControl
       );

    /* TODO: Replace this crap code with more accurate parsing */
    if (!wcsncmp((const wchar_t *)lpBuffer, CMD_QUERY_STATUS,
                wcslen(CMD_QUERY_STATUS)))
    {
        printf("Logging to %s\n", cmdlog_fname_expanded);
        LogInfoStampToFile(stdout);
    }

    LogToFile(cmdlog, "%S", lpBuffer);
    State = clsLabel;

    return ret;
}

The result is satisfactory. I type REM status, and if I'm hooked, I see a nice little confirmation that logging is enabled, including the log file name and some IP address information.

Yes, Neo, you are in the Matrix.

Limitations

Otherwise known as "problems I don't plan to solve until I get a copy of Detours Enterprise and some more time." The last 10% always takes 90% of the time, amirite?

Single-File Logging

This will probably entail using IPC, and some IPC mechanisms (like named pipes) cannot be initialized in DllMain because they could cause a deadlock by precipitating an attempt to acquire the loader lock (check out Microsoft's article on DLL best practices). This means writing "lazy initialization" code. I leave this as an exercise for the student.

Another scheme is for each child to share a log file with the parent process whose name is based on the PID of the top-most parent of the current process that has our DLL loaded in its address space. The APIs used to do this might entail a LoadLibrary or some APIs that violate DLL best practices, so again... Exercise left for the student.

Alternately, I could just open and close a single logfile with a single name, but then if I open several logged command prompts, one may fail to get access to the log as another is writing to it (say, if I'm running a command that outputs continuously while running another command in the other prompt). So, I didn't do that.

Cross-Architecture Process Creation

Because Detours Express is only for 32-bit, we have no 64-bit DLL. So here's what happens when you try to load a 64-bit process...

Nope.
Hooking 64-bit, while fun, is not something I have time for right now (I'm a father; give me a break). But my employer has a license for 64-bit, so perhaps I will extend this later. How? I anticipate that I will use the ImageHlp APIs or something to figure out whether the CreateProcess call is for a 32- or 64-bit process, and then load the appropriate DLL. Yay!

^M&^M's

If you open the output log files in something like gvim, you will see stray ^M's (character 0x0d) all over the place. Yuck. But a quick swipe of the %s/^M//g in gvim eliminates these, so I just can't bring myself to care.

Source Code

As is frequently the case with my spare-time experimentation, this code is proof of concept only. If it doesn't compile because I didn't close a pair of parentheses, rest assured that it's because I had to drop everything and rush over to my young daughter to prevent her from acquainting herself with an electric socket. Forgive me. But hopefully the thought process published here and the examples available in the code will help you think of new ways to solve problems.

The code is here: https://github.com/strictlymike/tools/tree/master/cmdlog

Thursday, October 22, 2015

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

Well, I guess I can post the script and results, now that Flare-On has been over for over a month! I'll continue from where I left off in my previous article.

Previously, I implemented a function to skip the ReadFile call and stuff arbitrary passwords into the challenge binary's input stream. By experimenting with this, I discovered a potential tell that might allow me to brute force the password by counting the number of times a particular instruction was executed. To make use of this, I needed to execute the binary several times with different passwords (aaaa..., abaa..., acaa...), moving on to the next character each time an additional sahf instruction was executed.

To do this, I knew I would first need to figure out which characters are valid for email addresses. I settled on a variant of the information available from a stackoverflow inquiry:

g_valid = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.#-_~!$&\'()*+,;=:%{|}\\/?@'

The next step was to initialize a buffer that would serve as my brute force password. How long could the password be? Based on the length comparison at the start of the password processing function...


It looked as if the program was seeking a 37-byte password. So, I whipped one up:

g_pw = list('a' * 37)

In order to move through candidate passwords, I iterated through valid characters for each character position of the brute force password:

    for pos in range(0,37):
        for c in g_valid:
            g_pw[pos] = c


To measure my progress, I executed the binary with one breakpoint set to stuff the brute force password into the program's input buffer and the other breakpoint set to count sahf instructions:

            trace = vtrace.getTrace()
            trace.execute(sys.argv[1])
            trace.addBreakpoint(MyBreakpoint(0x400000 + 0x1046, skipread))
            trace.addBreakpoint(MyBreakpoint(0x400000 + 0x10ae, count_iters))
            trace.setMode("RunForever", True)
            trace.run()

And finally, I compared the number of sahf breakpoints hit in each successive occurrence against the previous maximum. If an additional breakpoint was hit, I advanced to the next character position in the brute force password and began working on that character. The script in its entirety looked something like this:

 1 # coding: utf-8
 2 import vtrace
 3 import vdb
 4 import sys
 5 import struct
 6 
 7 # Offsets for d88dafdaefe27e7083ef16d241187d31 *very_success.exe:
 8 # cs:0x4010ae <-- sahf instruction: single iteration of password character scan
 9 #   baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - breakpoint hits once
10 #   aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - breakpoint hits twice
11 # Trying brute force by counting breakpoint hits
12 # cs:0x401046 <-- call kernel32!ReadFile, len at ebp-4
13 # cs:0x40104c <-- return from kernel32!ReadFile, len at ebp-4
14 # ds:0x402159 <-- gPasswordFromCONIN$[]
15 
16 # Props to: http://www.limited-entropy.com/stuff/drmless.py.txt
17 class MyBreakpoint(vtrace.Breakpoint):
18     def __init__(self, address, callback):
19         vtrace.Breakpoint.__init__(self, address)
20         self.address = address
21         self._cb = callback
22 
23     def notify(self, event, trace):
24         self._cb(trace)
25 
26 # Count of times sahf instruction was encountered in character scan loop
27 g_bp_count = 0
28 
29 # Count how many times sahf instruction was encountered in character scan loop
30 def count_iters(trace):
31     global g_bp_count
32     g_bp_count = g_bp_count + 1
33 
34 # Skip past ReadFile() call and tell the program that it received the bytes in
35 # the array g_pw
36 def skipread(trace):
37     trace.setProgramCounter(0x400000 + 0x104c)
38     print "\nTrying " + ''.join(g_pw)
39     tmp = ''.join(g_pw)
40     trace.writeMemory(0x400000 + 0x2159, tmp)
41     trace.writeMemory(trace.parseExpression("rbp-4 & 0xffffffff"), struct.pack("@i", 37))
42 
43 if len(sys.argv) != 2:
44     print "Usage: test.py filename"
45     sys.exit(1)
46 
47 # http://stackoverflow.com/questions/2049502/what-characters-are-allowed-in-email-address
48 g_valid = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.#-_~!$&\'()*+,;=:%{|}\\/?@'
49 
50 g_pw = list('a' * 37)
51 g_pw.append("\0")
52 g_breaks = 0
53 while True:
54     for pos in range(0,37):
55         for c in g_valid:
56             g_pw[pos] = c
57             g_bp_count = 0
58 
59             trace = vtrace.getTrace()
60             trace.execute(sys.argv[1])
61             trace.addBreakpoint(MyBreakpoint(0x400000 + 0x1046, skipread))
62             trace.addBreakpoint(MyBreakpoint(0x400000 + 0x10ae, count_iters))
63             trace.setMode("RunForever", True)
64             trace.run()
65             print "Breaks " + str(g_breaks)
66 
67             if (g_bp_count > g_breaks):
68                 g_breaks = g_bp_count
69                 break

The result was a little bit like a cinematic depiction of a password being brute forced, because the characters kept rolling by and locking in as the attack progressed:

Very Success!

In the screenshot above, you can see the output of the CTF binary (very_success.exe) interspersed with the script indicating what password was being tried (e.g. "Trying a_Little_b1t_baaaa...").

Using vtrace made this an incredibly cool learning experience, but it wasn't without its pitfalls. For instance, I was really excited when I found this snippet in the help for the Trace class:

     call(self, address, args, convention=None)
         Setup the "stack" and call the target address with the following
         arguments.  If the argument is a string or a buffer, copy that into
         memory and hand in the argument.

However, when I tried using this, I was disappointed to learn that I was out of luck:

Well, crap.

It could be that running a 32-bit binary in a WoW64 environment causes this condition, but I didn't have time to investigate, so I just went with executing the program over and over and over again, which worked fine.

There was also a flaw in my own process. I noticed that at various character positions, my assumptions broke down and the brute forcer ran off into the weeds. I suspect this was a function of the binary itself and not of the instrumentation tool (vtrace). With a little guesswork and some script adjustment, I was able to resume from various points in the process and pull the remainder of the password out of the binary:

a_Little_b1t_harder_plez@flare-on.com

After I submitted the flag, FLARE sent me the next binary and I celebrated by abandoning the CTF altogether, as I ultimately knew might happen due to my busy life. But I was glad I took the approach of figuring out how to create a scalable and repeatable instrumentation process for analyzing and abusing binaries. There are other tools out there, but vtrace is unique in that it doesn't require you to compile a DLL, and it allows you to make use of Python to instrument applications. Very useful!

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.

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.

Sunday, March 1, 2015

Not Exactly Charming

I've been annoyed with charms menu.  Most of the time, it extends in front of legitimate controls I am trying to click in my browser, evoking the "I'm TRYING to $@#!ing work here!" response from me.

A month ago, I found windows.immersiveshell.serviceprovider.dll in Process Explorer, and wondered if this had to do with the Charms bar.  I looked it up, and found an article that describes steps to use SysInternals' Process Explorer to terminate the thread that is running code within this "Immersive Experience" library.  In closing, the author states that using Process Explorer is not automatic (it entails user interaction), and that s/he hopes someone finds an effective way to disable the immersive start menu.

I found another article suggesting that the Registry affords this functionality.  I tested it, finding that it indeed does.  The relevant registry keys are:

[HKCU\Software\Microsoft\Windows\CurrentVersion\ImmersiveShell\EdgeUi]
DisableTLCorner=1
DisableCharmsHint=1

I also think that following the advice I found of right-clicking the taskbar to arrive at Properties and selecting the Navigation tab may have helped me locate a control to add another registry entry that has reduced the annoyance factor of the Windows 8 UI.  The relevant registry key was:

[HKCU\Software\Microsoft\Windows\CurrentVersion\ImmersiveShell\EdgeUi]
DisableTRCorner=1

A command script for making all these changes at the same time follows:

REG ADD HKCU\Software\Microsoft\Windows\CurrentVersion\ImmersiveShell\EdgeUi /v DisableTRCorner /d 1 /f
REG ADD HKCU\Software\Microsoft\Windows\CurrentVersion\ImmersiveShell\EdgeUi /v DisableTLCorner /d 1 /f
REG ADD HKCU\Software\Microsoft\Windows\CurrentVersion\ImmersiveShell\EdgeUi /v DisableCharmsHint /d 1 /f

Nevertheless, I thought I'd see if I could implement something similar to the "Kill Thread" function in SysInternals' process explorer.  The result can be found here on my Github:

https://github.com/strictlymike/charmkiller

It is based on the following two articles:
What didn't initially occur to me was that there is no API for enumerating threads associated with a particular module.  There is, however, the fact that a thread has a start address property that indicates what code was first executed when the thread was started.  As long as no indirection is incorporated (such as a dispatch function that uses arguments to determine what code is subsequently executed), and no tampering has been undertaken by the target process for any reason such as obfuscation (not sure if this structure is in the PEB or kernel), it is possible to classify a thread as being associated with a particular library by assessing whether the thread's start address lies within the base and end address of that library.  So, that's what I did.  Thanks, Rohitab!  See the code for more details.

The end result was a program that is capable of locating and terminating the thread that handles Immersive Experience events such as the charms menu.  Alas, that thread also handles things like wireless network configuration and the start menu which I commonly use to invoke programs whose locations I do not know, such as the Windows SDK prompt.  So, I would recommend trying the registry maneuvers first, restarting explorer to evaluate.  Regardless, the source code for the project I created could still be useful in the general sense for terminating specific threads in arbitrary processes.  Not sure I can think of an example, but nonetheless, it's out there, just in case ;-)