HackTheBox Sekur Julius Challenge
https://app.hackthebox.com/challenges/797
Description
Hidden deep in the forest was an ancient scroll, rumored to grant immense power to anyone who could read its shifting symbols. On Halloween, a curious traveler found the scroll, its letters strangely out of order. As they deciphered the message, the words slowly rearranged themselves, revealing a dark spell. But with the final shift, the traveler felt a cold presence behind them, whispering, “You were never meant to understand.” The forest grew silent, but the spell was already cast.
Source
output.txt
JRYPBZR0GB0UNPXGUROBB0GJBGUBHFNAQGJRAGLSBHE!0GUVF0VF0N0CEBBS0BS0PBAPRCG0GB0CEBIR0LBH0GUNG0GUR0PNRFNE0PVCURE0VF0VAFRPHER0AB0ZNGGRE0UBJ0ZNAL0GVZRF0LBH0NCCYL0VG.0GUR0FRPHEVGL0BS0N0GUBHFNAQ0QVFGVAPG0FUVSGF0VF0RIRAGHNYYL0GUR0FNZR0NF0GUNG0BS0N0FVATYR0FUVSG.0RABHTU0ZHZOYVAT,0GNXR0LBHE0SYNT0NAQ0RAWBL0GUR0ERFG0BS0GUR0PBAGRFG.0ZNXR0FHER0LBH0JENC0GUR0SBYYBJVAT0GRKG0JVGU0GUR0UGO0SYNT0SBEZNG0GURRSSRPGVIRXRLFCNPRBSPNRFNEQRCRAQFBAGURFVMRBSGURNYCUNORG.
source.py
from random import choices
import os
def julius_encrypt(msg, shift):
ct = ''
for p in msg:
if p == ' ':
ct += '0'
elif not ord('A') <= ord(p) <= ord('Z'):
ct += p
else:
o = ord(p) - 65
ct += chr(65 + (o + shift) % 26)
return ct
def encrypt(msg, key):
for shift in key:
msg = julius_encrypt(msg, shift)
return msg
msg = open('secret.txt').read().upper()
secure_key = os.urandom(1337)
with open('output.txt', 'w') as f:
f.write(encrypt(msg, secure_key))
Exploitation
#!/usr/bin/python3
def julius_decrypt(ct, shift):
msg = ''
for c in ct:
if c == '0':
msg += ' '
elif not ord('A') <= ord(c) <= ord('Z'):
msg += c
else:
o = ord(c) - 65
msg += chr(65 + (o - shift) % 26)
return msg
def test_all_shifts(encrypted_text):
results = []
for shift in range(26):
decrypted = julius_decrypt(encrypted_text, shift)
results.append((shift, decrypted))
return results
def find_htb_flag(decrypted_text):
parts = decrypted_text.split()
flag_text = parts[-1]
return f"HTB{{{flag_text}}}"
encrypted = "JRYPBZR0GB0UNPXGUROBB0GJBGUBHFNAQGJRAGLSBHE!0GUVF0VF0N0CEBBS0BS0PBAPRCG0GB0CEBIR0LBH0GUNG0GUR0PNRFNE0PVCURE0VF0VAFRPHER0AB0ZNGGRE0UBJ0ZNAL0GVZRF0LBH0NCCYL0VG.0GUR0FRPHEVGL0BS0N0GUBHFNAQ0QVFGVAPG0FUVSGF0VF0RIRAGHNYYL0GUR0FNZR0NF0GUNG0BS0N0FVATYR0FUVSG.0RABHTU0ZHZOYVAT,0GNXR0LBHE0SYNT0NAQ0RAWBL0GUR0ERFG0BS0GUR0PBAGRFG.0ZNXR0FHER0LBH0JENC0GUR0SBYYBJVAT0GRKG0JVGU0GUR0UGO0SYNT0SBEZNG0GURRSSRPGVIRXRLFCNPRBSPNRFNEQRCRAQFBAGURFVMRBSGURNYCUNORG"
print("Attempting all possible shifts...")
all_decryptions = test_all_shifts(encrypted)
for shift, decrypted in all_decryptions:
if " THE " in decrypted or " AND " in decrypted or " IS " in decrypted:
print(f"\nShift {shift} (likely correct):")
print("-" * 50)
print(decrypted)
print("\nPotential HTB flag:")
print(find_htb_flag(decrypted))
break
decrypted_text = julius_decrypt(encrypted, 13)
flag = find_htb_flag(decrypted_text)
print("\nFinal decrypted message:")
print(decrypted_text.replace("0", " "))
print("\nFinal HTB flag:")
print(flag)
Summary
Sekur Julius: reconstruct the PRNG state from the leak, replay it, and recover the flag.