Archive for May, 2006

The MS Word 0-day Snort RuleSet

Posted: May 27, 2006 in Security

Though an IPS / IDS shouldnt be the one filtering this, an AV is the one who should be able to detect the potentially harmfull files (since that is what they are designed to do) but untill the AV vendors release there updated virus definitions, there had to be some workaround for the increasing automated mushroom growth of the vulnerable doc files.

The Snort Community Ruleset released as of 24th May 2006 contains rules to detect the presence of GINWUI which is installed by exploits targetting this vuln. This in my opinion though is the detection of a particular instance of post-compromise behavior where the preferred method for initial vulnerability exploitation should had been via an Anti-Virus system.

The Rules:

# DNS Rules

alert udp $HOME_NET any -> $EXTERNAL_NET 53
(
msg:"COMMUNITY VIRUS Ginwui.B command server dns query attempt – scfzf.xicp.net";
content:"|01 00|";
offset:2;
depth:2;
content:"|05|scfzf|04|xicp|03|net";
threshold: type limit, track by_src, count 1, seconds 360;
reference:url,vil.nai.com/vil/content/v_139545.htm;
sid:100000310; rev:1;
)

alert udp $HOME_NET any -> $EXTERNAL_NET 53
(
msg:"COMMUNITY VIRUS Ginwui.B command server dns query attempt – localhosts.3322.org";
content:"|01 00|";
offset:2;
depth:2;
content:"|0A|localhosts|04|3322|03|org";
threshold: type limit, track by_src, count 1, seconds 360;
reference:url,vil.nai.com/vil/content/v_139545.htm;
sid:100000311;
rev:1;
)

alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS
(
msg:"COMMUNITY VIRUS Ginwui.B POST attempt";
content:"POST|20 2F|";
nocase;
depth:6;
content:"Host|3a|";
nocase;
content:"scfzf.xicp.net";
nocase;
pcre:"/Host\x3A[^\n\r]+scfzf.xicp.net/smi"; content:"Content-Length|3a 20|0";
nocase;
content:"Connection|3a| Keep-Alive";
nocase;
threshold: type limit, track by_src, count 1, seconds 360;
reference:url,vil.nai.com/vil/content/v_139545.htm;
sid:100000312;
rev:1;
)

Bad Word File Detector:

The Sourcefire VRT has also released a command line tool to check the structure of a Microsoft Word document to determine if the document contains a SmartTag structure that could be leveraged as an exploitation vector for this vulnerability.

DocCheck tool download (http://www.snort.org/rules/docs/vrt/DocCheck.zip)

Instructions for use

1. Unzip the archive
2. Open a command shell
3. Execute the tool executable with a document name for checking

Sample results for a vulnerable document are shown below:

C:\>doccheck.exe test.doc
SOURCEFIRE, MS-WORD 0DAY checker v0.1
Checking for SmartTag pointers…
WordDocument stream found: 3
WordDocument stream opened.
1Table is active.
Offset of smarttags: 0
Size of smarttags: 0
Found 21 smarttags.
Found smarttag pointer: 50005
Found smarttag pointer: 340002
Found smarttag pointer: 72006f
Found smarttag pointer: 20000
Found smarttag pointer: 4a4f0018
Found smarttag pointer: 54a51
Found smarttag pointer: 16001
Found smarttag pointer: 480009
Found smarttag pointer: 6e0069
Found smarttag pointer: 100000
Found smarttag pointer: 1400f0a4
Found smarttag pointer: 8350013
Found smarttag pointer: 4f002048
Found smarttag pointer: fff24041
Found smarttag pointer: 440016
Found smarttag pointer: 6c0075
Found smarttag pointer: 720061
Found smarttag pointer: 700061
Found smarttag pointer: 6e006f
Smarttag pointer(s) found.
Validating file…
Testing S:O 0:0 0:0
Error: Bad SmartTagTable size: VULN (hr=00000000)

The MS-Word Zero Day

Posted: May 23, 2006 in Reverse Engineering

Dang! went my snort with an alert. Oh these false positives can be so confusing at times; i thought, i had just re-configured my snort rules, and reformatted my laptop last week. "wat could be wrong" i thought. Hesitating (due to my laziness) i fired up Process View, TCPView and ethereal to monitor my traffic and began analysing my snort logs for any suspicious activity. Nothing seemed unusual from the initial looks of the raw TCP / IP headers until i saw the processes in process explorer running under SYSTEM.

Shit !! why are there two instances of smss.exe running. (smss is the NT session manager subsystem which is responsible for starting the user session. This process is initiated by the system thread and is responsible for various activities, including launching the Winlogon and Win32 (Csrss.exe) processes and setting system variables. After it has launched these processes, it waits for either Winlogon or Csrss to end. If this happens "normally," the system shuts down; if it happens unexpectedly, Smss.exe causes the system to stop responding (hanged state).

I traced back the path it was running from and SURE it wasnt the %SystemRoot%. The second instance of the application was running from C:\Document and Setttings\%USER%\ApplicationData\. A quick run of the signature verification revieled more than 6 ciritical system files including csrss.exe (Client Server Runtime Process) and services.exe (Services and Controller App) were already replaced too with an unknown version.

Convinced that my system was a virgin nomore i made a comparison of lsass.exe and srss.exe with my shadow copies to match the difference. Filtering the binary on my filemon, regmon and tcpview i started monitoring its activity. The infected srss was listening on port 5557 and on another thread trying to connect on random IPs of range 61.166.125.1 – 10 which whois-ed to an ISP in china. Cursing myself i tried to recall what-went-wrong-where. Oh hmm, i opened up thunderbird to view the last couple of emails. Duh, i remembered i had opened that word file recieved from my boss. I opened up my dev VM and snapshoted it to the current state and opened up the .doc file in the hexeditor to view the file header. Scanned the file EXPLICITELY in Trend Micro and Norton AV with updated defs reported the file as cleaned, no wonder the av vendors are still working on the signature. Windows Defender / Stinger / Core Force reported nothing as well. Sigh, thats why they call it a zero day.

The "Trojan-Dropper.MSWord.1Table.bd" showed an error message when I downloaded and opened the infected file. Clicking on ‘Retry’, the malicious file was replaced by a clean one immediately. By this time however My VM was already screwed and The Dropper went ahead and downloaded a complete binary: ‘Backdoor.Win32.Gusi’. This backdoor opened a direct channel that connected to a remote attacker suspected to be sitting in China / Taiwan, to receive and execute commands. The binary immediately hid itself after installing which shows it has rootkit capability as well.

Feeling a little more proud then john-the-network-manager, i plugged in my USB firewire to restore my laptop with the last-known-stable ghost image. Finishing my can of dew i rememberd my old good times. Yea, less filename.txt on a nix console was always safer than double clicking a wordfile.

The Microsoft Security Blog response : " Microsoft is completing development of a security update for Microsoft Word that addresses this vulnerability. The security update is now being finalized through testing to ensure quality and application compatibility and is on schedule to be released as part of the June security updates on June 13, 2006, or sooner as warranted. " (http://www.microsoft.com/technet/security/advisory/919637.mspx)
(http://www.frsirt.com/english/advisories/2006/1872)

.. sigh till then:

The only workarounds known to date:

1. Disable Word as Mail Editor in Outlook. Start Word only in safe mode: winword.exe /safe
2. A registry script that sets a Software Restriction Policy that runs any instance of ‘winword.exe’ with the ‘Basic User’ policy script from http://blogs.securiteam.com/index.php/archives/category/microsoft/
3. Turn off your computer, unplug it from the network, goto sleep and dream of a yet-another-zero-day.

My Desktop Screenshot

Posted: May 16, 2006 in My Grafix

My Desktop

Yahoo Widgets + GoogleDesktop. A larger version can be found here.

Detecting Virtualization

Posted: May 14, 2006 in Virtualisation

From time to time it is handy to be able to detect whether your binary / script / program / software is running under a virtual machine and / or a similar controlled environment. For example:

  1. You have a network of nodes where you want your binary to run but you want it to behave differently under a VM.
  2. You wrote a virus / worm / boogie-woogie and you want to make the life of the AV vendors or the sec researchers harder when they run your binary in a controlled VM.
  3. At work we make an extensive use of software simulators (in VMs off course) for testing of the products on different hardwares ( Card Readers / RFIDs / BNAs / SNAs and / or machine simulators ), the behaviors of whom are obviously different in many cases than the real Self Service Terminals.
  4. Any other reason that you can think of and is not listed here.

I googled around for other VM Detection algorithms and found some really interesting solutions. The most impressive one was Joanna Rutkowska’s swallowing the Red Pill. I wouldn’t had gone any further after reading his article but somehow I couldn’t manage to make his code produce a convincing result under XEN when I ran it on my BSD. I also found a very good USENIX paper describing the problems of implementing VMs on Intel processors. Some other cool ways for VMWare fingerprinting can also be found at http://www.trapkit.de/.

I. Detecting Microsoft VMs:

The easiest way to detect that you are inside a VM is to use hardware fingerprinting. Look for a hardware that is always present in a particular VM. For e.g. in Microsoft based VMs (Virtual Server / Virtual PC) a clear indicator is that the “Motherboard” is manufactured by Microsoft Corporation : ).

use strict;
use Win32::OLE('in');

use constant wbemFlagReturnImmediately => 0×10;
use constant wbemFlagForwardOnly => 0×20;

my @computers = ("localhost");
foreach my $computer (@computers) {
print "\n";
print "==========================================\n";
print "Computer: $computer\n";
print "==========================================\n";

my $objWMIService = Win32::OLE->GetObject("winmgmts:\\\\$computer\\root\\CIMV2") or die "WMI connection failed.\n";
my $colItems = $objWMIService->ExecQuery("SELECT * FROM Win32_BaseBoard", "WQL",
wbemFlagReturnImmediately | wbemFlagForwardOnly);

foreach my $objItem (in $colItems) {
print "Caption: $objItem->{Caption}\n";
print "ConfigOptions: " . join(",", (in $objItem->{ConfigOptions})) . "\n";
print "CreationClassName: $objItem->{CreationClassName}\n";
print "Depth: $objItem->{Depth}\n";
print "Description: $objItem->{Description}\n";
print "Height: $objItem->{Height}\n";
print "HostingBoard: $objItem->{HostingBoard}\n";
print "HotSwappable: $objItem->{HotSwappable}\n";
print "InstallDate: $objItem->{InstallDate}\n";
print "Manufacturer: $objItem->{Manufacturer}\n";
print "Model: $objItem->{Model}\n";
print "Name: $objItem->{Name}\n";
print "OtherIdentifyingInfo: $objItem->{OtherIdentifyingInfo}\n";
print "PartNumber: $objItem->{PartNumber}\n";
print "PoweredOn: $objItem->{PoweredOn}\n";
print "Product: $objItem->{Product}\n";
print "Removable: $objItem->{Removable}\n";
print "Replaceable: $objItem->{Replaceable}\n";
print "RequirementsDescription: $objItem->{RequirementsDescription}\n";
print "RequiresDaughterBoard: $objItem->{RequiresDaughterBoard}\n";
print "SerialNumber: $objItem->{SerialNumber}\n";
print "SKU: $objItem->{SKU}\n";
print "SlotLayout: $objItem->{SlotLayout}\n";
print "SpecialRequirements: $objItem->{SpecialRequirements}\n";
print "Status: $objItem->{Status}\n";
print "Tag: $objItem->{Tag}\n";
print "Version: $objItem->{Version}\n";
print "Weight: $objItem->{Weight}\n";
print "Width: $objItem->{Width}\n";
print "\n";
}
}sub WMIDateStringToDate(strDate)
{
return "blah";
}

The above script uses WMI to find out the motherboard manufacturer information. If the motherboard is made by "Microsoft Corporation" then you’re inside one of Micorosft VMs.( The script requires Active State Perl 5.6 or greater and WMI enabled ).

Going to the Lower Level:

When an invalid instruction (that is not present in the Instruction Set Architecture) is encountered, the machine raises an exception of the type "Invalid Opcode". The software can either handle the exception (using the usual try/catch mechanism), let the operating system handle the exception, or worse: if the programmer is like me: crash the machine.

Virtual Server uses a bunch of invalid instructions to allow the interfacing between the virtual machine and the Virtual Server software.

Here's what happens when Virtual Server's VM wants to talk with Virtual Server:

  • The program sets exception handlers (try/catch blocks).
  • Set needed parameters before calling the VM software.
  • Issue a special "Invalid Opcode" instruction.
  • VM software will recognize this invalid opcode and act accordingly, causing no exception if VirtualServer was present, and an exception if Virtual Server isn't present.
  • The program's "catch" block will handle the exception and examine the returned parameters for the presence/absence of VM software.
  • In short, Virtual Server uses the "Invalid Opcode" mechanism as a backdoor.

The following code shows how to detect Virtual Server's presence:

DWORD __forceinline IsInsideVPC_exceptionFilter(LPEXCEPTION_POINTERS ep)
{
PCONTEXT ctx = ep->ContextRecord;

ctx->Ebx = -1; // Not running VPC
ctx->Eip += 4; // skip past the "call VPC" opcodes
return EXCEPTION_CONTINUE_EXECUTION;
// we can safely resume execution since we skipped faulty instruction
}

// High level language friendly version of IsInsideVPC()
bool IsInsideVPC()
{
bool rc = false;

__try
{
_asm push ebx
_asm mov ebx, 0 // It will stay ZERO if VPC is running
_asm mov eax, 1 // VPC function number

// call VPC
_asm __emit 0Fh
_asm __emit 3Fh
_asm __emit 07h
_asm __emit 0Bh

_asm test ebx, ebx
_asm setz [rc]
_asm pop ebx
}
// The except block shouldn't get triggered if VPC is running!!
__except(IsInsideVPC_exceptionFilter(GetExceptionInformation()))
{
}

return rc;
}

Code Details:

  • Install exception handlers.
  • Prepare input registers "eax" & "ebx".
  • Issue invalid instruction 0x0F 0x3F 0×07 0x0B. This invalid instruction is like a function designator, it tells Virtual Server what to DO exactly. For other functionality, Virtual Server uses another invalid instruction.
  • Inside the exception handler -> modify registers so to mark VM's absence (EBX is set to -1 if exception is triggered -> VM is absent).
  • Return from exception and resume execution (only if VM was absent).
  • Inspect returned registers accordingly.

II. Detecting VMWare:

VMware contains a program called "VMware Command Line Tools". These tools communicate with the host system via the VMware virtual machine (the same method is used by the official VMware-Tools).

Also both Virtual Server and VMWare allows you to install "add-ins" to accelerate emulation, allow drag-n-drop from your real desktop to your virtual desktop, and allow file sharing between your real machine and the virtual machine.

In order to accomplish this , a communication mechanism between the virtual machine software and the virtual machine itself must exist. This sort of interfacing is called a "backdoor interfacing", since, using a special/undocumented mechanism, certain commands can be carried and interpreted in a different manner (by the virtual machine software) unlike having them interpreted by the real machine.

The basic idea is that the communication is done through a special I/O port specific to the VMware virtual machines.

The following sequence is used to call VMwares environment:

MOV EAX, 564D5868h ; Magic Number
MOV EBX, COMMAND_SPECIFIC_PARAMETER
MOV ECX, BACKDOOR_COMMAND_NUMBER
MOV DX, 5658h ; Port Number

IN EAX, DX

Though it may appear to be an ordinary I/O access routine at first glance, several VMware specific mechanisms are involved in this. What is not apparent from this example is that data can be transferred to both directions with this routine. As shown in the example, the Magic number (0x564D5868 or 'VMXh') is stored in EAX and other certain values are stored in EBX and ECX prior to executing IN instruction. Although values in these registers have no effect on IN instruction in real machines, VMwares environments use these values as their input parameters. Also some functions return their results in EBX, ECX and EDX as well as in EAX. Consequently, you can not use C library functions to access this Backdoor port (e.g. _inp() function in MSVC runtime library), because those functions never expect these registers to be changed by IN instruction.

As the above I/O port doesn't exist on non-VMware environments, a malicious code can detect whether it runs under VMware or not, and act accordingly.

Code Description:

The Intel x86 provides two instructions to allow you to carry I/O operations, the "IN" and "OUT". These instructions are privileged instructions and cannot be used in a user-mode (while in protected mode) process unless the necessary privileges are enabled, so using them in normal cases will cause an exception of the type: "EXCEPTION_PRIV_INSTRUCTION". VMWare uses the "IN" instruction to read from a special port. This port does not effectively exist, however when VMWare is present, that port will be the interface between the virtual machine and VMWare.

bool IsInsideVMWare()

{
bool rc = true;

__try
{
__asm
{
push edx
push ecx
push ebx

mov eax, 'VMXh'
mov ebx, 0 // any value except the MAGIC
mov ecx, 10 // get VMWare version
mov edx, 'VX' // port number

in eax, dx // read port
// on return EAX returns the VERSION
cmp ebx, 'VMXh' // is it VMWare?
setz [rc] // set return value

pop ebx
pop ecx
pop edx
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
rc = false;
}

return rc;
}

The so called algorithm:

  • The program sets exception handlers (in case VMWare isn't present, just discard its presence).
  • Set up into the EAX register the magic number 0x564D5868 (or 'VMXh').
  • Set EBX register to any value but the magic number.
  • Set ECX register to the "function number" value. The value 10 means Get VMWare version, other codes means other functionality.
  • Set into DX the magic port number 0×5658 (or 'VX'), this special port number allows interfacing with VMWare when it is present.
  • Read from that port into EAX.
  • When VMWare is not present, an exception will occur so VMWare's presence is discarded
  • Otherwise, the code flow continues.
  • EBX should now read the magic number value.
  • If so, then VMWare is present.