← Back to Writeups
HTBN/AReversing

RAuth

XESXOR8/23/20264 min read
#reversing#htb#n/a

RAuth

Platform: HackTheBox | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: NA | Author: D3v0o0Nu11 | Date: 2026-02-09 | Status: Solved Techniques: hardcoded_key_extraction, rodata_analysis, salsa20_decryption, simd_comparison_pattern, stream_cipher_symmetry

Summary

ELF 64-bit LSB PIE executable, x86-64, dynamically linked, with debug_info, not stripped. Rust binary rauth, compiled with Rust 1.47.0, implements authentication by encrypting the password with Salsa20 algorithm and comparing it to a reference ciphertext. A remote service is also provided at `154.

Recon

Port scan

nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
PortServiceVersionNotes
<PORT><SVC><VER><notes>

Enumeration highlights

  • Event: HackTheBox | ID: 20260209_hackthebox_rauth
  • Tags: elf64, stream_cipher, hardcoded_key, rust, salsa20, crypto_reversing, password_checker
  • Indicators: Rust binary with salsa20 crate in strings, hardcoded key/nonce in .rodata and immediates, stream cipher encrypt == decrypt (XOR symmetry), pcmpeqb + pmovmskb SIMD comparison pattern, cipher-0.3.0 and salsa20-0.8.0 crate references
  • Source: 20260209_hackthebox_rauth.md

Foothold

Vulnerability / Misconfiguration

  1. Hardcoded_key_extraction
  2. Rodata_analysis
  3. Salsa20_decryption
  4. Simd_comparison_pattern
  5. Stream_cipher_symmetry
<command>

Exploitation

  • See original writeup content for detailed exploitation.

Privilege Escalation

Enumeration

sudo -l
find / -perm -4000 2>/dev/null
getcap -r / 2>/dev/null
cat /etc/crontab
ps aux

Exploitation

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
<command>

Flags

FlagLocationValue
flagREDACTED

Key Takeaways / Lessons

  • hardcoded_key_extraction
  • rodata_analysis
  • salsa20_decryption
  • simd_comparison_pattern
  • stream_cipher_symmetry
  • Tags: elf64, stream_cipher, hardcoded_key, rust, salsa20, crypto_reversing, password_checker

Original Writeup

<details><summary>Click to expand original content</summary>

Description

My implementation of authentication mechanisms in C turned out to be failures. But my implementation in Rust is unbreakable. Can you retrieve my password?

ELF 64-bit LSB PIE executable, x86-64, dynamically linked, with debug_info, not stripped. Rust binary rauth, compiled with Rust 1.47.0, implements authentication by encrypting the password with Salsa20 algorithm and comparing it to a reference ciphertext. A remote service is also provided at 154.57.164.83:30723.

Analysis

Initial Reconnaissance

$ file rauth
ELF 64-bit LSB PIE executable, x86-64, dynamically linked, with debug_info, not stripped

$ strings rauth | grep -i salsa
salsa20-0.8.0
cipher-0.3.0

$ strings rauth | grep -E "password|auth|flag"
Welcome to secure login portal!
Enter the password to access the system:
Successfully Authenticated
You entered a wrong password!
Flag:

The binary is not stripped and contains debug_info — this significantly simplifies analysis. The strings show references to salsa20-0.8.0 and cipher-0.3.0 crates, which immediately points to the encryption algorithm.

Suspicious hex string in .rodata: ef39f4f20e76e33bd25f4db338e81b10

Symbols (nm)

$ nm rauth | grep -E "salsa|rauth"
0000000000006460 T _ZN5rauth4main17h7d7aed61ae7734f4E
                   _ZN7salsa204core13Core$LT$R$GT$3new17h06163fbcdf79ba51E
                   _ZN79_$LT$salsa20..salsa..Salsa$LT$R$GT$..cipher..stream..StreamCipher$GT$19try_apply_keystream17hdbdc0561b68e3b6aE

Key functions:

  • rauth::main @ 0x6460 — main logic
  • Salsa20::Core::new(key, nonce) — cipher initialization
  • StreamCipher::try_apply_keystream — applying keystream (encryption/decryption)

Disassembling main (0x6460 — 0x6bd0)

Execution flow of main:

  1. Print greeting — prints "Welcome to secure login portal!" and "Enter the password to access the system:"
  2. Read input — reads password from stdin, trims trailing newline
  3. Load Salsa20 key — 32 bytes from .rodata at address 0x39ca0: ASCII string ef39f4f20e76e33bd25f4db338e81b10 (used as raw key bytes, not as hex)
  4. Load nonce — 8 bytes from immediate value in instruction movabsq $0x3361303732633464 @ 0x65e3 → little-endian ASCII d4c270a3
  5. Initialize cipher — call Salsa20::Core::new(key, nonce) @ 0x6652
  6. Encrypt input — copy input to new buffer, call try_apply_keystream @ 0x6759
  7. Check length — compare encrypted input length with 0x20 (32 bytes) @ 0x67e0
  8. Compare with reference — 32-byte reference ciphertext from .rodata @ 0x39cc0, comparison via SSE instructions pcmpeqb + pmovmskb (byte-wise SIMD comparison)
  9. Result — on match: "Successfully Authenticated" + decrypt and print flag; otherwise: "You entered a wrong password!"

Extracting Crypto Parameters

Key   (32 bytes @ 0x39ca0): b'ef39f4f20e76e33bd25f4db338e81b10'  (ASCII hex string as raw bytes)
Nonce  (8 bytes, immediate): b'd4c270a3'                          (ASCII string as raw bytes)
Ciphertext (32 bytes @ 0x39cc0): 05055fb1a329a8d558d9f556a6cb31f324432a31c99dec72e33eb66f62ad1bf9

Important observation: the key is an ASCII string of hex characters (32 characters = 32 bytes), not decoded 16 bytes. The Rust salsa20 crate accepts &[u8; 32], and the program passes the string as-is.

Solution

Key Insight: Stream Cipher Symmetry

Salsa20 is a stream cipher. Encryption and decryption are the same operation: XOR with keystream. If encrypt(plaintext) = ciphertext, then encrypt(ciphertext) = plaintext. Therefore, to recover the password, we just need to "encrypt" the reference ciphertext with the same key and nonce.

Decryption Script

#!/usr/bin/env python3
"""
RAuth — Salsa20 password recovery
Decrypt the expected ciphertext to recover the password.
"""
from Crypto.Cipher import Salsa20

# Extracted from binary .rodata and immediates
key   = b'ef39f4f20e76e33bd25f4db338e81b10'   # 32 bytes ASCII (raw key)
nonce = b'd4c270a3'                             # 8 bytes ASCII (raw nonce)
ct    = bytes.fromhex('05055fb1a329a8d558d9f556a6cb31f324432a31c99dec72e33eb66f62ad1bf9')

cipher = Salsa20.new(key=key, nonce=nonce)
password = cipher.decrypt(ct)
print(f"Password: {password.decode()}")
# Output: TheCrucialRustEngineering@2021;)

Getting the Flag

$ echo 'TheCrucialRustEngineering@2021;)' | nc 154.57.164.83 30723
Welcome to secure login portal!
Enter the password to access the system: 
Successfully Authenticated
Flag: "HTB{REDACTED}"
</details>

Auto-tracked: saved to WriteUps; run /xesor-revise to fold lessons into XESXor_Methodology.md.

signed by XESXOR