Hidden Flag 220
Description:
Hidden Flag (Reverse, Hard, 220 pts) Author: Khanov Artur (awengar)
Somebody hides flag in RAM. Catch it
Raw dump: https://cybrics.net/files/20190717.zip.torrent
I didn’t solve this challenge during the ctf, one of the main reasons was because the challenge was a mix of a forensics/reverse, I got stuck on the forensics part, mostly because I don’t have much experience looking at memory dumps, the reversing part was pretty easy after finding the “malicious” binary.
Forensics part
So we start with a memdump and we somehow need to find the flag in memory, I used volatility for this part. The first thing we have to do is to find the most suitable profile for the dump, volatility has a command named imageinfo which can help us with that:
1 | $ volatility -f 20190717.mem imageinfo |
Volatility suggests 5 profiles, Win10x64_17134 is the most updated so I opted to use that one. This is the part where I got stuck I kept insisting on looking only at processes during the ctf, I used comands like pslist, psxview etc and I found some interesting processes that weren’t listed in pslist :
1 | $ volatility -f 20190717.mem --profile Win10x64_17134 psxview |
As you can see this 3 processes are not shown in pslist one of them doesn’t even have a name or a valid PID, I tried to dump the memory of this 3 but I was not able to do it, for some reason volatility was spiting errors, I also dumped part of the registry too trying to find something useful but that also failed.
Much later I decided to view the list of kernel drivers loaded on the system, for this I used the modules command. This command walks the doubly-linked list of LDR_DATA_TABLE_ENTRY structures pointed to PsLoadedModuleList. However this cannot find hidden/unlinked kernel drivers but if this doesn’t work we can also try to do a modscan which serves that purpose.
The output of the modules command:
1 | volatility -f 20190717.mem --profile Win10x64_17134 modules |
We didn’t even ran modscan and we already find two weird drivers that are loaded directly from a strange path C:\t4est and C:\test, this isn’t normal, the normal thing to happen is to be loaded from the system32 folder… Obviously RamCaptureDriver64.sys is probably what the creator used to dump this memory, so we are left with flagostor.sys which already has a weird name and also hints for flag after this I used moddump to extract this driver:
1 | $ volatility -f 20190717.mem --profile Win10x64_17134 moddump -b 0xfffff8005daf0000 -D . |
Checking what kind of file:
1 | $ file driver.fffff8005daf0000.sys |
And this is it, the forensics part is over lets go for the reversing part.
Reversing part
We have now a PE executable, I used both IDA and Ghidra, this time Ghidra actually helped me decoding the final part of the decryption function (Pseudo c code was somehow presented better than ida at least from my perspective). I first started analysing with IDA, the main function sub_FFFFF8005DAF1000 which I renamed later to printLoader in the picture below:
So lets check the next function:
Dumping the global variable (Double click on unk_FFFFF8005DAF3000):
Analysing sub_FFFFF8005DAF1440:
Since we can convert assembly to pseudo code c in IDA we can easily convert this function into python:
Creating a python script for this:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def generate_table(key):
table = []
for i in xrange(256):
table.append(i)
v6 = 0
for j in xrange(256):
iVar1 = ord(key[j%len(key)]) + table[j] + v6
v6 = ((iVar1&0xff) + iVar1) - iVar1
# swap
aux = table[j]
table[j] = table[v6]
table[v6] = aux
##########
return table
The same thing can be done for the decryptFlag function in this case I chose to use GHIDRA which the pseudo code was a bit more understandable for me at least:
Once again this could easily be converted to python:
1 | def decrypt_flag(table,flagB): |
Obviously there was no need to rewrite all of this in python if you manage to run the binary on your computer in my case I wasn’t able to do it in my virtual machine due to some errors that I don’t know, if you could run it you just needed to put a break point in the end and watch the stored values obtaining the flag with ease. The final python script:
1 | flagB = '\x2D\xFB\x9B\xA8\x21\xF8\xB0\xB5\xFA\xEC\x58\xC5\xF9\x35\x57\xFA\xE1\x62\x0E\x19\x45\x7D\x33\x58\x6F\xC9\x88\x4F\x70\x82' |
Getting the flag:
1 | $ python hiddenFlag/hidden.py |
The flag was cybrics{H1DD3N_D33P_1N_NTKRNL}