Forensics - Chips and Dip Redux - USCG 2024
A forensics and reverse engineering challenge developed by tsuto for Season IV of the U.S. Cyber Open.
Description
The threat actors from last season are back at it again with a new and improved implant that they used to steal the flag. See if you can figure out how to crack it….
Solution
Two files were provided with this challenge.
pid.657970.core
- A core dump of an applicationchips_and_dip.pcapng
- A PCAP containing information about the implant
Summary:
- Analyzing the PCAP allowed me to discover the binary,
system_update
, that was downloaded onto the victim’s computer. - Reverse engineering the binary in Ghidra revealed that
system_update
was sending and receiving encrypted data. - I was able to obtain the encryption key in GDB using the core dump.
- Analyzing the PCAP again, I recovered all the encrypted messages.
- Using the key from the core dump, I was able to decrypt all of the messages, revealing the flag.
Analyzing the PCAP
Upon opening the PCAP, the first thing I noticed was an HTTP request to /system_update
.
Inspecting this request clearly reveals that a binary file is being downloaded.
I was able to save the binary file by Navigating to File > Export Objects > HTTP
in Wireshark.
Running the file
command on the exported binary confirms that it is an executable. Additionally, running file
on the core dump shows that it was generated from system_update
, confirming that system_update
is the implant.
1
2
3
4
5
6
[[email protected]]╾─╼[chips-and-dip-redux]
▶ file system_update
system_update: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=yG_qz3gz2zrZ4zMo9_wL/cfRliiw7fIg0hQz7vvzu/oGwnV4HK9oKIi8UgGM5G/72tGbi3yBsO3P5NQzwek, with debug_info, not stripped
[[email protected]]╾─╼[chips-and-dip-redux]
▶ file pid.657970.core
pid.657970.core: ELF 64-bit LSB core file, x86-64, version 1 (SYSV), SVR4-style, from './system_update'
Reverse Engineering system_update
Reverse engineering the binary is pretty easy because debugging symbols aren’t stripped. Opening the binary in Ghidra and viewing the disassembly for main.main
reveals 5 primary actions of the binary.
- A random key is generated and saved to
main.salsa_key
. - The key is encrypted using an embedded public key in
main.EncryptWithPublicKey
. - The encrypted key is then sent to the remote server via an HTTP request.
- The function
main.GetC2Command
is used to retrieve encrypted commands from a C2 server which are then decrypted and executed. - The function
main.SendC2Output
encrypts command output and sends it back to the server.
Because a core dump was provided for system_update
, and system_update
still has symbols, it is easy to recover main.salsa_key
in GDB.
1
2
3
4
[[email protected]]╾─╼[chips-and-dip-redux]
▶ gdb ./system_update ./pid.657970.core
gef➤ print main.salsa_key
$1 = "E2FAC8A39573F1F416A8C6834BF49216"
Decrypting Traffic
To decrypt the messages it is first necessary to extract all the encrypted messages from the PCAP.
1
2
tshark -nr ./chips_and_dip.pcapng -Y "tcp.stream eq 1" -T fields -e http.file_data |\
xxd -r -p | sed 's/}/}\n/g > messages.txt'
Decrypting the messages is easy using the following Python script.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from Crypto.Cipher import Salsa20
from base64 import b64decode
import json
f = open('./messages.txt', 'r').readlines()
for line in f:
line = json.loads(line.strip())
try:
nonce = b64decode(line['Nonce'])
ciphertext = b64decode(line['Msg'])
c = Salsa20.new(key=b'E2FAC8A39573F1F416A8C6834BF49216', nonce=nonce)
plaintext = c.decrypt(ciphertext)
print(plaintext)
except:
pass
Flag: SIVUSCG{b4ck_f0r_an0ther_d1p}