Skip to content

Process Injection

TheWover edited this page Sep 28, 2019 · 11 revisions

Process Injection Library

In an effort to provide tool developers with a modular platform for building tools, we are adding a process injection library into SharpSploit. This project arose out of frustration with many open-source C2 Frameworks that rely on hard-coded, noisy injection techniques. When that functionality is blocked by AV, the operator of the tool has no way to adapt short of rewriting their toolset. By providing a modular, object-oriented platform tool designers should be able to mix-and-match techniques; hopefully even expose such choices to the operator so that the user may choose how their tool works at runtime. Rather than merging the complete library at once, we have provided this design as a reference for people wishing to expand on the library. We will build it iteratively, adding new allocation and injection techniques over time. Techniques that we wish to add are listed below, but feel free to submit PRs beyond our suggestions.

From a tool designer's perspective they should be able to call call Injector.Inject(AllocationType alloc, InjectionType technique, PayloadType payload). Each of those Type classes are base classes. We implement subclasses for each of them that implement the appropriate logic. The Inject function uses the specified allocation technique to make the payload available to the target process, then calls the InjectionType subclass's ExecutePayload(Process proc, PayloadType payload) function to run the payload. Each InjectionType subclass implements functionality for different subclasses of PayloadType. If the injection technique doesn't support a particular payload type, it returns a PayloadTypeNotSupported exception. If it does, then it will run the payload, using whatever options were specified when the InjectionType object was instantiated.

In general, every class/technique should provide as many options as possible. If you are asking yourself, "Should I hardcode this, or provide it as an option to the user?" then you should probably just go with the latter.

AllocationType subclasses should ALWAYS expose an option that allows the user to choose the permissions of the memory containing the payload. Hint, there are already values in Execution.Win32.WinNT for each permission (read, write, execute, etc.)

Each InjectionType is essentially a technique relying on a specific set/sequence of API calls that allows code to be executed in arbitrary processes. They should implement at least three variants. Each variant is rated for Reliability and OpSec. One that is High Reliability, Low Opsec; one that is Medium on both; and one that is Low Reliability, High Opsec. Ideally, they should also provide modularity for each variant.

When implementing a new PayloadType subclass, be sure to also update/add appropriate InjectionType subclasses with functionality to inject those payloads! Don't add a ReflectiveDLL payload type without any code for injecting Reflective DLLs. ;-)

The three techniques that we wish to provide at minimum are:

  1. Remote Thread Creation
  2. APC Injection
  3. Thread Hijacking (Suspend, Inject, Resume)

Remote Thread Creation:

  1. Create a thread in the target process using NtCreateThreadEx and a start address of your payload.
  2. Create a suspended thread in the target process using NtCreateThreadEx with a start address of RtlExitUserThread. Queue APC on the thread. Resume the thread. The shellcode should execute. Less covert than normal APC injection because a remote thread is created, but less suspicious than normal remote thread creation because the created thread has a legitimate start address.
  3. Create a suspended thread in the target process using NtCreateThreadEx and a valid start address, such as RtlUserThreadStart. Hijack it using NtSetThreadContext to execute your payload in memory of the remote process.

APC Injection:

  1. Attempt to find alertable threads using AtomBombing. Inject into a random alertable thread in the target process if there are multiple. Default Option.
  2. Attempt to find alertable threads using context analysis. Inject into a random alertable thread.
  3. Queue APC on all threads in the target process. Highly reliable, but not OpSec friendly.

May replace option 2 with: Queue APC on a random thread without performing an detection for an alertable state. Not reliable, but very quiet.

Thread Hijacking:

Have options for what event to resume the hijacked thread on. Either use a timer, dynamically add some PIC to the payload to run it in a new thread using CreateThread, or dynamically add some PIC to the payload to use some sort of Windows event/mutex.

  1. Hijack a random thread in the target process using NtSetThreadContext. After the event is triggered, restore the original context and resume it. Moderately safe and reliable.
  2. Only hijack suspended threads in the target process. If there are multiple suspended threads, choose a random one. If there are no suspended threads, do nothing. After the event is triggered, restore the original context and resume it. OpSec safe, but not reliable.
  3. Suspend all threads. Pick a random one, and hijack it. After the event is triggered, restore the original context and resume it. This is not as OpSec safe, but is reliable for execution.

Clone this wiki locally