Challenge Details
Name | C2 Pcap Analysis |
Author | Nightsedge |
Final Solves | 5 |
Final Points | 496 |
Description | We detected a C2 backdoor. Luckily because of our great cybersecurity infrastructure, we are able to decrypt the abnormal traffic. But what C2 framework is it? Seems not the common C2... |
Introduction
We are given a pcap file named "possible_c2_traffic_2025.pcap", which matches the description and name of this challenge, adhering to the theme of "C2". This is quite useful later on.
Opening the pcap file in wireshark to analyse, we find something similar to the screenshot below: A bunch of DNS + TCP + HTTP requests.
Looking through the DNS request we find that they are mostly used for microsoft services, in particular teams. It's also interesting to see that there exists a hkctf-night01.local
, yet the DNS stuff isn't quite useful yet.
However, taking a look at the singular TCP/HTTP stream, we find that contents are basically the same thing, and it appears that the client is sending quite a lot of stuff to the server with POST requests, as seen by "POST /".
Online sources suggest that the dumped requests should look something like the picture below, however this is not the case, as it feels to be encrypted by some sort of algorithm.
This is further backed by the challenge description mentiong that this "seems not the common C2", which is interesting.
Identifying Framework
If we take a look at the encrypted requests, we find a recurring pattern in these requests: after the HTTP headers, the first portion of the body reads "de ad be ef"!
While trying to look up how to identify C2 frameworks, we found that C2 often uses identifiable traffic patterns. This perfeclty matches with our previous observation of recurring "deadbeef" at the start of payload bodies!
Searching "deadbeef" c2 shows the following results which suggest that the C2 traffic captured in the pcap seems to be of the "Havoc C2 Framework"...
The first link tells us that:
- Encryption is in AES256 CTR mode
- The first packet show the AES(32 bytes) + IV(16 bytes) Key, 12 bytes after the Magic Byte Header, "deadbeef"
"Having obtained the keys, we then developed a methodology to help defensive operators acquire them from both packet capture and memory, detailed below. After setting everything up, we ran the demon on the target machine with Wireshark packet capture enabled. This allowed us to monitor all the HTTP and TCP traffic between the demon and the teamserver.Upon analyzing the first packet in the capture, we noticed that the first bytes said dead beef, which is a magic byte value, shown in the red box in the picture below."
Applying this to the first packet of the captured requests,
00000000 50 4f 53 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d POST / H TTP/1.1.
00000010 0a 43 61 63 68 65 2d 43 6f 6e 74 72 6f 6c 3a 20 .Cache-C ontrol:
00000020 6e 6f 2d 63 61 63 68 65 0d 0a 43 6f 6e 6e 65 63 no-cache ..Connec
00000030 74 69 6f 6e 3a 20 4b 65 65 70 2d 41 6c 69 76 65 tion: Ke ep-Alive
00000040 0d 0a 50 72 61 67 6d 61 3a 20 6e 6f 2d 63 61 63 ..Pragma : no-cac
00000050 68 65 0d 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 he..Cont ent-Type
00000060 3a 20 2a 2f 2a 0d 0a 55 73 65 72 2d 41 67 65 6e : */*..U ser-Agen
00000070 74 3a 20 4d 6f 7a 69 6c 6c 61 2f 35 2e 30 20 28 t: Mozil la/5.0 (
00000080 57 69 6e 64 6f 77 73 20 4e 54 20 36 2e 31 3b 20 Windows NT 6.1;
00000090 57 4f 57 36 34 29 20 41 70 70 6c 65 57 65 62 4b WOW64) A ppleWebK
000000A0 69 74 2f 35 33 37 2e 33 36 20 28 4b 48 54 4d 4c it/537.3 6 (KHTML
000000B0 2c 20 6c 69 6b 65 20 47 65 63 6b 6f 29 20 43 68 , like G ecko) Ch
000000C0 72 6f 6d 65 2f 39 36 2e 30 2e 34 36 36 34 2e 31 rome/96. 0.4664.1
000000D0 31 30 20 53 61 66 61 72 69 2f 35 33 37 2e 33 36 10 Safar i/537.36
000000E0 0d 0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 ..Conten t-Length
000000F0 3a 20 33 32 35 0d 0a 48 6f 73 74 3a 20 31 39 32 : 325..H ost: 192
00000100 2e 31 36 38 2e 31 31 33 2e 31 33 30 0d 0a 0d 0a .168.113 .130....
===
00000110 00 00 01 41 de ad be ef 4f 40 bb 84 00 00 00 63 ...A.... O@.....c
===
00000120 00 00 00 00 d6 b6 7c 00 44 2e be a0 fa de e2 fa ......|. D.......
00000130 a8 50 1c 22 34 42 ee 62 4e 00 12 1e 12 14 a6 9c .P."4B.b N.......
00000140 7c 32 2e 92 22 84 1e ca 72 04 f0 10 b8 a0 4c ba |2.."... r.....L.
00000150 84 22 4c a8 ab 65 6a cb fd f3 ef c6 fa 1a ff c6 ."L..ej. ........
00000160 c8 56 3b fb 5e 3b 9d 16 05 d9 c3 67 b6 2f 7f e9 .V;.^;.. ...g./..
00000170 b5 62 b7 6f b1 3c ab c4 f7 68 d7 a6 dc ba 34 cf .b.o.<.. .h....4.
00000180 18 30 7e cc 1c e3 b8 8b 6d 0a ce 66 f4 98 f1 dd .0~..... m..f....
00000190 2d cd 3f 28 1f 31 42 70 ec 15 f6 62 c3 89 46 9d -.?(.1Bp ...b..F.
000001A0 04 f3 86 39 38 75 2e 97 64 56 e2 f6 52 96 ed dd ...98u.. dV..R...
000001B0 e4 a0 3e 66 55 e1 2e 7d b5 06 a2 13 da f8 d6 75 ..>fU..} .......u
000001C0 2a 96 9c f6 ad 48 be 26 03 26 bf e1 cf 27 29 96 *....H.& .&...').
000001D0 34 f5 f4 49 80 78 b3 61 82 11 1a 8d 6d f5 80 bc 4..I.x.a ....m...
000001E0 46 41 c5 f6 71 6d ed 34 e8 2a b4 45 a8 ab 59 a7 FA..qm.4 .*.E..Y.
000001F0 d8 9c e0 0d bf e8 8f 76 a4 a0 7c 04 c4 b2 b0 af .......v ..|.....
00000200 c9 e4 9e c8 d9 c1 c1 01 89 f2 e4 30 6b 7a ab 20 ........ ...0kz.
00000210 5b f6 e2 d4 eb ee 4a 39 b1 47 fd 47 20 b1 72 4c [.....J9 .G.G .rL
00000220 86 73 08 cd 5b 5d 2c 42 13 e4 37 12 72 c6 cc 93 .s..[],B ..7.r...
00000230 7a 75 d3 ac 19 4d 39 b0 4e 88 3c c7 15 d1 4b ac zu...M9. N.<...K.
00000240 f8 1b 45 20 5d f1 98 cd 1e 55 68 68 3c 25 ba de ..E ]... .Uhh<%..
00000250 b0 d6 10 db f8 .....
Taking the AES Key (first 32 bytes), which begins 12 bytes after "deadbeef", we get d6b67c00442ebea0fadee2faa8501c223442ee624e00121e1214a69c7c322e92
.
Similarly, we treat the next 16 bytes as our IV Key: 22841eca7204f010b8a04cba84224ca8
.
Using the rest of the payload as input, we can plug the values into CyberChef and get the payload shown in the screenshot, which reads "HKCTF-NIGHT01"! This aligns with the "hkctf-night01.local" domain we found earlier, suggesting that we successfully decrypted the first packet.
(Night refers to Nightsedge the author?)
Exploitation
Decrypting the rest of the packets is surprisingly easy, since we already have the AES and IV Key, we just take the stuff, which is (12 bytes) after deadbeef and decrypt it with the same values.
We do this with the script below:
# file with hex dump from wireshark
with open('dump', 'r') as f:
hex_dump = f.read()
split = hex_dump.split("POST / H TTP/1.1.\n")
res = [x for x in split if "de ad be ef" in x]
for req in res:
lines = req.split("\n")[:-1]
hex_values = []
for line in lines:
if line.strip():
hex_values.extend(line[9:58].split())
hex = "".join(hex_values).split("deadbeef")[1]
ciphertext = binascii.unhexlify(hex[24:])
Then, simply automate the decrypting process we did in CyberChef, to decode it!
def decrypt_aes_ctr(key, nonce, ciphertext):
ctr = Counter.new(128, initial_value=int.from_bytes(nonce, byteorder='big'))
cipher = AES.new(key, AES.MODE_CTR, counter=ctr)
plaintext = cipher.decrypt(ciphertext)
return plaintext
key = binascii.unhexlify("d6b67c00442ebea0fadee2faa8501c223442ee624e00121e1214a69c7c322e92")
nonce = binascii.unhexlify("22841eca7204f010b8a04cba84224ca8")
for req in res:
# ...
plaintext = decrypt_aes_ctr(key, nonce, ciphertext)
print(plaintext.decode('ascii',errors='ignore'))
Redirecting the output to a file, we use CTRL + F
to look for the flag format of PUCTF25{...}
, and profit!