{"id":3029,"date":"2015-05-29T13:42:47","date_gmt":"2015-05-29T13:42:47","guid":{"rendered":"http:\/\/www.hexacorn.com\/blog\/?p=3029"},"modified":"2015-05-29T14:38:01","modified_gmt":"2015-05-29T14:38:01","slug":"enter-sandbox-part-1-all-api-are-equal-but-some-apis-are-more-equal-than-others","status":"publish","type":"post","link":"https:\/\/www.hexacorn.com\/blog\/2015\/05\/29\/enter-sandbox-part-1-all-api-are-equal-but-some-apis-are-more-equal-than-others\/","title":{"rendered":"Enter Sandbox &#8211; part 1: All APIs are equal, but some APIs are more equal than others"},"content":{"rendered":"<p>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&#8217;ll use &#8216;sandbox&#8217; here, cuz everyone already knows what it is.<\/p>\n<p>Creating a good sandbox is a very challenging task. Not only it&#8217;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:<\/p>\n<ul>\n<li>if you miss some &#8211; you may lose vital information from the report, or fail to intercept one of many &#8216;escape&#8217; mechanisms that modern malware utilizes for evasion purposes (heaven&#8217;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.)<\/li>\n<li>if you monitor too much &#8211; you will get a headache trying to understand the output<\/li>\n<\/ul>\n<p>There are many &#8216;schools&#8217; 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 &#8216;see&#8217; 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.<\/p>\n<p>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 \ud83d\ude42<\/p>\n<p>Note: I am mainly talking about the manual, in-depth analysis of malware and not general-purpose sandbox that is commercially &#8216;required&#8217; to &#8216;see&#8217; it all. This is actually quite a headache to manage and I do not envy sandbox companies that need to worry about it.<\/p>\n<p>Okay. So, if we focus on user-mode monitoring we definitely need to know what to monitor.<\/p>\n<p>One approach that can be taken to figure out what APIs to monitor is&#8230;very naive statistics &#8211; naive, because based on a simple principle and this is the topic I will cover today.<\/p>\n<p>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.<\/p>\n<p>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&#8217;t need to care for them.<\/p>\n<p>I mentioned that this is going to be about naive statistics\u00a0 &#8211; this is why we will only look at GetProcAddress. All we need is data.<\/p>\n<p>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.<\/p>\n<p>So, looking at results of 150K+ sandboxed samples I came up with the following list of APIs (top 100 are listed):<\/p>\n<p>KERNEL32.dll\u00a0\u00a0 \u00a0CloseHandle<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0WriteFile<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetModuleHandleA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0ExitProcess<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetLastError<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0VirtualAlloc<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetProcAddress<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0VirtualFree<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0Sleep<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0LoadLibraryA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0SetFilePointer<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0ReadFile<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0CreateFileA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0WaitForSingleObject<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetModuleFileNameA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0FlsFree<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0FlsGetValue<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0FlsSetValue<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0FlsAlloc<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0MultiByteToWideChar<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetTickCount<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0FreeLibrary<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0CreateThread<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0FindClose<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetFileSize<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetCurrentProcess<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetCurrentThreadId<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0HeapAlloc<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0WideCharToMultiByte<br \/>\nADVAPI32.dll\u00a0\u00a0 \u00a0RegCloseKey<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetCurrentProcessId<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetStdHandle<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0HeapFree<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0VirtualProtect<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0DeleteCriticalSection<br \/>\nUSER32.dll\u00a0\u00a0 \u00a0GetSystemMetrics<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0LoadResource<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0LeaveCriticalSection<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetCommandLineA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0InitializeCriticalSection<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0EnterCriticalSection<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GlobalAlloc<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0LocalFree<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0OpenProcess<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0TerminateProcess<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0LockResource<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0SizeofResource<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0DeleteFileA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetModuleFileNameW<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0SetLastError<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0SetEndOfFile<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0RtlUnwind<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetProcessHeap<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetStartupInfoA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GlobalFree<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0TlsSetValue<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0DeleteFileW<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0TlsGetValue<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0CreateFileW<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0lstrlenA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetModuleHandleW<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetSystemTimeAsFileTime<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GlobalUnlock<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0CreateProcessA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0InterlockedDecrement<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0SetUnhandledExceptionFilter<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0SetEvent<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0DecodePointer<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0IsProcessorFeaturePresent<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0LocalAlloc<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0UnhandledExceptionFilter<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GlobalLock<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0SetFileTime<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0RaiseException<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0CreateMutexA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0SetErrorMode<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0FindFirstFileA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0ResumeThread<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0EncodePointer<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0InterlockedIncrement<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetTempPathA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetFileType<br \/>\nADVAPI32.dll\u00a0\u00a0 \u00a0RegOpenKeyExA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetACP<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetVersionExA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0CreateToolhelp32Snapshot<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetCPInfo<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetFileAttributesW<br \/>\nUSER32.dll\u00a0\u00a0 \u00a0GetMonitorInfoA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0SystemTimeToFileTime<br \/>\nUSER32.dll\u00a0\u00a0 \u00a0MessageBoxA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetVersion<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0IsDebuggerPresent<br \/>\nUSER32.dll\u00a0\u00a0 \u00a0EnumDisplayMonitors<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0FlushFileBuffers<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0GetTempPathW<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0lstrcpyA<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0HeapReAlloc<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0ReleaseMutex<br \/>\nKERNEL32.dll\u00a0\u00a0 \u00a0TlsAlloc<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 &hellip; <a href=\"https:\/\/www.hexacorn.com\/blog\/2015\/05\/29\/enter-sandbox-part-1-all-api-are-equal-but-some-apis-are-more-equal-than-others\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[28,39,9],"tags":[],"_links":{"self":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts\/3029"}],"collection":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/comments?post=3029"}],"version-history":[{"count":6,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts\/3029\/revisions"}],"predecessor-version":[{"id":3035,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts\/3029\/revisions\/3035"}],"wp:attachment":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/media?parent=3029"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/categories?post=3029"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/tags?post=3029"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}