Fake Boost Writeup - Cyber Apocalypse 2024
- 1 Introduction
- 2 Key Techniques
- 3 Artifacts Summary
- 4 Packet analysis
- 5 Analyzing frame 328 - GET /freediscordnitro response
- 6 Obtaining part 1 of the flag
- 7 Analyzing frame 15422 - POST /rj1893rj1joijdkajwda request
- 8 Creating PowerShell AES decryption code
- 9 Obtaining part 2 of the flag
- 10 Combining the flag parts
- 11 Conclusion
→ 1 Introduction
This writeup covers the Fake Boost Forensics challenge from the Hack The Box Cyber Apocalypse 2024 CTF, which was rated as having an ‘easy’ difficulty. The challenge involved the forensic analysis of HTTP traffic containing obfuscated PowerShell and AES encrypted data.
The description of the challenge is shown below.
→ 2 Key Techniques
The key techniques employed in this writeup are:
- Extracting HTTP objects from a packet capture
- Deobfuscating PowerShell
- Decrypting AES encrypted data
→ 3 Artifacts Summary
The downloaded artifact had the following hash:
$ shasum -a256 forensics_fake_boost.zip
19953ff5d4e82ce9b4c6c56117626458dd0b23fd5a5e41780d47b67170c5f2e7 forensics_fake_boost.zip
The zip file contained a single packet capture file:
$ unzip forensics_fake_boost.zip
Archive: forensics_fake_boost.zip
inflating: capture.pcapng
$ shasum -a256 capture.pcapng
3895763f539214af2dfe44f522c21b0ca80d57113aa8d19d19344e6030f210a8 capture.pcapng
→ 4 Packet analysis
capture.pcap
was opened in Wireshark. The
Statistics->Protocol Hierarchy
menu highlighted the
presence of HTTP traffic:
→ 4.1 Exporting the HTTP objects
The HTTP objects corresponding to frames 328 and 15422 were exported:
→ 5 Analyzing frame 328 - GET /freediscordnitro response
The GET /freediscordnitro
response was identified as
ASCII text with very long lines:
$ file freediscordnitro
freediscordnitro: ASCII text, with very long lines (8111), with CRLF line terminators
It appeared to be obfuscated PowerShell:
$ head -c 100 freediscordnitro && echo ""
$jozeq3n = "9ByXkACd1BHd19ULlRXaydFI7BCdjVmai9ULoNWYFJ3bGBCfgMXeltGJK0gNxACa0dmblxUZk92YtASNgMXZk92Q
The last line creates an alias pWn
to
Invoke-Expression
and uses it to invoke the expression
stored in the $LOaDcODEoPX3ZoUgP2T6cvl3KEK
variable:
$ tail -2 freediscordnitro && echo ""
$LOaDcODEoPX3ZoUgP2T6cvl3KEK = [sYSTeM.TeXt.ENcODING]::UTf8.geTSTRiNG([SYSTEm.cOnVeRT]::FRoMBaSe64sTRing("$s0yAY2gmHVNFd7QZ")) ;
$U9COA51JG8eTcHhs0YFxrQ3j = "Inv"+"OKe"+"-EX"+"pRe"+"SSI"+"On" ; New-alIaS -Name pWn -VaLuE $U9COA51JG8eTcHhs0YFxrQ3j -FoRcE ; pWn $lOADcODEoPX3ZoUgP2T6cvl3KEK ;
The PowerShell script was defanged by using sed
to
delete the last line and outputting the result to
freediscordnitro-defanged.psh
:
$ sed -Ee '$d' freediscordnitro > freediscordnitro-defanged.psh
A statement was appended to echo the contents of the
$LOaDcODEoPX3ZoUgP2T6cvl3KEK
variable:
$ echo 'echo $LOaDcODEoPX3ZoUgP2T6cvl3KEK' >> freediscordnitro-defanged.psh
The defanged script was executed and the result output to
freediscordnitro-decoded.psh
, then converted from DOS to
Unix line endings:
$ pwsh freediscordnitro-defanged.psh > freediscordnitro-decoded.psh
$ dos2unix freediscordnitro-decoded.psh
dos2unix: converting file freediscordnitro-decoded.psh to Unix format...
freediscordnitro-decoded.psh
contained an AES encryption
key:
As well as the corresponding encryption functions:
function Create-AesManagedObject($key, $IV, $mode) {
$aesManaged = New-Object "System.Security.Cryptography.AesManaged"
if ($mode="CBC") { $aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC }
elseif ($mode="CFB") {$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CFB}
elseif ($mode="CTS") {$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CTS}
elseif ($mode="ECB") {$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::ECB}
elseif ($mode="OFB"){$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::OFB}
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
$aesManaged.BlockSize = 128
$aesManaged.KeySize = 256
if ($IV) {
if ($IV.getType().Name -eq "String") {
$aesManaged.IV = [System.Convert]::FromBase64String($IV)
}
else {
$aesManaged.IV = $IV
}
}
if ($key) {
if ($key.getType().Name -eq "String") {
$aesManaged.Key = [System.Convert]::FromBase64String($key)
}
else {
$aesManaged.Key = $key
}
}
$aesManaged
}
function Encrypt-String($key, $plaintext) {
$bytes = [System.Text.Encoding]::UTF8.GetBytes($plaintext)
$aesManaged = Create-AesManagedObject $key
$encryptor = $aesManaged.CreateEncryptor()
$encryptedData = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length);
[byte[]] $fullData = $aesManaged.IV + $encryptedData
[System.Convert]::ToBase64String($fullData)
}
→ 6 Obtaining part 1 of the flag
The decoded PowerShell was also found to contain part1 of the flag, base64 encoded:
$ grep part1 freediscordnitro-decoded.psh
$part1 = "SFRCe2ZyMzNfTjE3cjBHM25fM3hwMDUzZCFf"
$ echo -n 'SFRCe2ZyMzNfTjE3cjBHM25fM3hwMDUzZCFf' |base64 -d
HTB{fr33_N17r0G3n_3xp053d!_
→ 7 Analyzing frame 15422 - POST /rj1893rj1joijdkajwda request
rj1893rj1joijdkajwda
was found to contain base64 encoded
data. However, the decoded data was of an as-yet unidentified binary
type. It was conjectured that it was AES encrypted by the aforementioned
encryption functions.
$ cat rj1893rj1joijdkajwda|base64 -d |file -
/dev/stdin: data
$ cat rj1893rj1joijdkajwda|base64 -d |xxd|head
00000000: 6c41 beac 6711 c982 9eaa 5cd7 6f44 1555 lA..g.....\.oD.U
00000010: 1bc5 a791 3dbe 6952 486d e9bc 34c0 1a86 ....=.iRHm..4...
00000020: dad3 9531 bdea 70bf efb4 b967 b532 7e0b ...1..p....g.2~.
00000030: 8882 2766 2342 fc44 b5b5 2ed2 9b39 9b73 ..'f#B.D.....9.s
00000040: df55 71df 61e7 52a0 0394 6cd6 df13 e791 .Uq.a.R...l.....
00000050: 2be6 2738 165a 01cd 0eed a629 f0f7 d902 +.'8.Z.....)....
00000060: dfcd 1645 a59c ab50 9cf2 243a 9590 4fff ...E...P..$:..O.
00000070: 2a89 b8bb 1f2d 3a52 637c 8879 2c2a f19f *....-:Rc|.y,*..
00000080: 6dba cbf9 b96b ddf4 4f55 d078 7607 0939 m....k..OU.xv..9
00000090: 2c33 189f 2c19 c3ae 21b0 7f32 b84f eefe ,3..,...!..2.O..
→ 8 Creating PowerShell AES decryption code
PowerShell AES decryption code was found online at https://gist.github.com/ctigeek/2a56648b923d198a6e60.
This was used to create the following decrypt.psh
script:
function Create-AesManagedObject($key, $IV, $mode) {
$aesManaged = New-Object "System.Security.Cryptography.AesManaged"
if ($mode="CBC") { $aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC }
elseif ($mode="CFB") {$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CFB}
elseif ($mode="CTS") {$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CTS}
elseif ($mode="ECB") {$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::ECB}
elseif ($mode="OFB"){$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::OFB}
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
$aesManaged.BlockSize = 128
$aesManaged.KeySize = 256
if ($IV) {
if ($IV.getType().Name -eq "String") {
$aesManaged.IV = [System.Convert]::FromBase64String($IV)
}
else {
$aesManaged.IV = $IV
}
}
if ($key) {
if ($key.getType().Name -eq "String") {
$aesManaged.Key = [System.Convert]::FromBase64String($key)
}
else {
$aesManaged.Key = $key
}
}
$aesManaged
}
function Decrypt-String($key, $encryptedStringWithIV) {
$bytes = [System.Convert]::FromBase64String($encryptedStringWithIV)
$IV = $bytes[0..15]
$aesManaged = Create-AesManagedObject $key $IV
$decryptor = $aesManaged.CreateDecryptor();
$unencryptedData = $decryptor.TransformFinalBlock($bytes, 16, $bytes.Length - 16);
$aesManaged.Dispose()
[System.Text.Encoding]::UTF8.GetString($unencryptedData).Trim([char]0)
}
$AES_KEY = "Y1dwaHJOVGs5d2dXWjkzdDE5amF5cW5sYUR1SWVGS2k="
$backToPlainText = Decrypt-String $AES_KEY "bEG+rGcRyYKeqlzXb0QVVRvFp5E9vmlSSG3pvDTAGoba05Uxvepwv++0uWe1Mn4LiIInZiNC/ES1tS7Smzmbc99Vcd9h51KgA5Rs1t8T55Er5ic4FloBzQ7tpinw99kC380WRaWcq1Cc8iQ6lZBP/yqJuLsfLTpSY3yIeSwq8Z9tusv5uWvd9E9V0Hh2Bwk5LDMYnywZw64hsH8yuE/u/lMvP4gb+OsHHBPcWXqdb4DliwhWwblDhJB4022UC2eEMI0fcHe1xBzBSNyY8xqpoyaAaRHiTxTZaLkrfhDUgm+c0zOEN8byhOifZhCJqS7tfoTHUL4Vh+1AeBTTUTprtdbmq3YUhX6ADTrEBi5gXQbSI5r1wz3r37A71Z4pHHnAoJTO0urqIChpBihFWfYsdoMmO77vZmdNPDo1Ug2jynZzQ/NkrcoNArBNIfboiBnbmCvFc1xwHFGL4JPdje8s3cM2KP2EDL3799VqJw3lWoFX0oBgkFi+DRKfom20XdECpIzW9idJ0eurxLxeGS4JI3n3jl4fIVDzwvdYr+h6uiBUReApqRe1BasR8enV4aNo+IvsdnhzRih+rpqdtCTWTjlzUXE0YSTknxiRiBfYttRulO6zx4SvJNpZ1qOkS1UW20/2xUO3yy76Wh9JPDCV7OMvIhEHDFh/F/jvR2yt9RTFId+zRt12Bfyjbi8ret7QN07dlpIcppKKI8yNzqB4FA=="
echo $backToPlainText
→ 9 Obtaining part 2 of the flag
The decryption script was executed:
$ pwsh decrypt.psh
[
{
"ID": "1212103240066535494",
"Email": "YjNXNHIzXzBmX1QwMF9nMDBkXzJfYjNfN3J1M18wZmYzcjV9",
"GlobalName": "phreaks_admin",
"Token": "MoIxtjEwMz20M5ArNjUzNTQ5NA.Gw3-GW.bGyEkOVlZCsfQ8-6FQnxc9sMa15h7UP3cCOFNk"
},
{
"ID": "1212103240066535494",
"Email": "YjNXNHIzXzBmX1QwMF9nMDBkXzJfYjNfN3J1M18wZmYzcjV9",
"GlobalName": "phreaks_admin",
"Token": "MoIxtjEwMz20M5ArNjUzNTQ5NA.Gw3-GW.bGyEkOVlZCsfQ8-6FQnxc9sMa15h7UP3cCOFNk"
}
]
The base64 encoded email fields were found to contain part 2 of the flag:
$ echo -n 'YjNXNHIzXzBmX1QwMF9nMDBkXzJfYjNfN3J1M18wZmYzcjV9' | base64 -d
b3W4r3_0f_T00_g00d_2_b3_7ru3_0ff3r5}
→ 10 Combining the flag parts
The combined flag parts resulted in:
HTB{fr33_N17r0G3n_3xp053d!_b3W4r3_0f_T00_g00d_2_b3_7ru3_0ff3r5}
→ 11 Conclusion
The flag was submitted and the challenge was marked as pwned