hardwarefreemedium

Project Power Challenge Scenario

hackthebox

Task: recover an AES-128 key from a remote embedded device that exposes chosen-plaintext power traces over a socket. Solution: apply first-round AES CPA with a Hamming-weight leakage model, recover the key from 800 traces, then submit it to receive the flag.

$ ls tags/ techniques/
correlation_power_analysishamming_weight_modelfirst_round_aes_key_recovery

Project Power Challenge Scenario — hackthebox

Description

Project Power Challenge Scenario

The provided artifacts were a Python socket client and a lab layout image. The goal was to recover the embedded device's AES-128 key and use it against the live instance at 154.57.164.74:31688.

Analysis

At first glance this looked like a remote exploitation challenge, but the supplied interface was not a memory-corruption target. socket_interface.py exposed a much more direct side channel:

  • option 1: send a 16-byte plaintext and receive a base64-encoded NumPy power trace
  • option 2: send a 32-hex-char AES-128 key and receive the flag if the key is correct

remote_lab_layout.png clarified the architecture: plaintext is sent to the embedded device, an oscilloscope captures the AES power consumption, and Laptop-2 forwards the trace back over the socket. That makes this a standard AES side-channel problem, not a pwn or reverse challenge.

The useful prior-art match was CTFBase writeup 20260123_0xl4ugh_sca1, which used classic Correlation Power Analysis (CPA) against AES. The right first-round leakage model here was:

HW(SBOX[plaintext[i] XOR key[i]])

CPA works because the real power trace contains samples that correlate with the number of switching bits in this intermediate AES state. For each key-byte guess 0..255, we compute the hypothetical Hamming weights across many chosen plaintexts and measure which guess correlates best with the observed traces. The correct key byte stands out with the highest correlation.

Live collection confirmed that traces decoded as float64 arrays of length 1042, and 800 traces were already enough for a clean recovery. Alternate leakage models and dtype overrides were unnecessary.

Solution

  1. Read socket_interface.py and identify the two menu options: trace oracle and key submission.
  2. Use the layout image to confirm the side-channel path: embedded AES device -> oscilloscope -> socket-delivered NumPy traces.
  3. Implement first-round AES CPA in project_power_solver.py using the Hamming-weight model of SBOX[PT ^ K] for each byte position.
  4. Collect 800 live traces and plaintexts from the target.
  5. Correlate all 256 guesses for each of the 16 key bytes against the trace matrix.
  6. Reconstruct the AES-128 key and submit it with socket option 2.

Minimal run command:

python3 project_power_solver.py \ --host 154.57.164.74 \ --port 31688 \ --count 800 \ --save /Users/sergeyskorobogatov/Projects/Agents/CTF/tasks/hackthebox/project-power/live_traces_800.npz \ --submit

This recovered:

  • AES-128 key: 35425203F4BF23C7F93444BF772F2E1F
  • Flag: HTB{51d3_ch4nn31_c4n_8234k_3v3n_7h3_m057_53cu23_d3v1c35!@^5%2}

Non-needed paths:

  • pwn/reverse-style service exploitation was unnecessary
  • alternate leakage models were unnecessary
  • dtype override experimentation was unnecessary once float64 decoding was confirmed

$ cat /etc/motd

Liked this one?

Pro unlocks every writeup, every flag, and API access. $9/mo.

$ cat pricing.md

$ grep --similar

Similar writeups