Category: offline data analysis · Artifacts: notes.txt, aps.conf, run.log, scan_export.csv
The scoring rule (reconstructed from the files)
notes.txt states the idea; run.log is the single good run of the (now lost) tracker.py
and leaks the one number that was deliberately left out of the notes:
- "moving" filter - from
run.logfor CafeDelMundo:step_delta=40 -> stationary, droppedbutstep_delta=41 -> moving, kept. Cutoff: keep only rows withstep_delta >= 41. - per-AP score - sum over kept rows of
signal * weight, where weight comes fromaps.conf:FoxgloveCoffee_Guest=3,HomePlex_5G=2,CafeDelMundo=2,NETGEAR-8841=1. (Check: CafeDelMundo kept rows 58+60+64=182, x2 = 364, exactly thesubtotal = 364inrun.log; HomePlex_5G kept row 87, x2 = 174 = the loggedsubtotal = 174.) - Only APs listed in
aps.confcount; everything else in the export is ignored.
Solve
1python3 - <<'EOF'
2import csv
3W = {'FoxgloveCoffee_Guest':3,'HomePlex_5G':2,'CafeDelMundo':2,'NETGEAR-8841':1}
4sc = {k:0 for k in W}
5for r in csv.DictReader(open('scan_export.csv')):
6 if r['ap_name'] in W and int(r['step_delta']) >= 41:
7 sc[r['ap_name']] += int(r['signal']) * W[r['ap_name']]
8print(sorted(sc.items(), key=lambda x: -x[1]))
9EOF
10# [('FoxgloveCoffee_Guest', 1044), ('CafeDelMundo', 364), ('NETGEAR-8841', 240), ('HomePlex_5G', 174)]
The traps work exactly as advertised: HomePlex_5G is the loudest AP (signal 87-92) and
also the most frequent (10 rows), but you are almost never moving there (1 kept row),
so it finishes last. FoxgloveCoffee_Guest - the place the person keeps returning to -
wins by a wide margin.
Flag
hiCTF{FoxgloveCoffee_Guest}