A proof-of-concept User-Defined Reflective Loader (UDRL) which aims to recreate, integrate, and enhance Cobalt Strike's evasion features!
Contributor | Notable Contributions | |
---|---|---|
Bobby Cooke | @0xBoku | Project original author and maintainer |
Santiago Pecin | @s4ntiago_p | Reflective Loader major enhancements |
Chris Spehn | @ConsciousHacker | Aggressor scripting |
Joshua Magri | @passthehashbrwn | IAT hooking |
Dylan Tran | @d_tranman | Reflective Call Stack Spoofing |
James Yeung | @5cript1diot | Indirect System Calls |
The built-in Cobalt Strike reflective loader is robust, handling all Malleable PE evasion features Cobalt Strike has to offer. The major disadvantage to using a custom UDRL is Malleable PE evasion features may or may not be supported out-of-the-box.
The objective of the public BokuLoader project is to assist red teams in creating their own in-house Cobalt Strike UDRL. The project aims to support all worthwhile CS Malleable PE evasion features. Some evasion features leverage CS integration, others have been recreated completely, and some are unsupported.
Before using this project, in any form, you should properly test the evasion features are working as intended. Between the C code and the Aggressor script, compilation with different versions of operating systems, compilers, and Java may return different results.
NtProtectVirtualMemory
obfuscate "true"
with custom UDRL Aggressor script implementation.0x1000
bytes will be nulls.XGetProcAddress
for resolving symbolsKernel32.GetProcAddress
xLoadLibrary
for resolving DLL's base address & DLL LoadingTEB->PEB->PEB_LDR_DATA->InMemoryOrderModuleList
Kernel32.LoadLibraryA
Command | Option(s) | Supported |
---|---|---|
allocator | HeapAlloc, MapViewOfFile, VirtualAlloc | All supported via BokuLoader implementation |
module_x64 | string (DLL Name) | Supported via BokuLoader implementation. Same DLL stomping requirements as CS implementation apply |
obfuscate | true/false | HTTP/S beacons supported via BokuLoader implementation. SMB/TCP is currently not supported for obfuscate true. Details in issue. Accepting help if you can fix :) |
entry_point | RVA as decimal number | Supported via BokuLoader implementation |
cleanup | true | Supported via CS integration |
userwx | true/false | Supported via BokuLoader implementation |
sleep_mask | (true/false) or (Sleepmask Kit+true) | Supported. When using default "sleepmask true" (without sleepmask kit) set "userwx true". When using sleepmask kit which supports RX beacon.text memory (src47/Ekko ) set "sleepmask true" && "userwx false". |
magic_mz_x64 | 4 char string | Supported via CS integration |
magic_pe | 2 char string | Supported via CS integration |
transform-x64 prepend | escaped hex string |
BokuLoader.cna Aggressor script modification |
transform-x64 strrep | string string |
BokuLoader.cna Aggressor script modification |
stomppe | true/false | Unsupported. BokuLoader does not copy beacon DLL headers over. First 0x1000 bytes of virtual beacon DLL are 0x00
|
checksum | number | Experimental. BokuLoader.cna Aggressor script modification |
compile_time | date-time string | Experimental. BokuLoader.cna Aggressor script modification |
image_size_x64 | decimal value | Unsupported |
name | string | Experimental. BokuLoader.cna Aggressor script modification |
rich_header | escaped hex string | Experimental. BokuLoader.cna Aggressor script modification |
stringw | string | Unsupported |
string | string | Unsupported |
make
BokuLoader.cna
Aggressor scriptUse the Script Console
to ensure BokuLoader was implemented in the beacon build
Does not support x86 option. The x86 bin is the original Reflective Loader object file.
RAW
beacons works out of the box. When using the Artifact Kit for the beacon loader, the stagesize
variable must be larger than the default.Original Cobalt Strike String | BokuLoader Cobalt Strike String |
---|---|
ReflectiveLoader | BokuLoader |
Microsoft Base Cryptographic Provider v1.0 | 12367321236742382543232341241261363163151d |
(admin) | (tomin) |
beacon | bacons |
Kernel32.LoadLibraryExA
is called to map the DLL from diskKernel32.LoadLibraryExA
is DONT_RESOLVE_DLL_REFERENCES (0x00000001)
RX
or RWX
memory will exist in the heap if sleepmask kit is not used.Kernel32.CreateFileMappingA
& Kernel32.MapViewOfFile
is called to allocate memory for the virtual beacon DLL.NtAllocateVirtualMemory
, NtProtectVirtualMemory
ntdll.dll
will not detect these systemcalls.mov eax, r11d; mov r11, r10; mov r10, rcx; jmp r11
assembly instructions within its executable memory.0x1000
bytes of the virtual beacon DLL are zeros.LOLSpoof is a an interactive shell program that automatically spoof the command line arguments of the spawned process. Just call your incriminate-looking command line LOLBin (e.g. powershell -w hidden -enc ZwBlAHQALQBwAHIAbwBjAGUA....
) and LOLSpoof will ensure that the process creation telemetry appears legitimate and clear.
Process command line is a very monitored telemetry, being thoroughly inspected by AV/EDRs, SOC analysts or threat hunters.
lolbin.exe " " * sizeof(real arguments)
Although this simple technique helps to bypass command line detection, it may introduce other suspicious telemetry: 1. Creation of suspended process 2. The new process has trailing spaces (but it's really easy to make it a repeated character or even random data instead) 3. Write to the spawned process with WriteProcessMemory
Built with Nim 1.6.12 (compiling with Nim 2.X yields errors!)
nimble install winim
Programs that clear or change the previous printed console messages (such as timeout.exe 10
) breaks the program. when such commands are employed, you'll need to restart the console. Don't know how to fix that, open to suggestions.
Espionage is a network packet sniffer that intercepts large amounts of data being passed through an interface. The tool allows users to to run normal and verbose traffic analysis that shows a live feed of traffic, revealing packet direction, protocols, flags, etc. Espionage can also spoof ARP so, all data sent by the target gets redirected through the attacker (MiTM). Espionage supports IPv4, TCP/UDP, ICMP, and HTTP. Espionag e was written in Python 3.8 but it also supports version 3.6. This is the first version of the tool so please contact the developer if you want to help contribute and add more to Espionage. Note: This is not a Scapy wrapper, scapylib only assists with HTTP requests and ARP.
1: git clone https://www.github.com/josh0xA/Espionage.git
2: cd Espionage
3: sudo python3 -m pip install -r requirments.txt
4: sudo python3 espionage.py --help
sudo python3 espionage.py --normal --iface wlan0 -f capture_output.pcap
wlan0
with whatever your network interface is.sudo python3 espionage.py --verbose --iface wlan0 -f capture_output.pcap
sudo python3 espionage.py --normal --iface wlan0
sudo python3 espionage.py --verbose --httpraw --iface wlan0
sudo python3 espionage.py --target <target-ip-address> --iface wlan0
sudo python3 espionage.py --iface wlan0 --onlyhttp
sudo python3 espionage.py --iface wlan0 --onlyhttpsecure
sudo python3 espionage.py --iface wlan0 --urlonly
usage: espionage.py [-h] [--version] [-n] [-v] [-url] [-o] [-ohs] [-hr] [-f FILENAME] -i IFACE
[-t TARGET]
optional arguments:
-h, --help show this help message and exit
--version returns the packet sniffers version.
-n, --normal executes a cleaner interception, less sophisticated.
-v, --verbose (recommended) executes a more in-depth packet interception/sniff.
-url, --urlonly only sniffs visited urls using http/https.
-o, --onlyhttp sniffs only tcp/http data, returns urls visited.
-ohs, --onlyhttpsecure
sniffs only https data, (port 443).
-hr, --httpraw displays raw packet data (byte order) recieved or sent on port 80.
(Recommended) arguments for data output (.pcap):
-f FILENAME, --filename FILENAME
name of file to store the output (make extension '.pcap').
(Required) arguments required for execution:
-i IFACE, --iface IFACE
specify network interface (ie. wlan0, eth0, wlan1, etc.)
(ARP Spoofing) required arguments in-order to use the ARP Spoofing utility:
-t TARGET, --target TARGET
A simple medium writeup can be found here:
Click Here For The Official Medium Article
The developer of this program, Josh Schiavone, written the following code for educational and ethical purposes only. The data sniffed/intercepted is not to be used for malicous intent. Josh Schiavone is not responsible or liable for misuse of this penetration testing tool. May God bless you all.
MIT License
Copyright (c) 2024 Josh Schiavone
NetProbe is a tool you can use to scan for devices on your network. The program sends ARP requests to any IP address on your network and lists the IP addresses, MAC addresses, manufacturers, and device models of the responding devices.
You can download the program from the GitHub page.
$ git clone https://github.com/HalilDeniz/NetProbe.git
To install the required libraries, run the following command:
$ pip install -r requirements.txt
To run the program, use the following command:
$ python3 netprobe.py [-h] -t [...] -i [...] [-l] [-o] [-m] [-r] [-s]
-h
,--help
: show this help message and exit-t
,--target
: Target IP address or subnet (default: 192.168.1.0/24)-i
,--interface
: Interface to use (default: None)-l
,--live
: Enable live tracking of devices-o
,--output
: Output file to save the results-m
,--manufacturer
: Filter by manufacturer (e.g., 'Apple')-r
,--ip-range
: Filter by IP range (e.g., '192.168.1.0/24')-s
,--scan-rate
: Scan rate in seconds (default: 5)$ python3 netprobe.py -t 192.168.1.0/24 -i eth0 -o results.txt -l
$ python3 netprobe.py --help
usage: netprobe.py [-h] -t [...] -i [...] [-l] [-o] [-m] [-r] [-s]
NetProbe: Network Scanner Tool
options:
-h, --help show this help message and exit
-t [ ...], --target [ ...]
Target IP address or subnet (default: 192.168.1.0/24)
-i [ ...], --interface [ ...]
Interface to use (default: None)
-l, --live Enable live tracking of devices
-o , --output Output file to save the results
-m , --manufacturer Filter by manufacturer (e.g., 'Apple')
-r , --ip-range Filter by IP range (e.g., '192.168.1.0/24')
-s , --scan-rate Scan rate in seconds (default: 5)
$ python3 netprobe.py
You can enable live tracking of devices on your network by using the -l
or --live
flag. This will continuously update the device list every 5 seconds.
$ python3 netprobe.py -t 192.168.1.0/24 -i eth0 -l
You can save the scan results to a file by using the -o
or --output
flag followed by the desired output file name.
$ python3 netprobe.py -t 192.168.1.0/24 -i eth0 -l -o results.txt
ββββββββββββββββ³ββββββββββββββββββββ³ββββββββββββββ³βββββββββββββββββββββββββββββββ
β IP Address β MAC Address β Packet Size β Manufacturer β
β‘ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ©
β 192.168.1.1 β **:6e:**:97:**:28 β 102 β ASUSTek COMPUTER INC. β
β 192.168.1.3 β 00:**:22:**:12:** β 102 β InPro Comm β
β 192.168.1.2 β **:32:**:bf:**:00 β 102 β Xiaomi Communications Co Ltd β
β 192.168.1.98 β d4:**:64:**:5c:** β 102 β ASUSTek COMPUTER INC. β
β 192.168.1.25 β **:49:**:00:**:38 β 102 β Unknown β
ββββββββββββββββ΄ββββββββββββββββββββ΄ββββββββββββββ΄βββββββββββββββββββββββββββββββ
If you have any questions, suggestions, or feedback about the program, please feel free to reach out to me through any of the following platforms:
This program is released under the MIT LICENSE. See LICENSE for more information.
PoC Implementation of a fully dynamic call stack spoofer
SilentMoonwalk is a PoC implementation of a fully dynamic call stack spoofer, implementing a technique to remove the original caller from the call stack, using ROP to desynchronize unwinding from control flow.
This PoC is the result of a joint research done on the topic of stack spoofing. The authors of the research are:
I want to stress that this work would have been impossible without the work of Waldo-IRC and Trickster0, which both contributed to the early stages of the PoC, and to the research behind the PoC.
This repository demonstrates a PoC implementation to spoof the call stack when calling arbitrary Windows APIs.
This attempt was inspired by this Twitter thread, and this Twitter thread, where sensei namazso showed and suggested to extend the stack unwinding approach with a ROP chain to both desynchronize the unwinding from real control flow and restore the original stack afterwards.
This PoC attempts to do something similar to the above, and uses a desync stack to completely hide the original call stack, also removing the EXE image base from it. Upon return, a ROP gadget is invoked to restore the original stack. In the code, this process is repeated 10 times in a loop, using different frames at each iteration, to prove stability.
The tool currently supports 2 modes, where one is actually a wrong patch to a non-working pop RBP frame identified, which operates by shifting the current RSP and adding two fake frames to the call stack. As it operates using synthetic frames, I refer to this mode as "SYNTHETIC".
When selecting the frame that unwinds by popping the RBP register from the stack, the tool might select an unsuitable frame, ending up in an abruptly cut call stack, as observable below.
A silly solution to the problem would be to create two fake frames and link them back to the cut call stack. This would create a sort of apparently legit call stack, even without a suitable frame which unwinds calling POP RBP, but:
The result of the _synthetic spoof can be observed in the image below:
Figure 1: Windows 10 - Apparently Legit, non unwoundable call stack whereby the EXE module was completely removed (calling no parameters function getchar)
Note: This operation mode is disabled by default. To enable this mode, change the CALLSTACK_TYPE to 1
This mode is the right solution to the above problem, whereby the non-suitable frame is simply replaced by another, suitable one.
Figure 2: Windows 10 - Legit, unwoundable call stack whereby the EXE module was completely removed (calling 4 parameters function MessageBoxA)
In the repository, you can find also a little util to inspect runtime functions, which might be useful to analyse runtime function entries.
UnwindInspector.exe -h
Unwind Inspector v0.100000
Mandatory args:
-m <module>: Target DLL
-f <function>: Target Function
-a <function-address>: Target Function Address
Sample Output:
UnwindInspector.exe -m kernelbase -a 0x7FFAAE12182C
[*] Using function address 0x7ffaae12182c
Runtime Function (0x000000000000182C, 0x00000000000019ED)
Unwind Info Address: 0x000000000026AA88
Version: 0
Ver + Flags: 00000000
SizeOfProlog: 0x1f
CountOfCodes: 0xc
FrameRegister: 0x0
FrameOffset: 0x0
UnwindCodes:
[00h] Frame: 0x741f - 0x04 - UWOP_SAVE_NONVOL (RDI, 0x001f)
[01h] Frame: 0x0015 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0015)
[02h] Frame: 0x641f - 0x04 - UWOP_SAVE_NONVOL (RSI, 0x001f)
[03h] Frame: 0x0014 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0014)
[04h] Frame: 0x341f - 0x04 - UWOP_SAVE_NONVOL (RBX, 0x001f)
[05h] Frame: 0x0012 - 0x00 - UWOP_PUSH_NONVOL (RAX, 0x0012)
[06h] Frame: 0xb21f - 0x02 - UWOP_ALLOC_SMALL (R11, 0x001f)
[07h] Frame: 0xf018 - 0x00 - UWOP_PUSH_NONVOL (R15, 0x0018)
[0 8h] Frame: 0xe016 - 0x00 - UWOP_PUSH_NONVOL (R14, 0x0016)
[09h] Frame: 0xd014 - 0x00 - UWOP_PUSH_NONVOL (R13, 0x0014)
[0ah] Frame: 0xc012 - 0x00 - UWOP_PUSH_NONVOL (R12, 0x0012)
[0bh] Frame: 0x5010 - 0x00 - UWOP_PUSH_NONVOL (RBP, 0x0010)
In order to build the POC and observe a similar behaviour to the one in the picture, ensure to:
/GS-
)/Od
)/GL
)/Os
, /Ot
)/Oi
)It's worth mentioning previous work done on this topic, which built the foundation of this work.