ctf-misc

Quick reference for misc challenges. For detailed techniques, see supporting files.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "ctf-misc" with this command: npx skills add ramzxy/ctf/ramzxy-ctf-ctf-misc

CTF Miscellaneous

Quick reference for misc challenges. For detailed techniques, see supporting files.

Additional Resources

  • pyjails.md - Python jail/sandbox escape techniques

  • bashjails.md - Bash jail/restricted shell escape techniques

  • encodings.md - Encodings, QR codes, audio, esolangs

  • RF/SDR/IQ signal processing section below covers QAM, PSK, carrier recovery, timing sync

General Tips

  • Read all provided files carefully

  • Check file metadata, hidden content, encoding

  • Power Automate scripts may hide API calls

  • Use binary search when guessing multiple answers

Common Encodings

Base64

echo "encoded" | base64 -d

Base32 (A-Z2-7=)

echo "OBUWG32D..." | base32 -d

Hex

echo "68656c6c6f" | xxd -r -p

ROT13

echo "uryyb" | tr 'a-zA-Z' 'n-za-mN-ZA-M'

Identify by charset:

  • Base64: A-Za-z0-9+/=

  • Base32: A-Z2-7= (no lowercase)

  • Hex: 0-9a-fA-F

IEEE-754 Float Encoding (Data Hiding)

Pattern (Floating): Numbers are float32 values hiding raw bytes.

Key insight: A 32-bit float is just 4 bytes interpreted as a number. Reinterpret as raw bytes → ASCII.

import struct

List of suspicious floating-point numbers

floats = [1.234e5, -3.456e-7, ...] # Whatever the challenge gives

Convert each float to 4 raw bytes (big-endian)

flag = b'' for f in floats: flag += struct.pack('>f', f) print(flag.decode())

CyberChef solution:

  • Paste numbers (space-separated)

  • "From Float" → Big Endian → Float (4 bytes) → Space delimiter

Variations:

  • Double (8 bytes): struct.pack('>d', val)

  • Little-endian: struct.pack('<f', val)

  • Mixed endianness: try both if first doesn't produce ASCII

USB Mouse PCAP Reconstruction

Pattern (Hunt and Peck): USB HID mouse traffic captures on-screen keyboard typing.

Workflow:

  • Open PCAP in Wireshark — identify USBPcap with HID interrupt transfers

  • Identify device (Device Descriptor → manufacturer/product)

  • Use USB-Mouse-Pcap-Visualizer: github.com/WangYihang/USB-Mouse-Pcap-Visualizer

  • Extract click coordinates (falling edges of left_button_holding )

  • Plot clicks on scatter plot with matplotlib

  • Overlay on image of Windows On-Screen Keyboard

  • Animate clicks in order to read typed text

Key details:

  • Mouse reports relative coordinates (deltas), not absolute

  • Cumulative sum of deltas gives position track

  • Rising/falling edges of button state = click start/end

  • Need to scale/stretch overlay to match OSK layout

import pandas as pd import matplotlib.pyplot as plt

df = pd.read_csv('mouse_data.csv')

Find click positions (falling edges)

clicks = df[df['left_button_holding'].shift(1) == True & (df['left_button_holding'] == False)]

Cumulative position from relative deltas

x_pos = df['x'].cumsum() y_pos = df['y'].cumsum()

Plot clicks over OSK image

plt.scatter(click_x, click_y, c='red', s=50)

File Type Detection

file unknown_file xxd unknown_file | head binwalk unknown_file

Archive Extraction

7z x archive.7z # Universal tar -xzf archive.tar.gz # Gzip tar -xjf archive.tar.bz2 # Bzip2 tar -xJf archive.tar.xz # XZ

Nested Archive Script

while f=$(ls .tar *.gz *.bz2 *.xz *.zip *.7z 2>/dev/null|head -1) && [ -n "$f" ]; do 7z x -y "$f" && rm "$f" done

QR Codes

zbarimg qrcode.png # Decode qrencode -o out.png "data"

Audio Challenges

sox audio.wav -n spectrogram # Visual data qsstv # SSTV decoder

RF / SDR / IQ Signal Processing

IQ File Formats

  • cf32 (complex float 32): GNU Radio standard, np.fromfile(path, dtype=np.complex64)

  • cs16 (complex signed 16-bit): np.fromfile(path, dtype=np.int16).reshape(-1,2) , then I + jQ

  • cu8 (complex unsigned 8-bit): RTL-SDR raw format

Analysis Pipeline

import numpy as np from scipy import signal

1. Load IQ data

iq = np.fromfile('signal.cf32', dtype=np.complex64)

2. Spectrum analysis - find occupied bands

fft_data = np.fft.fftshift(np.fft.fft(iq[:4096])) freqs = np.fft.fftshift(np.fft.fftfreq(4096)) power_db = 20*np.log10(np.abs(fft_data)+1e-10)

3. Identify symbol rate via cyclostationary analysis

x2 = np.abs(iq_filtered)**2 # squared magnitude fft_x2 = np.abs(np.fft.fft(x2, n=65536))

Peak in fft_x2 = symbol rate (samples_per_symbol = 1/peak_freq)

4. Frequency shift to baseband

center_freq = 0.14 # normalized frequency of band center t = np.arange(len(iq)) baseband = iq * np.exp(-2j * np.pi * center_freq * t)

5. Low-pass filter to isolate band

lpf = signal.firwin(101, bandwidth/2, fs=1.0) filtered = signal.lfilter(lpf, 1.0, baseband)

QAM-16 Demodulation with Carrier + Timing Recovery

The key challenge is carrier frequency offset causing constellation rotation (circles instead of points).

Decision-directed carrier recovery + Mueller-Muller timing:

Loop parameters (2nd order PLL)

carrier_bw = 0.02 # wider BW = faster tracking, more noise damping = 1.0 theta_n = carrier_bw / (damping + 1/(4*damping)) Kp = 2 * damping * theta_n # proportional gain Ki = theta_n ** 2 # integral gain

carrier_phase = 0.0 carrier_freq = 0.0

for each symbol sample: # De-rotate by current phase estimate symbol = raw_sample * np.exp(-1j * carrier_phase)

# Find nearest constellation point (decision)
nearest = min(constellation, key=lambda p: abs(symbol - p))

# Phase error (decision-directed)
error = np.imag(symbol * np.conj(nearest)) / (abs(nearest)**2 + 0.1)

# Update 2nd order loop
carrier_freq += Ki * error
carrier_phase += Kp * error + carrier_freq

Mueller-Muller timing error detector:

timing_error = (Re(y[n]-y[n-1]) * Re(d[n-1]) - Re(d[n]-d[n-1]) * Re(y[n-1])) + (Im(y[n]-y[n-1]) * Im(d[n-1]) - Im(d[n]-d[n-1]) * Im(y[n-1]))

y = received symbol, d = decision (nearest constellation point)

Key Insights for RF CTF Challenges

  • Circles in constellation = frequency offset not corrected

  • Spirals = frequency offset + time-varying phase

  • Blobs on grid = correct sync, just noise

  • 4-fold ambiguity: DD carrier recovery can lock with 0°/90°/180°/270° rotation — try all 4

  • Bandwidth vs symbol rate: BW = Rs × (1 + α), where α is roll-off factor (0 to 1)

  • RC vs RRC: "RC pulse shaping" at TX means receiver just samples (no matched filter needed); "RRC" means apply matched RRC filter at RX

  • Cyclostationary peak at Rs confirms symbol rate even without knowing modulation order

  • AGC: normalize signal power to match constellation power: scale = sqrt(target_power / measured_power)

  • GNU Radio's QAM-16 default mapping is NOT Gray code — always check the provided constellation map

Common Framing Patterns

  • Idle/sync pattern repeating while link is idle

  • Start delimiter (often a single symbol like 0)

  • Data payload (nibble pairs for QAM-16: high nibble first, low nibble)

  • End delimiter (same as start, e.g., 0)

  • The idle pattern itself may contain the delimiter value — distinguish by context (is it part of the 16-symbol repeating pattern?)

pwntools Interaction

from pwn import *

r = remote('host', port) r.recvuntil(b'prompt: ') r.sendline(b'answer') r.interactive()

Python Jail Quick Reference

Enumerate functions:

for c in string.printable: result = test(f"{c}()") if "error" not in result.lower(): print(f"Found: {c}()")

Oracle pattern (L, Q, S functions):

flag_len = int(test("L()")) for i in range(flag_len): for c in range(32, 127): if query(i, c) == 0: flag += chr(c) break

Bypass character restrictions:

Walrus operator

(abcdef := "new_allowed_chars")

Octal escapes

'\141' = 'a'

Decorator bypass (ast.Call banned, no quotes, no = ):

Decorators = function calls + assignment without ast.Call or =

function.name = strings without quotes

See pyjails.md "Decorator-Based Escape" for full technique

@import @func.class.dict[name.name].get # name extractor def os(): 0

Result: os = import("os")

Z3 Constraint Solving

from z3 import *

flag = [BitVec(f'f{i}', 8) for i in range(FLAG_LEN)] s = Solver() s.add(flag[0] == ord('f')) # Known prefix

Add constraints...

if s.check() == sat: print(bytes([s.model()[f].as_long() for f in flag]))

Hash Identification

By constants:

  • MD5: 0x67452301

  • SHA-256: 0x6a09e667

  • MurmurHash64A: 0xC6A4A7935BD1E995

PyInstaller Extraction

python pyinstxtractor.py packed.exe

Look in packed.exe_extracted/

Marshal Code Analysis

import marshal, dis with open('file.bin', 'rb') as f: code = marshal.load(f) dis.dis(code)

Python Environment RCE

PYTHONWARNINGS=ignore::antigravity.Foo::0 BROWSER="/bin/sh -c 'cat /flag' %s"

Floating-Point Precision Exploitation

Pattern (Spare Me Some Change): Trading/economy games where large multipliers amplify tiny floating-point errors.

Key insight: When decimal values (0.01-0.99) are multiplied by large numbers (e.g., 1e15), floating-point representation errors create fractional remainders that can be exploited.

Finding Exploitable Values

mult = 1000000000000000 # 10^15

Find values where multiplication creates useful fractional errors

for i in range(1, 100): x = i / 100.0 result = x * mult frac = result - int(result) if frac > 0: print(f'x={x}: {result} (fraction={frac})')

Common values with positive fractions:

0.07 → 70000000000000.0078125

0.14 → 140000000000000.015625

0.27 → 270000000000000.03125

0.56 → 560000000000000.0625

Exploitation Strategy

  • Identify the constraint: Need balance >= price AND inventory >= fee

  • Find favorable FP error: Value where x * mult has positive fraction

  • Key trick: Sell the INTEGER part of inventory, keeping the fractional "free money"

Example (time-travel trading game):

Initial: balance=5.00, inventory=0.00, flag_price=5.00, fee=0.05 Multiplier: 1e15 (time travel)

Buy 0.56, travel through time:

balance = (5.0 - 0.56) * 1e15 = 4439999999999999.5 inventory = 0.56 * 1e15 = 560000000000000.0625

Sell exactly 560000000000000 (integer part):

balance = 4439999999999999.5 + 560000000000000 = 5000000000000000.0 (FP rounds!) inventory = 560000000000000.0625 - 560000000000000 = 0.0625 > 0.05 fee ✓

Now: balance >= flag_price ✓ AND inventory >= fee ✓

Why It Works

  • Float64 has ~15-16 significant digits precision

  • (5.0 - 0.56) * 1e15 loses precision → rounds to exact 5e15 when added

  • 0.56 * 1e15 keeps the 0.0625 fraction as "free inventory"

  • The asymmetric rounding gives you slightly more total value than you started with

Red Flags in Challenges

  • "Time travel amplifies everything" (large multipliers)

  • Trading games with buy/sell + special actions

  • Decimal currency with fees or thresholds

  • "No decimals allowed" after certain operations (forces integer transactions)

  • Starting values that seem impossible to win with normal math

Quick Test Script

def find_exploit(mult, balance_needed, inventory_needed): """Find x where selling int(x*mult) gives balance>=needed with inv>=needed""" for i in range(1, 500): x = i / 100.0 if x >= 5.0: # Can't buy more than balance break inv_after = x * mult bal_after = (5.0 - x) * mult

    # Sell integer part of inventory
    sell = int(inv_after)
    final_bal = bal_after + sell
    final_inv = inv_after - sell

    if final_bal >= balance_needed and final_inv >= inventory_needed:
        print(f'EXPLOIT: buy {x}, sell {sell}')
        print(f'  final_balance={final_bal}, final_inventory={final_inv}')
        return x
return None

Example usage:

find_exploit(1e15, 5e15, 0.05) # Returns 0.56

Useful One-Liners

grep -rn "flag{" . strings file | grep -i flag python3 -c "print(int('deadbeef', 16))"

Keyboard Shift Cipher

Pattern (Frenzy): Characters shifted left/right on QWERTY keyboard layout.

Identification: dCode Cipher Identifier suggests "Keyboard Shift Cipher"

Decoding: Use dCode Keyboard Shift Cipher with automatic mode.

Pigpen / Masonic Cipher

Pattern (Working For Peanuts): Geometric symbols representing letters based on grid positions.

Identification: Angular/geometric symbols, challenge references "Peanuts" comic (Charlie Brown), "dusty looking crypto"

Decoding: Map symbols to Pigpen grid positions, or use online decoder.

ASCII in Numeric Data Columns

Pattern (Cooked Books): CSV/spreadsheet numeric values (48-126) are ASCII character codes.

import csv with open('data.csv') as f: reader = csv.DictReader(f) flag = ''.join(chr(int(row['Times Borrowed'])) for row in reader) print(flag)

CyberChef: "From Decimal" recipe with line feed delimiter.

Python Jail: String Join Bypass

Pattern (better_eval): + operator blocked for string concatenation.

Bypass with ''.join() :

Blocked: "fl" + "ag.txt"

Allowed: ''.join(["fl","ag.txt"])

Full payload:

open(''.join(['fl','ag.txt'])).read()

Other bypass techniques:

  • chr()
  • list comprehension: ''.join([chr(102),chr(108),chr(97),chr(103)])
  • Format strings: f"{'flag'}.txt" (if f-strings allowed)

  • bytes([102,108,97,103]).decode() for "flag"

Backdoor Detection in Source Code

Pattern (Rear Hatch): Hidden command prefix triggers system() call.

Common patterns:

  • strncmp(input, "exec:", 5) → runs system(input + 5)

  • Hex-encoded comparison strings: \x65\x78\x65\x63\x3a = "exec:"

  • Hidden conditions in maintenance/admin functions

Cipher Identification Workflow

  • ROT13 - Challenge mentions "ROT", text looks like garbled English

  • Base64 - A-Za-z0-9+/= , title hints "64"

  • Base32 - A-Z2-7= uppercase only

  • Atbash - Title hints (Abash/Atbash), preserves spaces, 1:1 substitution

  • Pigpen - Geometric symbols on grid

  • Keyboard Shift - Text looks like adjacent keys pressed

  • Substitution - Frequency analysis applicable

Auto-identify: dCode Cipher Identifier

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

ctf-osint

No summary provided by upstream source.

Repository SourceNeeds Review
General

write-exploit

No summary provided by upstream source.

Repository SourceNeeds Review
General

ctf-stego

No summary provided by upstream source.

Repository SourceNeeds Review