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
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:
Define :
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
--pubickey : The public key input
--private : enable recovery of private key
- Some good writeups to learn RSA challenges
Crypto Day 4 : Meet Me Halfway
Given : The following encryption python script
from random import randint
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import json
flag = b'HTB{dummyflag}'
def gen_key(option=0):
alphabet = b'0123456789abcdef' #16 bytes with the characters (hex values)
const = b'cyb3rXm45!@#' # 12 byte password
key = b''
# range = 16 - 12 = 4
for i in range(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 + const
else:
return const + key # key 1 = const + 4 random bytes
# Simply double AES - google for vulnerabilites
def encrypt(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 2
return ct.hex()
# generates two keys
def challenge(): #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 ciphertext
print(res + '\n')
exit(1)
except Exception as e:
print(e)
print('Invalid payload.\n')
exit(1)
if __name__ == "__main__":
challenge()