RowdyHacks XII: exact change
A 250-point reversing challenge: reconstructing a JAR's hidden service command by reproducing its coin-reconciliation algorithm to derive the service code.
Challenge
Reversing · 250 points. The ZIP contains a Java JAR (a vending/coin service) and
a five-sale shift slip. Running the documented status command confirms five
reconciled sales and one penny left over.
Finding the hidden command
Bytecode inspection (javap / a decompiler) reveals an undocumented
service <slip> <code> command gated behind a computed code. The code is derived
by replaying the business logic:
- Reconcile each sale in order.
- For each, make exact change with the fewest coins available, favoring larger denominations on ties.
- Subtract those coins from the tubes.
- Mix the sale details and dispensed coin counts into a rolling 16-bit state, emitting two base-36 characters per sale.
Reproducing that over the slip yields the service code 3O2WCO5E3W, and the
remaining tubes [0, 0, 0, 1] match the JAR's own status output, a good
cross-check that the reimplementation is faithful before trusting the code.
Solution
java -jar exact-change.jar service shift-v39.txt 3O2WCO5E3W
The service command prints the flag.
Takeaway
Hidden commands and computed "secret" codes inside shipped bytecode are not security: Java decompiles cleanly and any deterministic algorithm can be re-derived and replayed, which is how the service code came out. Secrets and privileged operations belong server-side behind real authorization, never behind obscurity in a client artifact.
Flag
Spoiler: show the flag
rowdy{c0ins_d0nt_f0ll0w_gr33dy}