Credits to the numerous other walkthroughs posted by other players of the HTB Cyber Santa CTF 2021, these are just notes I compiled for future referencing and for revision
Forensics Day 3 : Persistence
Here are my recorded theory learnings and notes taken when I attempted to do the challenge again after the event.
- Pre Challenge Learnings
The clue is in the name, persistence. Googling this and malicious actors gives us the following information:
Persistence is an overall tactic that adversaries, malware, and tools will use to ensure they keep access to systems across events that might interrupt access. Some examples of events that may interrupt access are shutdowns and restarts, file deletion, or credential changes. Persistence may also be used as a means of “cleaning up” the evidence that a malware payload was ever even there.
Common techniques:
1. Registry run keys
2. Startup folder
Registry run keys are very specific keys in the Windows registry that are invoked during system start up.
These keys allow specific settings or configurations to be loaded automatically. In addition, registry run keys can also point directly at executable files, allowing specific programs (and DLL files) to be executed at start up.
Similarly, the startup folder corresponds to a series of registry keys that will execute files in specific locations on start up.
Persistence, when talking about technique T1547.001, is the modification of specific registry keys and values in order to have an executable, command, or script run every time the system is rebooted.
Most Common targets:
While there are several registry keys that can be used, the most commonly abused are the default keys on a Windows system, specifically:
hivescan - To find the physical addresses of CMHIVEs (registry hives) in memory
hivelist - To locate the virtual addresses of registry hives in memory, and the full paths to the corresponding hive on disk
printkey - To display the subkeys, values, data, and data types contained within a specified registry key, use the printkey command. By default, printkey will search all hives and print the key information (if found) for the requested key.
hivedump - To recursively list all subkeys in a hive, use the hivedump command and pass it the virtual address to the desired hive.
hashdump - To extract and decrypt cached domain credentials stored in the registry
lsadump - To dump LSA secrets from the registry, use the lsadump command. This exposes information such as the default password (for systems with autologin enabled), the RDP public key, and credentials used by DPAPI
One of the problems faced here was the zsh killing of RsaCtfTool, which can be solved by increasing the amount of RAM for Kali to 10GB for encryption to run.
Given : Email with public key and encrypted text
Hello Mr Jingles,
We got the reindeer as you requested. There is a problem though. Its nose is so red and bright and makes it very hard to hide him anywhere near north pole. We have moved to a secret location far away. I have encrypted this information with your public key in case you know who is watching.
The steps below are taken to crack the challenge :
┌──(kali㉿kali)-[~/Desktop/tools/RsaCtfTool]
└─$ ./RsaCtfTool.py --dumpkey --publickey reindeer_key.pub 2 ⨯
private argument is not set, the private key will not be displayed, even if recovered.
Details for reindeer_key.pub:
n: 29052360453120059177701146498207729611014362120841772147885284668310294675407700581246333337318872050600353022438909391852076208405990507154764842795064455368228014381969783955360165426546947312973195061115837228105648770122442650123819968683831588775039837617788817831554836487051931001049480790287468125246758818911220414888048673899462271009956700067150701189256017793349102117503912782889345559816174845605183913828898737756645848010661322897081850561427949550036638510279173557403134806365178654334553002357480355906235714208451535185647256346503450896572487047615057007598805977277186223884121839444217172432487
e: 3
┌──(kali㉿kali)-[~/Desktop/tools/RsaCtfTool]
└─$ ./RsaCtfTool.py --publickey reindeer_key.pub --uncipherfile reindeer_location.enc --private
...
[*] Performing brent attack on reindeer_key.pub.
[!] Timeout.
[*] Performing neca attack on reindeer_key.pub.
Can't load neca because neca binary is not installed
[*] Performing binary_polinomial_factoring attack on reindeer_key.pub.
Can't load binary_polinomial_factoring because sage binary is not installed
Results for reindeer_key.pub:
Sorry, cracking failed.
Unciphered data :
HEX : 0xa415e596f3e4a21c25003081894a080532af6ba4739145593a9695f886b146e5b865b3c46fd2c14cc19059d8a3491018ff10fe4d02bfad9cceee6735c2844e87f10ada2593acb6988315f2e760a65b15fea3b781937af3651fdedae68e1210c4ed3602d0d1bc94e1f054ad
INT (big endian) : 307968727924643589446817054356670587947811738257755826328391346771555909495309166997072951847162296442948717292181103911669692516081555431892296155634695866133360083497101472628760457860959909333788155352877056162451321677649740405158218026991156435780392109
INT (little endian) : 325322852408515827924680177664573471113206438368894095154748946216388495533407429128074259190964109468771287894216654896504526078759213214576415893088320551628507634445347416332262568586203743010212094388519639262170697695732520271131614082510566363490489764
STR : b'\xa4\x15\xe5\x96\xf3\xe4\xa2\x1c%\x000\x81\x89J\x08\x052\xafk\xa4s\x91EY:\x96\x95\xf8\x86\xb1F\xe5\xb8e\xb3\xc4o\xd2\xc1L\xc1\x90Y\xd8\xa3I\x10\x18\xff\x10\xfeM\x02\xbf\xad\x9c\xce\xeeg5\xc2\x84N\x87\xf1\n\xda%\x93\xac\xb6\x98\x83\x15\xf2\xe7`\xa6[\x15\xfe\xa3\xb7\x81\x93z\xf3e\x1f\xde\xda\xe6\x8e\x12\x10\xc4\xed6\x02\xd0\xd1\xbc\x94\xe1\xf0T\xad'
- RsaCtfTool.py Command References
--dumpkey : Just dump the RSA variables from a key - n,e,d,p,q
from random import randintfrom Crypto.Cipher import AESfrom Crypto.Util.Padding import padimport jsonflag =b'HTB{dummyflag}'defgen_key(option=0): alphabet =b'0123456789abcdef'#16 bytes with the characters (hex values) const =b'cyb3rXm45!@#'# 12 byte password key =b''# range = 16 - 12 = 4for i inrange(16-len(const)):# append a randome char from alphabet to the key key +=bytes([alphabet[randint(0,15)]])if option:return key + const # key 2 = 4 random bytes + constelse:return const + key # key 1 = const + 4 random bytes# Simply double AES - google for vulnerabilitesdefencrypt(data,key1,key2): cipher = AES.new(key1, mode=AES.MODE_ECB)# Encrypt with key 1 ct = cipher.encrypt(pad(data, 16))# padded to 16 bytes cipher = AES.new(key2, mode=AES.MODE_ECB)# Encrypt with key 2 ct = cipher.encrypt(ct)# encrypt the key 1 encrypted text with key 2return ct.hex()# generates two keysdefchallenge(): #keys unkown to everyone but evil elves, but encryption algo is vulnerable k1 =gen_key()# no parameters parsed in, hence default to option = 0 k2 =gen_key(1)# option = 1 ct =encrypt(flag, k1, k2)print('Super strong encryption service approved by the elves X-MAS spirit.\n'+\'Message for all the elves:\n'+ct +'\nEncrypt your text:\n> ')try: dt = json.loads(input().strip())# Takes our input as JSON pt =bytes.fromhex(dt['pt'])# Loads plain text from 'pt' key (hex) res =encrypt(pt, k1, k2)# Encrypt our plaintext and print ciphertextprint(res +'\n')exit(1)exceptExceptionas e:print(e)print('Invalid payload.\n')exit(1)if__name__=="__main__":challenge()