Mem
Mem
Platform: spbctf | Category: Forensics | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-03-17 | Status: Solved Techniques: bash_history_recovery, command_line_forensics, gpg_symmetric_decryption, little_endian_byte_reversal, memory_dump_analysis, multi_step_encoding_reversal, string_extraction
Summary
Linux memory dump forensics. Attacker obfuscated THEFLAG.txt through 5-step encoding chain (od -t x4, base64, xxd -E -b, tr, GPG), then shredded originals. Solution: extract bash history from RAM to reveal commands and GPG passphrase, reverse each transformation step, handle little-endian byte order from od -t x4.
Mem - spbctf
Description
Ыж оставил незалоченную линуховую консоль, и куда-то отошёл. Пока его не было, кто-то жестоко надругался над флагом в файле THEFLAG.txt, а потом и вообще зашифровал его и грохнул оригинал с диска. Вернувшись, Ыж не растерялся и снял дамп оперативки со своей машины. Восстановите содержимое THEFLAG.txt.
(Translation: Someone left an unlocked Linux console. While away, an attacker obfuscated the flag in THEFLAG.txt through multiple transformations, encrypted it with GPG, and securely deleted all original files with shred. The owner took a memory dump. Recover THEFLAG.txt contents.)
File provided: mem.rar containing a 134MB Linux memory dump
Analysis
Initial Recon
Extracted mem.rar (23MB compressed → 134MB raw memory dump). Since this is a Linux memory dump and the task mentions bash commands, started by searching for references to THEFLAG.txt using strings.
Bash History Recovery
Found the complete bash command history still resident in memory:
bash read-only • copy allowedstrings mem | grep -B2 -A10 "cat THEFLAG.txt"
This revealed the full attack chain:
bash read-only • copy allowedcat > THEFLAG.txt cat THEFLAG.txt | od -t x4 | tr -d ' ' | tsort > ttt1.txt cat ttt1.txt | base64 -w23 | tac | xxd -E -b > ttt2.txt cat ttt2.txt | tr a-zA-Z0-9 0-9a-zA-Z | sed 's/ //g' > ttt3.txt gpg --armor --symmetric --batch --passphrase mys3cr3tP4SSW0RDnotAflag < ttt3.txt > encrypted_flag.txt shred -u THEFLAG.txt ttt1.txt ttt2.txt ttt3.txt
PGP Message Extraction
Found the full PGP-armored encrypted message still in memory:
bash read-only • copy allowedstrings mem | grep -A100 "BEGIN PGP MESSAGE"
Solution
Step 1: GPG Decrypt
Decrypted with the passphrase visible in bash history:
bash read-only • copy allowedgpg --decrypt --batch --passphrase "mys3cr3tP4SSW0RDnotAflag" encrypted_flag.txt > ttt3_recovered.txt
Step 2: Reverse tr Mapping
The forward transform was tr a-zA-Z0-9 0-9a-zA-Z. This is NOT its own inverse!
- Forward:
a-z→0-9a-p,A-Z→q-zA-P,0-9→Q-Z - Inverse:
tr 0-9a-zA-Z a-zA-Z0-9
bash read-only • copy allowedcat ttt3_recovered.txt | tr '0-9a-zA-Z' 'a-zA-Z0-9' > ttt2_recovered.txt
Step 3: Reverse xxd -E -b
The xxd -E -b command outputs binary representation with big-endian grouping. Parse binary back to bytes:
bash read-only • copy allowedcat ttt2_recovered.txt | sed 's/^[0-9a-f]*://' | sed 's/[^01]//g' | tr -d '\n' | \ fold -w8 | while read byte; do printf "\\x$(printf '%02x' $((2#$byte)))"; done > ttt2_binary.txt
Step 4: Reverse tac + base64
bash read-only • copy allowedcat ttt2_binary.txt | tac | base64 -d > ttt1_recovered.txt
Step 5: Reverse od -t x4 | tr -d ' ' | tsort
This was the trickiest step:
od -t x4outputs 4-byte words in little-endian format (on x86)tr -d ' 'removes all spaces, collapsing address+data into single tokenstsortdoes topological sort, but with single-word lines it just reorders
Recovery process:
- Sort lines by the 7-digit octal address prefix
- Extract hex data after the address
- Reverse each 4-byte word from little-endian to big-endian byte order
- Convert hex to ASCII
Example: 676e6f43 (little-endian) → 436f6e67 (big-endian) → "Cong"
python read-only • copy allowed#!/usr/bin/env python3 import re with open('ttt1_recovered.txt') as f: lines = f.readlines() # Parse lines: 7-digit octal address followed by hex data data = [] for line in lines: line = line.strip() if len(line) >= 7: addr = int(line[:7], 8) # Octal address hex_data = line[7:] # Remaining hex data.append((addr, hex_data)) # Sort by address data.sort(key=lambda x: x[0]) # Extract and reverse each 4-byte word (little-endian to big-endian) result = b'' for addr, hex_str in data: # Each 8 hex chars = 4 bytes in little-endian for i in range(0, len(hex_str), 8): word = hex_str[i:i+8] if len(word) == 8: # Reverse byte order reversed_word = word[6:8] + word[4:6] + word[2:4] + word[0:2] result += bytes.fromhex(reversed_word) print(result.decode('utf-8', errors='ignore'))
Result
Recovered THEFLAG.txt content:
Congratulations! You won. Here's the flag: REDACTED