The first half of 2009 has seen the following main virus threats: Conficker, Virut and Neeris. The latter is a worm which spreads like Conficker by exploiting the MS08-067 vulnerability. It was far from receiving the same media attention as Conficker but did succeed in infecting many companies. Different ways of spotting the first infected machine on a network, namely the infection source, are described in this post.

It is assumed that all machines are synchronized with a time server; comparing time between machines then makes sense and our problem boils down to determining the infection date of each machine. This can be determined from the modifications the worm made on the system, mainly on the filesystem, events and registry (NB: a filter like "Category is Write" in Process Monitor is a good starting point).

Filesystem

The worm begins by copying itself in C:\WINDOWS\system under a randomly chosen name, netmon.exe in this case. NTFS attributes give the file creation date and time, that is to say an infection date (NB: first, fls is used to get the index of the file in the MFT, then istat is used to retrieve the information):

$ fdisk -ul neeris_disque.raw
neeris_disque.raw1   *          63     8369864     4184901    7  HPFS/NTFS
$ fls -o 63 -r neeris_disque.raw | grep netmon
++ r/r 9433-128-3:	netmon.exe
$ istat -o 63 neeris_disque.raw 9433
$STANDARD_INFORMATION Attribute Values:
Created:	Mon Aug 31 18:02:33 2009
File Modified:	Mon Aug 31 18:02:32 2009
MFT Modified:	Tue Sep  1 06:36:38 2009
Accessed:	Mon Aug 31 18:02:33 2009

Similarly, the worm drops a rootkit in C:\WINDOWS\system32\drivers\sysdrv32.sys. The properties of this file also give us an infection date:

$ fls -o 63 -r neeris_disque.raw | grep sysdrv32.sys
+++ r/r 9437-128-3:	sysdrv32.sys

$ istat -o 63 neeris_disque.raw 9437
$STANDARD_INFORMATION Attribute Values:
Created:	Mon Aug 31 18:02:36 2009
File Modified:	Mon Aug 31 18:02:36 2009
MFT Modified:	Mon Aug 31 18:02:36 2009
Accessed:	Mon Aug 31 18:02:36 2009

This gives us another time, showing us that this action occurred a few seconds after the other one.

We have another option: prefetch files. Prefetch is a functionality of the Windows Memory Manager which aims at speeding up the boot and application load process, enabled by default and configurable via the HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters registry key (refer to chapter 7 of the Windows Internals book for more details). Like every application, the worm is also impacted by this mechanism and Windows will create the appropriate files in C:\WINDOWS\Prefetch:

$ fls -o 63 -r neeris_disque.raw | grep NETMON
++ r/r 9436-128-4:	NETMON.EXE-0D87B210.pf
$ istat -o 63 neeris_disque.raw 9436      
$STANDARD_INFORMATION Attribute Values:
Created:	Mon Aug 31 18:02:34 2009
File Modified:	Mon Aug 31 18:02:44 2009
MFT Modified:	Mon Aug 31 18:02:44 2009
Accessed:	Mon Aug 31 18:02:34 2009

The filesystem timeline (the capture below was taken with PTK) shows that at the time determined above, temporary Internet files have been written under the NetworkService account. This is a sign of a successful exploitation of a vulnerability in a Windows network service:

All directories and files in the capture above, if their names are not system dependent, can be used to determine the infection date.

Events

The rootkit is loaded via the Windows Service Control Manager and this will generate a 7035 event in the System event log, providing us with an infection date:

Searching for this event is trivial as the rootkit always installed itself as Play Port I/O Driver. The only issue we may face would be the overwrite of these events. However, the time given by this method is relatively late (10s after the main executable was dropped).

Registry

Several modifications are made in the registry:

  1. new value in the HKLM\SOFTWARE\CurrentVersion\Run key under a randomly chosen name (netmon here), pointing to a copy of the worm in C:\WINDOWS\system
  2. new firewall exception (new value in the HKLM\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\AuthorizedApplications\List key)
  3. kernel rootkit (new HKLM\SYSTEM\CurrentControlSet\Services\sysdrv32 key)
  4. the worm runs even in safe mode with or without network support (new HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\{Minimal,Network}\netmon keys)

In the registry, dates and times are stored, but they correspond to keys and not values. Indeed, the LastWriteTime is stored in a _CM_KEY_CONTROL_BLOCK structure:

lkd> dt nt!_CM_KEY_CONTROL_BLOCK
  +0x038 KcbLastWriteTime : _LARGE_INTEGER

We are looking for a registry key specifically created by the worm which we will be able to extract the LastWriteTime (last modification time) from, and not a new value in an existing key. The second and third points above meet this requirement. The date and time can be extracted manually with regedit by exporting the key in text format:

The procedure can be automatized via the RegQueryInfoKey function which returns the information in its lpftLastWriteTime field.

Another method would be to analyze the RAM. The task has recently become easy thanks to the possibility of using RegRipper plugins against memory dumps via Volatility. First, let's list the hives available in our RAM dump via the hivelist plugin:

$ ./volatility hivelist -f neeris_ram.raw
Address      Name
0xe17ff008   \Documents and Settings\<user>\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe17f7b60   \Documents and Settings\<user>\NTUSER.DAT
0xe13112b0   \WINDOWS\system32\config\software
0xe1311b60   \WINDOWS\system32\config\default
0xe1309008   \WINDOWS\system32\config\SECURITY
0xe1309758   \WINDOWS\system32\config\SAM
0xe101b008   \WINDOWS\system32\config\system

Now, our plugin can be executed against these hives and will return the information, for example from the SYSTEM hive:

$ perl rip.pl -p neeris_lexsi -r neeris_ram.raw@0xe101b008

ControlSet001\Services\sysdrv32
[Mon Aug 31 16:02:41 2009]

ControlSet001\Control\Safeboot\Minimal\netmon
[Mon Aug 31 16:02:33 2009]

ControlSet001\Control\Safeboot\Network\netmon
[Mon Aug 31 16:02:33 2009]

ControlSet001\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\AuthorizedApplications\List
[Tue Sep  1 04:36:38 2009]

In these examples, the given time doesn't take into account the time zone (this is a memory dump from a French system at UTC+2). The time of the sysdrv32 key matches the one extracted from the event log. However, the AuthorizedApplications\List key has been modified afterwards and doesn't give a correct time.

This RegRipper plugin is available for download (please note that the plugin is not exhaustive and is only a proof of concept).

If these keys were removed by the antivirus, it is still possible to apply the LastWriteTime method on a key where the worm only added a value, such as HKLM\SOFTWARE\CurrentVersion\Run or HKLM\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\AuthorizedApplications\List, rather than on a key it created. This will surely returns a result, but it may not be correct due to legitimate modifications of these keys by other programs, which also affect the date and time (see the example above about the RAM dump). Anyway, if these dates match, chances are that this is the right infection date.

Processes

By analyzing the RAM, it is also possible to determine the time when the netmon.exe process was launched via the psscan2 Volatility plugin (NB: pslist will not work here due to the rootkit which hides this process):

$ ./volatility psscan2 -f neeris_ram.raw
PID    PPID   Time created             Time exited              Offset     PDB        Remarks
  1352    556 Mon Aug 31 11:07:23 2009                          0x00f79228 0x00f66000 spoolsv.exe     
   916    556 Mon Aug 31 11:06:55 2009                          0x0102f6b0 0x06a00000 svchost.exe     
   852    556 Mon Aug 31 11:06:53 2009                          0x0103b020 0x0643a000 svchost.exe     
   772    556 Mon Aug 31 11:06:48 2009                          0x0104da90 0x05c50000 svchost.exe     
   568    484 Mon Aug 31 11:06:41 2009                          0x0106b938 0x057d7000 lsass.exe       
   556    484 Mon Aug 31 11:06:41 2009                          0x0106d090 0x057cb000 services.exe    
  1664   1608 Mon Aug 31 16:02:34 2009                          0x0107d670 0x06f26000 netmon.exe      
   356      4 Mon Aug 31 11:06:34 2009                          0x0108c4d0 0x047dc000 smss.exe        
   460    356 Mon Aug 31 11:06:37 2009                          0x010b5488 0x052ae000 csrss.exe       
   484    356 Mon Aug 31 11:06:38 2009                          0x011b7020 0x05473000 winlogon.exe    
     4      0                                                   0x011f29c8 0x00039000 System          
  1964    556 Mon Aug 31 11:08:13 2009                          0x0604cb00 0x001c4000 alg.exe         
  1924    556 Mon Aug 31 11:08:09 2009                          0x060c8020 0x024a0000 svchost.exe     
  1036    556 Mon Aug 31 11:07:06 2009                          0x078e9508 0x0791e000 svchost.exe     
  1208   1140 Mon Aug 31 11:07:16 2009                          0x07d29020 0x07de8000 explorer.exe    
  1204   1208 Mon Aug 31 11:19:46 2009                          0x07d92820 0x0554a000 cmd.exe

Modulo the 2-hour time difference, this gives us the same date and time as determined above.

Network connections

Finally, sockets also have a creation date. By listing the sockets associated with our process (PID 1664), we are given the connections corresponding to the exploitation of the MS08-067 vulnerability on remote hosts; the first of these dates is the first exploitation attempt, and the date matches (modulo 2 hours again):

$ ./volatility sockets -f neeris_ram.raw | grep 1664 
Pid    Port   Proto  Create Time
1664   4637   6      Tue Sep 01 04:39:01 2009  
1664   4641   6      Tue Sep 01 04:39:02 2009  
1664   4645   6      Tue Sep 01 04:39:02 2009  
1664   1664   6      Tue Sep 01 01:10:06 2009  
1664   2866   6      Mon Aug 31 22:01:10 2009  
1664   4634   6      Tue Sep 01 04:39:00 2009  
1664   4638   6      Tue Sep 01 04:39:02 2009  
1664   3502   6      Tue Sep 01 01:52:38 2009  
1664   4642   6      Tue Sep 01 04:39:02 2009  
1664   4646   6      Tue Sep 01 04:39:02 2009  
1664   3762   6      Tue Sep 01 01:53:03 2009  
1664   14575  6      Mon Aug 31 16:02:36 2009  
1664   3495   6      Tue Sep 01 01:52:37 2009  
1664   1669   6      Tue Sep 01 01:10:07 2009  
1664   4635   6      Tue Sep 01 04:39:00 2009  
1664   4639   6      Tue Sep 01 04:39:02 2009

Conclusion

Different ways of determining the date when a system has been infected by Neeris have been described, through disk and RAM analysis. These methods have their own advantages and drawbacks, but their efficiency can be decreased by the actions performed by the antivirus which may remove pieces of evidence when removing the worm. Analyzing the RAM can be useful, provided the first responder doesn't arrive too late...