Blogs :: Martin Pillion
All Blogs
Greg Hoglund
Rich Cummings
Jim Butterworth
Chris Harrison
Jeremy Flessing
Charles Copeland
Michael Snyder
Martin Pillion
Jim Richards
Shawn Bracken
Scott Pease

About Martin Pillion

Martin Pillion is Director of Threat Intelligence at HBGary

12>>
Page 1 of 2

Further investigation of the Zero Access rootkit

In a previous blog I explored the methods and techniques that Zero Access uses to hook kernel functions.  One of the functions I mentioned was IoIsOperationSynchronous, which caught the eye of an astute reader.  Why does Zero Access hook IoIsOperationSynchronous? 

Hooked IoIsOperationSynchronous:

804EE549   loc_804EE549:
804EE549       call 0xF78D40F5   // call Hook_Implementation
 
804EE54E   Subroutine IoIsOperationSynchronous:
804EE54E       jmp 0x804EE549    // Jump to Hook call
 
804EE550   loc_804EE550:
804EE550       push ebp
804EE551       mov ebp,esp

Initially, I thought it was because IoIsOperationSynchronous is called by many system threads and would provide a method to obtain consistent time slices from the system without creating a new system thread.  However, there are many kernel functions that would serve the same purpose, so why hook IoIsOperationSynchronous?  

IoIsOperationSynchronous does have the added benefit of providing access to many of the system's IRPs, especially file system IRPs.  When I examined the code run by the hook, Zero Access uses the IRP passed into IoIsOperationSynchronous.

F78D40F5   Subroutine Hook_Implementation:
F78D40F5       pushad
F78D40F6       mov ecx,dword ptr [esp+0x28]  // obtain pIrp passed into IoIsOperationSynchronous
F78D40FA       call 0xF78CF940               // call IrpHandler
 
F78D40FF   loc_F78D40FF:
F78D40FF       popad
F78D4100       add dword ptr [esp],0x2       // Increment the return address by 2 so we skip over the hook jmp code
F78D4104       ret

What is located at [esp+0x28]?  Let's examine the stack after the pushad instruction::

esp+00 [edi]
esp+04 [esi]
esp+08 [ebp]
esp+0c [esp]
esp+10 [ebx]
esp+14 [edx]
esp+18 [ecx]
esp+1c [eax]
esp+20 [804EE54E]   // ret address to IoIsOperationSynchronous
esp+24 [xxxxxxxx]   // ret address to caller of IoIsOperationSynchronous
esp+28 [pIRP]       // arg0 = pIrp

There is the IRP.  Just glancing at the IrpHandler() function, the use of "%u.exe" and string comparison stand out immediately.  Is it checking the process name?

F78CF940   Subroutine IrpHandler
F78CF940       mov eax,dword ptr [ecx+0x60]  // pIrp->Tail.Overlay.CurrentStackLocation
F78CF943       sub esp,0x50                  // make space on the stack for some local variables
F78CF946       cmp byte ptr [eax],0x0
F78CF949       jne 0xF78CF9C2

ECX is the IRP pointer passed into IoIsOperationSynchronous.  ECX+60 is the offset for pIrp->Tail.Overlay.CurrentStackLocation, so this initial block of code is behaving like IoGetCurrentIrpStackLocation().

F78CF94B   loc_F78CF94B:
F78CF94B       push esi
F78CF94C       mov esi,dword ptr [eax+0x18]  // obtain IoStackLocation->FileObject
F78CF94F       test esi,esi
F78CF951       je 0xF78CF9C1

The FileObject member of the stack location is retrieved.

F78CF953   loc_F78CF953:
F78CF953       mov eax,dword ptr [0xF78D9984]   // data_F78D9984
F78CF958       not eax
F78CF95A       push eax
F78CF95B       lea ecx,[esp+0x18]
F78CF95F       push 0xF78D74A8                  // %u.exe
F78CF964       push ecx
F78CF965       call dword ptr [0xF78D7084]      // __ptr_ntoskrnl.exe!swprintf[80536BA5]

Zero Access creates a wide string buffer with "%u.exe" formatting.  The parameter supplied to printf for the %u is a dword equivalent for the usermode component's name.  For example: 

NOT 0xA0B8A151
= 0x5F475EAE
= 1598512814 in decimal, so the zero Access usermode component's process (and file) name is 1598512814.exeA5]
 
This could be used as a file name or a process name comparison. 

F78CF96B   loc_F78CF96B:
F78CF96B       movzx ecx,word ptr [esi+0x30] // length of target filename from FileObject->FileName.Length
F78CF96F       add eax,eax
F78CF971       add esp,0xC
F78CF974       lea edx,[esp+0x14]            // ptr to swprintf dest buffer
F78CF978       mov word ptr [esp+0xC],ax     // set length
F78CF97D       mov word ptr [esp+0xE],ax     // set max length
F78CF982       mov dword ptr [esp+0x10],edx  // set ptr
F78CF986       cmp cx,ax                     // Is caller target filename long enough?
F78CF989       jb 0xF78CF9C1

Obtains the FileObject->FileName.Length field and uses that to validate the string lengths before doing the actual string comparison.  The block also sets up a UNICODE_STRING on the local stack.

F78CF98B   loc_F78CF98B:
F78CF98B       mov edx,dword ptr [esi+0x34]  // ptr to target filename buffer
F78CF98E       mov word ptr [esp+0x4],ax
F78CF993       mov word ptr [esp+0x6],ax
F78CF998       movzx eax,ax
F78CF99B       sub edx,eax
F78CF99D       movzx eax,cx
F78CF9A0       add edx,eax
F78CF9A2       push 0x1
F78CF9A4       lea ecx,[esp+0x8]
F78CF9A8       mov dword ptr [esp+0xC],edx
F78CF9AC       push ecx
F78CF9AD       lea edx,[esp+0x14]
F78CF9B1       push edx
F78CF9B2       call dword ptr [0xF78D7028]   // __ptr_ntoskrnl.exe!RtlEqualUnicodeString[805D67A2]

Compare the FileObject Name from the IRP to the manually constructed string.

F78CF9B8   loc_F78CF9B8:
F78CF9B8       test al,al
F78CF9BA       je 0xF78CF9C1     // jmp if RtlEqualUnicodeString returned 0 (strings are not equal)
 
F78CF9BC   loc_F78CF9BC:
F78CF9BC       call 0xF78CD650   // call Handle_ZeroAccess_UserModeComponent_IRP
 
F78CF9C1   loc_F78CF9C1:
F78CF9C1       pop esi
 
F78CF9C2   loc_F78CF9C2:
F78CF9C2       add esp,0x50
F78CF9C5       ret

If the strings match,  Handle_ZeroAccess_UserModeComponent_IRP is called.  Otherwise the function returns without doing anything.
 
So now the question is, what does Handle_ZeroAccess_UserModeComponent_IRP do?  Is it trying to block file access to the user mode component's file?  Is it using this as a usermode->kernelmode communication mechanism?  Or is it returning false data for file reads to prevent AV detection?
 
To be continued in my next blog...

Posted by Martin Pillion on February 7, 2012 at 5:53pm

Analyzing pieces of the Zero Access rootkit

One of our customers recently asked us to take a look at the inner workings of the Zero Access rootkit. After analyzing it in Responder Pro, I decided to blog about a few of the interesting pieces. I'll start with its use of a known but not often used method of loading a kernel driver from kernel mode. The core of this method is to use the ZwSetSystemInformation function with SYSTEM_INFORMATION_CLASS number 0x36 (SystemLoadGdiDriverInSystemSpaceInformation). As the name implies, this allows a driver to load and map a PE file into system space (instead of session space). Essentially, it just calls MmLoadSystemImage and MmPageEntireDriver.

 

Zero Access Code Snippet:

F78D3A60   Subroutine sub_F78D3A60:
F78D3A60       sub esp,0x70
F78D3A63       mov ecx,dword ptr [eax]
F78D3A65       mov edx,dword ptr [eax+0x4]
F78D3A68       push esi
F78D3A69       mov esi,dword ptr [0xF78D71C8]
F78D3A6F       push 0x1C                      // sizeof SYSTEM_GDI_DRIVER_INFORMATION struct
F78D3A71       lea eax,[esp+0x18]
F78D3A75       push eax                       // pointer to SYSTEM_GDI_DRIVER_INFORMATION struct
F78D3A76       push 0x36                      // SystemLoadGdiDriverInSystemSpaceInformation (54)
F78D3A78       mov dword ptr [esp+0x20],ecx
F78D3A7C       mov dword ptr [esp+0x24],edx
F78D3A80       call esi                       //  __ptr_ntoskrnl.exe!ZwSetSystemInformation
F78D3A82   loc_F78D3A82:
F78D3A82       test eax,eax
F78D3A84       jl 0xF78D3B28                  // eax > 0

 

Now that the requested driver code is loaded into system memory, Zero Access creates a driver name and calls the undocumented IoCreateDriver function. IoCreateDriver creates and initializes a DRIVER_OBJECT, then calls an initialization function that is provided as a parameter (usually the exported DriverEntry function, but for Zero Access it is a hardcoded internal function pointer). This is very similar to code found in TDL4.

 

Zero Access Code Snippet:

F78D3A8A   eax >= 0:
F78D3A8A       push 0x0
F78D3A8C       lea ecx,[esp+0xC]
F78D3A90       push ecx
F78D3A91       lea edx,[esp+0x38]
F78D3A95       push 0xF78D78D8:[              // \driver\%I64u
F78D3A9A       push edx
F78D3A9B       call dword ptr [0xF78D7084]    // __ptr_ntoskrnl.exe!swprintf
F78D3AA1   call_RtlInitUnicodeString:
F78D3AA1       add esp,0x10
F78D3AA4       lea eax,[esp+0x30]
F78D3AA8       push eax
F78D3AA9       lea ecx,[esp+0x10]
F78D3AAD       push ecx
F78D3AAE       call dword ptr [0xF78D7088]    // __ptr_ntoskrnl.exe!RtlInitUnicodeString
F78D3AB4   call___ptr_ntoskrnl.exe!IoCreateDriver[80569566]:
F78D3AB4       push 0xF78D39C0                // Initialization Function
F78D3AB9       lea edx,[esp+0x10]
F78D3ABD       push edx                       // DriverName
F78D3ABE       call dword ptr [0xF78D71CC]    // __ptr_ntoskrnl.exe!IoCreateDriver

 

Zero Access also hooks functions exported by various drivers, including the kernel. It does this by creating an Mdl for the address of the function to be hooked, updating the Mdl to have the appropriate physical page, mapping the page with caching, and then modifying the bytes just before and at the start of the function with a call HookFunction and short jmp -5.

 

Zero Access Code Snippet:

F78CF740   Subroutine Hook_Kernel_Function:
F78CF740       push edi
F78CF741       mov edi,eax
F78CF743       mov eax,0xFF8B
F78CF748       cmp word ptr [ebx],ax          // check if it is already hooked...
F78CF74B       jne 0xF78CF7C3
F78CF74D   loc_F78CF74D:
F78CF74D       push esi
F78CF74E       push 0x0
F78CF750       push 0x0
F78CF752       push 0x0
F78CF754       push 0x7
F78CF756       lea ecx,[ebx-0x5]
F78CF759       push ecx
F78CF75A       call dword ptr [0xF78D70B4]    // __ptr_ntoskrnl.exe!IoAllocateMdl

F78CF760   loc_F78CF760:
F78CF760       mov esi,eax
F78CF762       test esi,esi
F78CF764       je 0xF78CF7C2
F78CF766   loc_F78CF766:
F78CF766       push ebp
F78CF767       push esi
F78CF768       call dword ptr [0xF78D70B8]    // __ptr_ntoskrnl.exe!MmBuildMdlForNonPagedPool

F78CF76E   loc_F78CF76E:
F78CF76E       movzx eax,word ptr [esi+0x6]
F78CF772       movzx ebp,ax
F78CF775       and eax,0xFFFFFFFB
F78CF778       or eax,0x2
F78CF77B       mov word ptr [esi+0x6],ax
F78CF77F       test al,0x5
F78CF781       je 0xF78CF788
F78CF783   loc_F78CF783:
F78CF783       mov eax,dword ptr [esi+0xC]
F78CF786       jmp 0xF78CF799
F78CF788   loc_F78CF788:
F78CF788       push 0x0
F78CF78A       push 0x0
F78CF78C       push 0x0
F78CF78E       push 0x1
F78CF790       push 0x0
F78CF792       push esi
F78CF793       call dword ptr [0xF78D70BC]    // __ptr_ntoskrnl.exe!MmMapLockedPagesSpecifyCache
F78CF799   loc_F78CF799:
F78CF799       test eax,eax
F78CF79B       je 0xF78CF7B6

F78CF79D   loc_F78CF79D:
F78CF79D       push esi
F78CF79E       sub edi,ebx
F78CF7A0       mov edx,0xF9EB                 // bytes for jmp -5
F78CF7A5       push eax
F78CF7A6       mov byte ptr [eax],0xE8        // Call Instruction Opcode
F78CF7A9       mov dword ptr [eax+0x1],edi    // offset to hook function
F78CF7AC       mov word ptr [eax+0x5],dx      // jmp -5
F78CF7B0       call dword ptr [0xF78D70C0]    // __ptr_ntoskrnl.exe!MmUnmapLockedPages

F78CF7B6   loc_F78CF7B6:
F78CF7B6       push esi
F78CF7B7       mov word ptr [esi+0x6],bp
F78CF7BB       call dword ptr [0xF78D70C4]    // __ptr_ntoskrnl.exe!IoFreeMdl

F78CF7C1   loc_F78CF7C1:
F78CF7C1       pop ebp
F78CF7C2   loc_F78CF7C2:
F78CF7C2       pop esi
F78CF7C3   loc_F78CF7C3:
F78CF7C3       pop edi
F78CF7C4       ret

 

One of the functions hooked by Zero Access is ntoskrnl!IoIsOperationSynchronous. After hooking, the function looks like this:

 

NTOS Kernel Code Snippet:

804EE549   loc_804EE549:
804EE549   E8 A7 5B 3E 77        call 0xF78D40F5           // call the Hook function
804EE54E   Subroutine IoIsOperationSynchronous:
804EE54E   EB F9                 jmp 0x804EE549            // Hook
804EE550   loc_804EE550:
804EE550   55                    push ebp
804EE551   8B EC                 mov ebp,esp
804EE553   8B 45 08              mov eax,dword ptr [ebp+0x8]
804EE556   8B 48 60              mov ecx,dword ptr [eax+0x60]
804EE559   8B 49 18              mov ecx,dword ptr [ecx+0x18]
804EE55C   F6 41 2C 02           test byte ptr [ecx+0x2C],0x2

 

Zero Access also uses this same method to hook the root ACPI driver's IRP_MJ_INTERNAL_DEVICE_CONTROL function:

 

Zero Access Code Snippet:

F78D3D4C   8B 98 34 01 00 00      mov ebx,dword ptr [eax+0x00000134]
F78D3D52   8B 8C 24 20 04 00 00   mov ecx,dword ptr [esp+0x00000420]     // DriverObject
F78D3D59   8D 44 24 10            lea eax,[esp+0x10]                     // DeviceObject
F78D3D5D   50                     push eax
F78D3D5E   6A 01                  push 0x1
F78D3D60   68 00 01 00 00         push 0x0100
F78D3D65   6A 32                  push 0x32                        // Device Type ACPI
F78D3D67   6A 00                  push 0x0
F78D3D69   6A 10                  push 0x10
F78D3D6B   51                     push ecx
F78D3D6C   FF 15 8C 71 8D F7      call dword ptr [0xF78D718C]      // !IoCreateDevice
...
F78D3D9C   8B 44 24 10            mov eax,dword ptr [esp+0x10]
F78D3DA0   81 48 1C 10 20 00 00   or dword ptr [eax+0x1C],0x00002010
F78D3DA7   8B 44 24 10            mov eax,dword ptr [esp+0x10]
F78D3DAB   81 60 1C 7F FF FF FF   and dword ptr [eax+0x1C],0xFFFFFF7F
F78D3DB2   8B 06                  mov eax,dword ptr [esi]
F78D3DB4   50                     push eax
F78D3DB5   FF 15 E4 71 8D F7      call dword ptr [0xF78D71E4]      // !IoGetDeviceAttachmentBaseRef

F78D3DBB   8B E8                  mov ebp,eax                      // PDEVICE_OBJECT
F78D3DBD   8B 4D 08               mov ecx,dword ptr [ebp+0x8]      // ->PDRIVER_OBJECT
F78D3DC0   8B 59 74               mov ebx,dword ptr [ecx+0x74]     // ->MajorFunction [
                                                                   // IRP_MJ_INTERNAL_DEVICE_CONTROL]
F78D3DC3   85 DB                  test ebx,ebx
F78D3DC5   74 0A                  je 0xF78D3DD1

F78D3DC7   B8 F0 F8 8C F7         mov eax,0xF78CF8F0               // Hook func
F78D3DCC   E8 6F B9 FF FF         call 0xF78CF740 ?                // ZeroAccess!Hook_Kernel_Function

 

Neither method is new, but both are implemented elegantly. The Zero Access rootkit appears to be a well-written kernel driver. It takes great care to handle error conditions, reference and dereference objects, and synchronize access with locking mechanisms. The observable impact to system performance is minimal and I don't expect it to cause system crashes.

 

Much like the TDSS series of rootkits, it seems that the Zero Access rootkit was professionally developed.

Posted by Martin Pillion on December 21, 2011 at 2:42pm

The Evolution of Memory-only Malware

Malware detection is a complex game of cat and mouse. Yet every time the cat finds a way to catch the mouse, ten new mice are created that know how to avoid the cat. This constant back and forth has driven the development of malware in a convoluted direction. Advanced malware often uses multiple techniques in an attempt to hide its behavior. For example, some attempt to detect if they are being debugged or virtualized. Some encode strings, hide the use of certain API functions, or wrap themselves in legitimate looking code. The list of malware techniques is nearly endless and always evolving. Here is a look at how memory-only malware evolved and adapted.

Memory-only malware

One technique that cropped up many years ago was memory-only malware. It was used to avoid writing to disk and creating artifacts that could be detected by anti-virus software and hard drive forensics. Eventually the cat learned to detect the mouse and the memory-only technique became just another entry in the list of detectable techniques.

Chunked memory-only malware

In 2010 we began to see a new spin on the memory-only technique. Some malware would split its functionality across multiple single page allocations, thus spreading its behavior into many pieces and making it more difficult to determine what the malware was attempting to do. The pinnacle of this technique was a malware that split into 18 separate chunks. Separately, most of these chunks looked innocuous. They were often hand written assembly that resembled shellcode. Most used indirect calls through registers + offsets to obscure what function was being called. A single block contained data and arrays of function pointers. A pointer to this data block would be passed around with every internal call.

01100000   loc_01100000:
01100000       push ebp  
01100001       mov ebp,esp  
01100003       add esp,0xFFFFFA30  
01100009       mov esi,dword ptr [ebp+0x8]  
0110000C       lea eax,[esi+0x000003FB]  
01100012       push eax  
01100013       push 0x0  
01100015       push 0x0 
01100017       call dword ptr [esi+0x00000085]  // Module32NextW

In the above example, a passed parameter [ebp+0x8] is moved into esi, then esi + 0x85 is used for an indirect call. The function called is Module32NextW, but how would an anti-virus program determine that when statically analyzing a section of memory?

Obviously malware doesn't need to spread itself all over memory to use indirect calls, but when all the code, data, and function pointers are contained in a single module it is easier to determine if something is malicious.

This particular malware is now detected by a majority of anti-virus products on the market, although I suspect some use byte-based signatures to detect it (easy to avoid). But this malware is old news, what is the next step?

Cross process, chunked, memory-only malware

The latest variant we have seen involves spreading the malware chunks across multiple processes. Memory is allocated in multiple processes and small pieces of the malware are copied to each. One process contains the code for installing and surviving reboot. Another process (usually the browser) contains the code for sending communications, while another monitors the communication process and can re-inject or restart the process if needed. Yet another process does keylogging. Every major behavior of the malware is injected into a separate process. They all communicate using a single shared page of memory accessed through a randomly named global file mapping. Access is synchronized using the InterlockedXXX API calls to behave like a spinlock.

Creating cross process, chunked, memory-only malware definitely takes more time and more skill than most other malware (though not as much as kernel based malware). It adds overhead and makes debugging more difficult. It increases the chance of failure due to OS differences or permission restrictions. It is complex, yet just another step in the evolution of this type of malware.

The future of memory-only malware

Perhaps the next step in memory-only malware evolution is a separation of components so that you have to be infected with multiple distinct pieces of the malware before the malicious behavior is functional and/or decrypted. Or perhaps we have reached the end of memory-only malware evolution. All I know for sure is that future malware will find a way to surprise us.

- Martin Pillion

Posted by Martin Pillion on October 21, 2011 at 12:00am

Malware using the Local Group Policy

Malware is constantly finding obscure ways to hide hooks within the OS so that it can remain active after a reboot. One approach that we encountered recently involved using the Local Group Policy. Group Policy is a set of rules and settings that can be used to manage the Operating System and environment.

Local Group Policy is a simpler version of Group Policy. Group Policy is a complicated beast. It is not well understood by many system administrators or thoroughly examined by many security applications. Both are a prime location for malware to hide in plain sight.

Local Group Policy summary


Figure 1: Component Architecture 1

In our example, we will focus on the Local Group Policy. Prior to Windows Vista, a system had a single Local Group Policy object (except Windows NT which has none). Newer Windows OS versions support Multiple Local Group Policy objects, but are still backwards compatible with the single object model.

As their name implies, Local Group Policy objects are stored locally on a system. It does not matter if the system is part of Active Directory or even in a network environment. However, Group Policy objects can override Local Group Policy objects. 2

You can edit the Local Group Policy object using an MMC snap-in. The quickest way is to open the Run Dialog and type "gpedit.msc". 3


Figure 2: The Local Group Policy Editor in Windows 7

The Local Group Policy data is stored at %SystemRoot%\system32\GroupPolicy. In this directory you will find gpt.ini, which contains version and synchronization information for each required file component.

There are many things you can do with a Local Group Policy object, but we will focus on Scripts. Scripts allow the execution of code when specific events occur. Scripts of particular interest include User Logon or Logoff, and Computer Startup or Shutdown 4. These scripts are referred to as Client-Side Extensions (CSE).

Client-Side Extensions

CSE information is stored in the registry at:

HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\Winlogon\ GPExtensions

Under this Registry key you will find a list of CLSID subkeys for each installed CSE. Malware interested in Script execution will utilize the object CLSID {42B5FAAE-6536-11D2-AE5A-0000F87571E3} which is the object responsible for processing Group Policy scripts.


Figure 3: The GPExtensions Scripts subkey in Windows 7

Programmatically Adding a Logon/Logoff Script

Step 1: Modify %SystemRoot%\system32\GroupPolicy\gpt.ini


Figure 4: Malware Example

To add a logon/logoff script you have to add the Script CSE to gpt.ini. We do this by adding the following line in the [General] section:

gPCUserExtensionNames=[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B66650-4972-11D1-A7CA-0000F87571E3}]

This tells the CSE engine that the Script CSE (42B5FAAE-6536-11D2-AE5A-0000F87571E3) and the Logon/Logoff MMC extension (40B66650-4972-11D1-A7CA-0000F87571E3)have data in the Local Group Policy object.


Figure 5: Malware Example

We should also update the version information. There is an official method for incrementing the version based on what we changed: add 1 if we made a machine specific change, add 65536 if we made a user specific change.

Version=65536

Step 2: Create the full path for your scripts

For Logon scripts the path is

%SystemRoot%\system32\GroupPolicy\User\Scripts\Logon

For Logoff:

%SystemRoot%\system32\GroupPolicy\User\Scripts\Logoff

Within the directory, create the script file that you want to be executed. Something like

Badmalware.cmd

Note: This does not have to be a script! It can be an executable instead.

Step 3: Modify %SystemRoot%\system32\GroupPolicy\User\Scripts\scripts.ini

This is where you point the CSE to your script and provide it command line parameters. For logon scripts modify the [Logon] section, for logoff scripts the [Logoff] section:

[Logon]
CmdLine=Badmalware.cmd
Parameters={whatever options I need}


Figure 6: Malware Example

User Logon/Logoff scripts run under the specific user/domain account. Computer startup/shutdown scripts run as SYSTEM. Both of these security contexts can be used by malware to do evil things such as keylogging, screen capture, installing botnets, or searching through sensitive corporate data. The SYSTEM context is especially dangerous because it grants unrestricted access to the entire machine, which can be used to install rootkits and bypass most computer security products.

All of the above directories and files should be restricted to Administrators only by default, so this Persistence Technique only works for malware that already has Administrator access. The real value to the attacker is that most users and many IT administrators do not look for malware hiding in these places. It is a lot more involved and less understood that the typical Windows Service or Run key method.

If you are an IT Admin, it would be wise to review the Local Group Policy settings on machines in your enterprise and verify that they are configured correctly. As of version 11.0, the Autoruns 5 tool from Microsoft (SysInternals), which many Administrators rely on, does not detect Local Group Policy script settings. This is because the Autoruns tool primarily searches the Windows Registry, but all the Local Group Policy script settings are stored on the file system in the gpt.ini and scripts.ini files.

-- Martin Pillion

1 - http://technet.microsoft.com/en-us/library/cc736967(WS.10).aspx

2 - http://technet.microsoft.com/en-us/library/cc775702(WS.10).aspx

3 - http://technet.microsoft.com/en-us/library/cc787064(WS.10).aspx

4 - http://technet.microsoft.com/en-us/library/cc757265(WS.10).aspx

5 - http://technet.microsoft.com/en-us/sysinternals/bb963902

Posted by Martin Pillion on September 22, 2011 at 2:00pm
12>>
Page 1 of 2