Skip to content

3. Emulation

Shiva Shashank edited this page Sep 22, 2022 · 6 revisions

Assembly instructions from raw shellcode files can be emulated via the l option from the main menu. This feature allows the user to detect both Syscalls and WinAPI calls made by shellcode, along with the corresponding parameters used and simulated outcomes of the call. Additionally, SHAREM can automatically decode encoded shellcode sections, detect DLLs loaded, and display discovered artifacts. The SHAREM Emulator menu contains several options, which optionally be preset in the config file:

image9

  • z – Executes the emulation process with current selections. This should be selected only after all other settings have been set up.
  • s – SHAREM looks for syscalls made by the sample. Each Windows version uses a different set of syscall IDs, so this menu allows the user to select which ID set(s) to use. This feature is not yet fully operational, but will be in the next couple weeks. All are set and working in SHAREM, but this is just the option to select the desired OS and release. Currently by default it is the most recent OS and release build of Windows 10.
  • m – Maximum number of instructions emulated before stopping. The default is 500000, but some extremely large shellcodes may need a million or more. An example of this could be a PE file converted to shellcode by a tool.
  • v – Verbose mode – This creates timeless debugging. It will generate a file called emulationLog.txt located in sharem\sharem\sharem\sharem. This maintains a record of every instruction executed in the CPU state (including all registers before and after). This is highly effective at tracing the functionality of shellcode, and it can record hundreds of thousands of instructions executed.

timeless_debugging

  • c – Toggle complete code coverage. Code coverage maintains a record of ever instruction executed, and if it misses one, it will go back and revisit it. Before every change in program flow (e.g. jump conditional), the CPU state (registers, stack values, etc) are preserved, so that when it goes and revisits it, things are the same as they were previously. This helps to identify additional APIs or Syscalls. While it can add additional instructions to execute, this is generally recommended.
  • a – Select whether to emulate 32-bit or 64-bit instructions. Currently, only 32-bit is supported, although we suspect 64-bit will be available within the next month.
  • b – If this option is selected, SHAREM will automatically break out of infinite loops that would normally impede the emulation process.
  • n – Determines how many iterations of a loop will execute before SHAREM escapes the loop if option b is selected.
  • p – Changes verbosity of printing when emulation is run. Generally, default settings are recommended.
  • e – Entry points for certain shellcodes may not be the start of the sample file. This option allows the user to manually set the entry point to begin emulation from.
  • w – Changes printing style of artifacts.

Once initialized by the z option, SHAREM will perform the emulation according to the options selected. Information such as WinAPIs and Syscalls used by the shellcode will be displayed, as well as DLLs and artifacts discovered. This information is also saved internally and will be included in text report and JSONs generated, if the user “prints” results or obtains them through automation.

SHAREM will also automatically run ssdeep on the shellcode, to compare the original state and its state after it has been executed. Additionally, if the shellcode was encoded, SHAREM will automatically switch to the decoded version of the shellcode for any other actions performed in SHAREM if possible. The user can toggle between performing actions on obfuscated and deobfuscated shellcode via the U option at the main menu, although it is strongly recommended to focus on the deobfuscated shellcode, as the encoded form is rather meaningless. Even if the shellcode deobfuscated and immediately modifies the deobfuscated instruction after execution, it still is recovered.

Deobfuscation of Encoded Shellcodes through Emulation

The steps to follow to deobfuscate a shellcode is relatively simple. Assuming desired settings are set in the config file, the entire process could be automated with no user interaction. But, if desired to interact the UI, then some possible basic steps to follow are as follows:

Step 1: Enter the emulation menu by typing l in the main menu.

Step 2: In the emulation menu, make any tweaks to the desired settings. No changes are necessary, unless desired. If a shellcode is very large, a user might increase the maximum number of instructions to emulate (unlimited), or if they wish to understand it better, they might enable timeless debugging. Once choices have been made, simply type z (which is the SHAREM universal to “execute”). The emulation process will begin.

emulation

Step 3: Now, we have some options. We can go an generate reports or we can run the disassembler. Even though this shellcode was encoded, the disassembler will immediately display disassembly of its decoded form, while maintaining the original decoder stub. The end of the decoder stub is marked, as seen below.

decoded_emu

Shellcodes often use API tables, as they use checksum hashes to find desired APIs. Once found, the runtime addresses are saved to an API table, where they can be called again later. Often the API tables in the original form will just be 00’s that are overwritten. SHAREM in emulating it can identify these API pointers as being part of the API table and used for this purpose.

api_table

Here we can see DeleteFileA being used in the shellcode, and it is labelled in the disassembly.

deleteFile

Without emulation, there would be no possible way to know what the call eax is, aside from executing it in a debugger, as DeleteFileA does not appear anywhere in the shellcode as plain text – only a checksum hash.

Step 4: The next step would be simply to go to the print menu and print out everything that has been found.

The above is just one possible way of obtaining this information. Simply doing the z option from the main menu would be another option, although that would not display the disassembly – but it would print it to text file and JSON. The user could then simply type D from the main menu to see the above. Thus, even a very complex shellcode could be deobfuscated fully with minimal effort.