I am going to start a new series about sandbox and sandbox evasions. I will utilize data I gathered over last 10 years together with an experience of actually getting my hands dirty and coding my own monitor from the scratch. I actually never considered it a real sandbox, as it does way much more, but I’ll use ‘sandbox’ here, cuz everyone already knows what it is.

Creating a good sandbox is a very challenging task. Not only it’s technically challenging, but you also need to be very selective. One such area where you have to be really specific about what you do is a list of APIs that you need to intercept, because:

if you miss some – you may lose vital information from the report, or fail to intercept one of many ‘escape’ mechanisms that modern malware utilizes for evasion purposes (heaven’s gate, tricks to launch code under a different process while at the same time fooling the sandbox/av monitor that nothing is going on, etc.)

if you monitor too much – you will get a headache trying to understand the output

There are many ‘schools’ of what to intercept. Some people prefer kernel-mode hooks and monitor stuff on a high-level (or, a low-level, depending where we observe it from). They ‘see’ everything, but they miss context of the execution (process, thread, window procedure, etc.). The user-mode monitoring fans are better off when it comes to the context, but they may miss the more complex stuff. In some approaches the monitoring of APIs/services is also supported by extra checks e.g. $MFT, Registry analysis pre- and post-session, and outside-sandbox analysis of disk/file system/memory. Plus, of course network stuff.

I am personally a big fan of user-mode only monitoring. It worked for me for last 10 years pretty well, and while it may miss stuff I believe that wherever evasive or kernel mode stuff is involved you need to simply get your hands dirty and do manual analysis. This btw. is actually the fun part of the malware analyst job 🙂

Note: I am mainly talking about the manual, in-depth analysis of malware and not general-purpose sandbox that is commercially ‘required’ to ‘see’ it all. This is actually quite a headache to manage and I do not envy sandbox companies that need to worry about it.

Okay. So, if we focus on user-mode monitoring we definitely need to know what to monitor.

One approach that can be taken to figure out what APIs to monitor is…very naive statistics – naive, because based on a simple principle and this is the topic I will cover today.

Most of malware nowadays is either packed, or somehow protected. Once it executes, the wrapper launches the actual payload and during this phase it often resolves the APIs. Later on it may inject stuff into other processes, some more APIs may get resolved, and so on and so forth. It can get pretty messy.

Now, there are plenty of methods to resolve the APIs including leveraging the GetProcAddress and/or LdrGetProcedureAddress, or simply walking through the export tables of respective libraries and finding the required API addresses. You can also do pattern searching, brute-force and some fancy algorithmic API address discovery, but these are exotic cases and we don’t need to care for them.

I mentioned that this is going to be about naive statistics – this is why we will only look at GetProcAddress. All we need is data.

As long as we execute a large number of samples while we monitor this particular API we can get a nice, and quite a fair representation of popularity of certain APIs. These APIs need to be screened manually and then a subset of them can be selected for monitoring.

So, looking at results of 150K+ sandboxed samples I came up with the following list of APIs (top 100 are listed):

KERNEL32.dll CloseHandle

KERNEL32.dll WriteFile

KERNEL32.dll GetModuleHandleA

KERNEL32.dll ExitProcess

KERNEL32.dll GetLastError

KERNEL32.dll VirtualAlloc

KERNEL32.dll GetProcAddress

KERNEL32.dll VirtualFree

KERNEL32.dll Sleep

KERNEL32.dll LoadLibraryA

KERNEL32.dll SetFilePointer

KERNEL32.dll ReadFile

KERNEL32.dll CreateFileA

KERNEL32.dll WaitForSingleObject

KERNEL32.dll GetModuleFileNameA

KERNEL32.dll FlsFree

KERNEL32.dll FlsGetValue

KERNEL32.dll FlsSetValue

KERNEL32.dll FlsAlloc

KERNEL32.dll MultiByteToWideChar

KERNEL32.dll GetTickCount

KERNEL32.dll FreeLibrary

KERNEL32.dll CreateThread

KERNEL32.dll FindClose

KERNEL32.dll GetFileSize

KERNEL32.dll GetCurrentProcess

KERNEL32.dll GetCurrentThreadId

KERNEL32.dll HeapAlloc

KERNEL32.dll WideCharToMultiByte

ADVAPI32.dll RegCloseKey

KERNEL32.dll GetCurrentProcessId

KERNEL32.dll GetStdHandle

KERNEL32.dll HeapFree

KERNEL32.dll VirtualProtect

KERNEL32.dll DeleteCriticalSection

USER32.dll GetSystemMetrics

KERNEL32.dll LoadResource

KERNEL32.dll LeaveCriticalSection

KERNEL32.dll GetCommandLineA

KERNEL32.dll InitializeCriticalSection

KERNEL32.dll EnterCriticalSection

KERNEL32.dll GlobalAlloc

KERNEL32.dll LocalFree

KERNEL32.dll OpenProcess

KERNEL32.dll TerminateProcess

KERNEL32.dll LockResource

KERNEL32.dll SizeofResource

KERNEL32.dll DeleteFileA

KERNEL32.dll GetModuleFileNameW

KERNEL32.dll SetLastError

KERNEL32.dll SetEndOfFile

KERNEL32.dll RtlUnwind

KERNEL32.dll GetProcessHeap

KERNEL32.dll GetStartupInfoA

KERNEL32.dll GlobalFree

KERNEL32.dll TlsSetValue

KERNEL32.dll DeleteFileW

KERNEL32.dll TlsGetValue

KERNEL32.dll CreateFileW

KERNEL32.dll lstrlenA

KERNEL32.dll GetModuleHandleW

KERNEL32.dll GetSystemTimeAsFileTime

KERNEL32.dll GlobalUnlock

KERNEL32.dll CreateProcessA

KERNEL32.dll InterlockedDecrement

KERNEL32.dll SetUnhandledExceptionFilter

KERNEL32.dll SetEvent

KERNEL32.dll DecodePointer

KERNEL32.dll IsProcessorFeaturePresent

KERNEL32.dll LocalAlloc

KERNEL32.dll UnhandledExceptionFilter

KERNEL32.dll GlobalLock

KERNEL32.dll SetFileTime

KERNEL32.dll RaiseException

KERNEL32.dll CreateMutexA

KERNEL32.dll SetErrorMode

KERNEL32.dll FindFirstFileA

KERNEL32.dll ResumeThread

KERNEL32.dll EncodePointer

KERNEL32.dll InterlockedIncrement

KERNEL32.dll GetTempPathA

KERNEL32.dll GetFileType

ADVAPI32.dll RegOpenKeyExA

KERNEL32.dll GetACP

KERNEL32.dll GetVersionExA

KERNEL32.dll CreateToolhelp32Snapshot

KERNEL32.dll GetCPInfo

KERNEL32.dll GetFileAttributesW

USER32.dll GetMonitorInfoA

KERNEL32.dll SystemTimeToFileTime

USER32.dll MessageBoxA

KERNEL32.dll GetVersion

KERNEL32.dll IsDebuggerPresent

USER32.dll EnumDisplayMonitors

KERNEL32.dll FlushFileBuffers

KERNEL32.dll GetTempPathW

KERNEL32.dll lstrcpyA

KERNEL32.dll HeapReAlloc

KERNEL32.dll ReleaseMutex

KERNEL32.dll TlsAlloc