Forensics
For this challenge we have to connect to a Windows machine hosted on https://training.leveleffect.com
. Looks like we need to get the credentials for the user crimson
. Let’s start by booting up the machine and connecting to the VM.
Once we connect, we see we’re actually the Administrator.
This makes things really easy for us, and should let us dump credentials from memory with no issue.
First things first, let’s download mimikatz from GitHub.
Lol yeah it does get flagged but we can ignore that. Once its installed, lets run it and dump the creds using the following commands:
token::elevate
lsadump::sam
Note: I tried this with PowerDump but ran into a couple issues so Mimikatz was just easier. Running this gets us the hash for the user Crimson:
We could load this up in hashcat but I’ve been using ntlm.pw lately which has been reliable, is faster than, and doesn’t require a captcha like crackstation.net.
Also, it’s nice to use as a pentester since crack.sh has been down for what feels like forever.
Using ntlm.pw gets us the plaintext password, and solves this challenge.
OSINT
For this challenge, we are given a conversation in Russian, and asked to find info on a secret plan.
Because I am not fluent in Russian, we’ll drop this into Google translate. Doing so gives us the following translation:
Shadow
14:04 (22 minutes ago)
To jakearmitage1337
Dude! Why did you post such information for everyone to see!
Clean it up quickly before the whole operation is covered!
-------------------------------------------------- --------
jakearmitage1337
14:09 (17 minutes ago)
To Shadow
Sorry, boss! I missed it. I already removed it, so everything is fine.
We’ve got a very specific user name we can start googling for, but given the challenge title, we should go straight to GitHub instead.
Looking at the “SuperSecretProject” nothing really stands out, but given the conversation we read, there’s probably something in the commit history. checking out the oldest commit reveals the flag.
Networking
In this challenge we told there is a internal webserver hosted at 0.cloud.chals.io
on port 8888
. We are given a private SSH key as well as a username, passphrase, and SSH port. Upon logging in, we see the following error:
Looks like we might be in a restricted shell, but regardless we don’t actually need access to a terminal on the host to get the flag. The username should have been a clue, but we can actually just create an SSH tunnel to forward our local port to 8888 to the internal hosts 8888.
We can do that with the following modified SSH command using the -L
flag:
ssh tunneler@0.cloud.chals.io -p 27141 -i ~/Downloads/p3.private.key -L 8888:localhost:8888
After authenticating, we have a short epriod of time to then grab the flag. We can do so by using curl and pointing it to localhost which is now being forwarded to the internal webserver.
curl http://localhost:8888
Crypto
This challenge gives us a pcap file with some interesting traffic on it.
Looks like the flag was actually downloaded in the captured traffic so we can just export it.
Once again the challenge name was a hint, and as I suspected, the flag is password protected.
We can use zip2john
to convert the zip file into a hash that we can then crack with Hashcat.
Typically I’d transfer the hash over to my computer with a GPU for cracking, but given the title of this challenge, I know the password will be in rockyou.txt. Using the following command, we can crack the password for the zip file.
hashcat -m 17220 flag.zip.hash /opt/wordlistst/rockyou.txt
Using the recovered password we try unzipping the file and…..
We got another password protected file, but we can just do the exact same thing. This time we use pdf2john
to extract the hash.
Doing the same thing, we can just use the following command to get the password for the pdf
hashcat -m 10500 flag.pdf.hash /opt/rockyou.txt
Finally, we can open the PDF and grab the flag.
Scripting
Here, we are given a seemingly random string with the flag embedded in it. Each character of the flag contains exactly 6 digits preceding it, so we’ll need to write something for RegEx.
>=i^SEc54m$:JHHATDl8H#Ig7$;YSR/T5Q@/T5Q@/T5Q@%15XKEc`FLDflKr%16<?ATDj'+>I123456l.2$<LddEb-A2D]j+CEa`iuATDi7FDi:<Dg#\$$<_:i+DYk5G9D!@AKZ#9Ch7Z1@;]TuF)N13D577829e]hUo-q%tr8LY)U5p0c^Cht5(Df'?*FDYT,F=2,PGA(E,+A!qt+EV:2DJNs(B-;,)%166VFWbmHF_kT+-ZgJDATT&:BPDN1Ao_g,+C855963vT/5+E)@8ATAo+Fa4E'%16<9Eb-giBQ%p6F'T4^8K_bjF*&OK@;]sk+EV12C`n"AFW855963eb@9G9BI)D'3G%ASc'uB+52<Dfg)0+DkP&AK345567lZ8:FWbgEA7]e&FCB&t%13OO>=3(BEclG/%15jAG%G\:B5_[*@3B2sG%DeADf345556em1FE"*.LAThX*+D5V1DIFZ(ATT&?Dfm15Dg-(.$;P/UATAo+Df0H$+EDUB+CT;/F`(878523f_4@;]TuA7]gnEc`FLDflKr:1\T[EZf"5DJil*D..3k+F.mJ+CfG;%15jAG%G\:B5_[*@3BW"989794fGp$a<De*=&AISuAAThX*+D5V1DIF246832eZ0ASc0*@3BB#AKYE!A0>Q.Ec`FLDflKr%16<?ATDj'+>R43$<LddG%De3DJs`:+D"tkBHV58BOu3,AoD]4F)N1;098765cDf01s$<_:iEZf%,@<-H;F!+q'ASrW!@q]RoB.P07F`\aODfmFJAKZ)5D]j+7Gp738102t%3I+ELt:+DGp?-rb+-F('>:Blkd5$;#,VBk1d++EqB>@W-@%+DY172654{k5G9D*C@<<l<+C\nnDBNS1Bl7Q+Df-[G7rN*ZB-;,1.1HVcAK567432rYc+Dg*=GBOr<!@;TR,+CT.u+EqBEEb-A+Df0H$+E2.*Gp$gC%13GH:0136793i^,!6YLCYF`Ugt$:/Q?+DGF1H#IgJ@<63,D.Oi'Dg*<q-Z'u<AS#[lDJ'Cc6uQrjF<G[:Cht52AKZ8:FX567901gM3@+EVO?+C]/$DIal3D]j+4AIStU$<ol2DfTuA>n%-9AThX*+D5V1DIFZ#Bm+&1H#IgJF`7cs:1\T[5681343EZf"5DJil*Ch7]2H#IgJA8c[0%15jAG%G\:B5_[*@3BT5D667892xBNA.Dfor.+CT.u+Co&)ATDl8H#Ig7$;P/UAT777924_Ao+Df0H$+DkP&AKZ8:FWb17Gmt*UAThX*+D5V1DIFZ/@<iu.Df9/qH"@El:1\T[EZf"5DJ1089221il*FCf9)+CQC/Bk8DqDIal'F`MRHH#Ig7$;P/UATAo+Df0H$+D5D3AKZ8:FWbgG%15jAG%G\:B5_[*@3BAtF4546605<GjIFWb45GA[is:1\T[EZf"5DJil*Ecl7B@<-:/DIakuDIal#ATMF'F<GjIFU\[QAThX*+D5V1DIFZ)@;889566_BEsH#IgJ@rci($;P/UATAo+Df0H$+ELt:+D5V2A7Bgq%15jAG%G\:B5_[*@3BZ'Cht5&+Dbb'+CT.u+D>n8675303<F<GjIFU\Ze$<p>FF*'!$BQ%p6F'T4^:N'nh-q@upAKZ8:FWbgG.1HV[DeL_@DeL7A7qm-X+F.mJ+E_WP9180024%15mLBJ".@BFP;DAThX*+D5V1DIFZ#Bm+&=+Dtb6ATAo+Df0H$+D5D3AKWBkBm+&1H#IgJF`8c=$;YSR/T5Q@%15jAG%G\:B5_[*@3B2sG%E3I5082295DIn!&EZf"5DJil*B5)O#+=K`oG%DeADfm1FE%)5'>=*@EA7oIZ%160J-['&DCMn'7DBNM!@q[!'FD,6++D,P4+EMHDCi=3(%166VF`JU<ARTV$-Z^D>AS#a%@:NtbDJ(LC@Wcc8H#IgQEb-A8Df6b>BR(_BD]j+0Gp$gC+=L3-+ELt:+DGpH%15[E785413yF(o/r/0K.J+C]82BHV).Dg*=JBOQ!1F!+q'ASrW'DeX*%+E)-?-qA2iDJ()1DCH#%=(NLiDJs_AFD,5.B45Xg/0JA=A0?115678})--ZWc@B5_[*@3BN*@<iu0F:AQd$<p>IAM$8_DfTuA>n%-4+DQ%?F<Gd9DJil*FCf9)+F.mJ+D>\;+A!qt+D,1rCh[d"%15UDFECq6D..3k+F.mJ+E_R4ATDj6@;]Tb$4R>H6YLCYF`Ugt$;P/UATAo+Df0H$+D5D3AKZ8:FWbgG%15jAG%G\:B5_[*@3BAtF<GjIFWb45GA[is:1\T[EZf"5DJil*Ecl7B@<-:/DIakuDIal#ATMF'F<GjIFU\[QAThX*+D5V1DIFZ)@;BEsH#IgJ@rci($;P/UATAo+Df0H$+ELt:+D5V2A7Bgq%15jAG%G\:B5_[*@3BZ'Cht5&+Dbb'+CT.u+D>n<F<GjIFU\[QAThX*+D5V1DIFZ#Bm+&1H#IgJF`7cs:1\T[EZf"5DJil*Ch7]2H#IgJA8c[0%15jAG%G\:B5_[*@3BT5DBNA.Dfor.+CT.u+Co&)ATDl8H#Ig7$;P/UATAo+Df0H$+DkP&AKZ8:FWb17Gmt*UAThX*+D5V1DIFZ/@<iu.Df9/qH"@El:1\T[EZf"5DJil*FCf9)+CQC/Bk8DqDIal'F`MRHH#Ig7$;P/UATAo+Df0H$+D5D3AKZ8:FWbgG%15jAG%G\:B5_[*@3BAtF<GjIFWb45GA[is:1\T[EZf"5DJil*Ecl7B@<-:/DIakuDIal#ATMF'F<GjIFU\[QAThX*+D5V1DIFZ)@;BEsH#IgJ@rci($;P/UATAo+Df0H$+ELt:+D5V2A7Bgq%15jAG%G\:B5_[*@3BZ'Cht5&+Dbb'+CT.u+D>n<F<GjIFT
We know the structure of the flag with start with leveleffect{, most likely contain special characters, and also end in }. None of this actually matters though since we just want any type of character that is preceded by 6 exact digits.
Knowing this, we can write some super simple dog water code to extract the flag.
import re
with open("haystack.txt") as f:
data = f.read()
pattern = re.compile(r'\d{6}(.)')
matches = pattern.findall(data)
flag = ''.join(matches)
print(flag)
Boom, we got the flag.
Reversing
In this challenge, we are given an obfuscated PowerShell script with the flag embedded in it.
$key = "seinfeld"; -join ([char[]](([Text.Encoding]::UTF8.GetString(([Convert]::FromBase64String("GgNJRkdFNxcHFwAAAThWXjoWJxsKCSMWNggZGh9NNzcKFh0LC0spCgUMGwEICAkKBzhTVCEAGCEdEwAcCQsBAR0RPw8UDA0GHwBBSTYpKSUgIE5HT0xMH3lFSU5GQQoIEgJJU0ZHAAEFAAULAAMJBwceGgsUAAINBxw2AAkSEUZ5RUlORjIeDQcARCETERwRB0VLLwUGCRcARQ4cBwsYARdJSRoOAEwCHwQOTg8WVkRXAwUPAUdmGVMABR0DRRduU0VJTjEXBRAWSCYbEhUZEFNHKAZKRQ0MX0UIBkdFNQsGRQ0HAgtLEFMWCBdGEQQBUwgICQ8GTBMcFw1PRG8R") | % { [char]($_ -bxor [byte][char]$key[$i++ % $key.Length]) } -begin { $i=0 }))))) | iex
Let’s break down the components of this script.
- The script decodes the following Base64 encoded string
FromBase64String("GgNJRkdFNxcHFwAAAThWXjoWJxsKCSMWNggZGh9NNzcKFh0LC0spCgUMGwEICAkKBzhTVCEAGCEdEwAcCQsBAR0RPw8UDA0GHwBBSTYpKSUgIE5HT0xMH3lFSU5GQQoIEgJJU0ZHAAEFAAULAAMJBwceGgsUAAINBxw2AAkSEUZ5RUlORjIeDQcARCETERwRB0VLLwUGCRcARQ4cBwsYARdJSRoOAEwCHwQOTg8WVkRXAwUPAUdmGVMABR0DRRduU0VJTjEXBRAWSCYbEhUZEFNHKAZKRQ0MX0UIBkdFNQsGRQ0HAgtLEFMWCBdGEQQBUwgICQ8GTBMcFw1PRG8R")
2. Each byte of the decoded Base64 then gets XORed with the string “seinfeld”
$key = "seinfeld" ....... | % { [char]($_ -bxor [byte][char]$key[$i++ % $key.Length]) } -begin { $i=0 }
3. Finally, the script is joined into a single string and executed
-join ([char[]](([Text.Encoding]::UTF8.GetString(([Convert]::FromBase64String(STEP_1))) | % {STEP_2} -begin { $i=0 }))) | iex
So we could reverse everything and build out the script step by step in order to see exactly what its doing, OR we could just omit the “iex” command and print out the decoded script instead of executing it.
Looks like the script would check for an environment variable, “PLEASE”, and print out the flag if it was set. Since the flag is hard coded into the script itself in cleartext, we don't actually need to do any of that.
Just to be thorough tho here are the commands to build out the script step by step and print out the full decoded output.
$key = "seinfeld"
$base64 = "GgNJRkdFNxcHFwAAAThWXjoWJxsKCSMWNggZGh9NNzcKFh0LC0spCgUMGwEICAkKBzhTVCEAGCEdEwAcCQsBAR0RPw8UDA0GHwBBSTYpKSUgIE5HT0xMH3lFSU5GQQoIEgJJU0ZHAAEFAAULAAMJBwceGgsUAAINBxw2AAkSEUZ5RUlORjIeDQcARCETERwRB0VLLwUGCRcARQ4cBwsYARdJSRoOAEwCHwQOTg8WVkRXAwUPAUdmGVMABR0DRRduU0VJTjEXBRAWSCYbEhUZEFNHKAZKRQ0MX0UIBkdFNQsGRQ0HAgtLEFMWCBdGEQQBUwgICQ8GTBMcFw1PRG8R"
$decodedBytes = [Convert]::FromBase64String($base64)
$keyBytes = [System.Text.Encoding]::UTF8.GetBytes($key)
$i = 0
$result = $decodedBytes | ForEach-Object { [char]($_ -bxor $keyBytes[$i++ % $keyBytes.Length]) }
$resultString = -join $result
Write-Output $resultString