Using SCYTHE payload as Shellcode

Using SCYTHE payload as Shellcode

Guest blog post by one of our partners, Jean-Maes from NVISO.

During Unicon21, I (Jean-Maes) presented how I leverage the D/Invoke project from TheWover to load a SCYTHE campaign using the SCYTHE DLL that is automatically created for each campaign. SCYTHE provides 32-bit and 64-bit EXEs, DLLs, and Reflective Loader + DLL for Windows payloads. I provide an alternative: a way to leverage the great sRDI project from Nick Landers to transform any DLL into position independent shellcode, which can thereafter be used at the operator's discretion.

Attack

According to Red Canary’s 2021 threat intel report, process injection is the sixth most used technique by threat actors. In order to provide the most complete picture for our clients, and knowing what we know about the threat report, it would thus be very beneficial for us to demonstrate these TTPs. (Un)fortunately for us, EDR solutions detect process injection techniques pretty well under normal use cases, so we will have to use some “advanced” red team tradecraft to attempt to bypass the defenses and launch our sweet, SCYTHE campaign. 

One way to attempt and thwart EDR solutions is the usage of syscalls, and this is where the D/Invoke project really helps us out. Let’s take a look at how it works in practice, and walk you through how to create shellcode from your SCYTHE DLL and inject it using syscalls. As an additional TTP (and because it’s fun) we’ve also thrown parent-pid spoofing in there as well.

Create a SCYTHE Campaign

We create a demo campaign that will simply send our SCYTHE C2 server a screenshot and exit gracefully. After creating the automation logic we run our campaign.

 

Getting the ShellCode

For each campaign created, SCYTHE automatically generates 64-bit and 32-bit EXEs and DLLs.For our use case, we will select DLL and we set our entry-point function name to Unicon.

Getting the Shellcode can be done in three ways using the sRDI project:

  1. PowerShell
  2. Python
  3. C program included in the project

An interesting step-by-step article was already written at ired.team on using powershell to obtain shellcode from the DLL.

First off let’s open up a PowerShell prompt, importing our ConvertTo-ShellCode module from the sRDI project, point it to our DLL and specifying the exported function: 

Once this is done, convert your shellcode, now stored in the $UnicornsAreAwesome parameter and convert it to hexadecimal: 

Finally, write the output to a .txt file: 

Now that you have this txt file, you can copy it over into a hex editor such as HxD to create your final bin file, it should be noted that you can automate this process even further, but that will be left as an exercise to the reader :)

Now that we have the Shellcode binary blob, we can leverage it on our offensive tradecraft!

Adapting the loader

As we don't want to rely on precompiled DLLs in our code, we will opt to download D/Invokes source code and include it in our process instead.  A nice example payload loader can be found on the NVISO github repository. Essentially what will happen is we will leverage a series of NTDLL.dll exported functions, recreate their behaviour using the syscall stub generation of D/Invoke, and instruct our injector to use those functions.

The relevant functions that where leveraged in the demo loader are:

  • NtAllocateVirtualMemory
  • NtWriteVirtualMemory
  • NtProtectVirtualMemory
  • NtCreateThreadEx

It should be noted that these are not the only functions that are capable of injecting shellcode in an arbitrary process, there are many varieties out there.

The demo loader in the GitHub repo has  a hardcoded shellcode blob, for our use case, this blob is irrelevant so we removed it (codeline 31-51). 

We added a new input parameter to accept an arbitrary shellcode file instead, at line 288 we added a new string variable called shellcodeFile

And on line 296 we added
{"f|file=","path to the shellcode to inject",o => shellcodeFile = o }

Finally on line 307 we added
byte[] buf = File.ReadAllBytes(shellcodeFile);

By making these modifications we extended the available loaders functionality to load shellcode from an arbitrary file on system. It should be noted that there are more complex loading techniques that could be implemented, for example fetching the payload remotely over the internet or even decrypt an encrypted shellcode blob before injecting it into a process.

Running the loader

Now we have everything in place to run the loader:

Let’s check if the campaign indeed did what it was supposed to do…

Detection & Response

As advocates for Purple Teaming we have to cover some defense, right? How does someone detect process injection if it has bypassed the almighty EDR? What about parent child relationships? Well, thankfully our friends at Falcon Force have multiple Falcon Friday posts about detectioning these techniques:

Conclusion

Success! Congratulations, you have successfully learned how to create position independent shellcode from the SCYTHE DLL, and inject it into an arbitrary process using system calls!  Pat yourself on the back, grab a libation to celebrate, and sit back and enjoy your EDR-Free SCYTHE campaign!

About SCYTHE

SCYTHE provides an advanced attack emulation platform for the enterprise and cybersecurity consulting market. The SCYTHE platform enables Red, Blue, and Purple teams to build and emulate real-world adversarial campaigns in a matter of minutes. Customers are in turn enabled to validate the risk posture and exposure of their business and employees and the performance of enterprise security teams and existing security solutions. Based in Arlington, VA, the company is privately held and is funded by Gula Tech Adventures, Paladin Capital, Evolution Equity, and private industry investors.