$ cat writeup.md…
$ cat writeup.md…
alfactf
Task: a public Google Sheet exposed a fake provisioning terminal backed by hidden worksheets and formula-driven validation. Solution: reverse the affine checker in s1 to recover the password xlmatrix, regenerate the s2 keystream, XOR-decode s3, and render the 80x26 bitmap to read the flag.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Учёт провизии
ТЕРМИНАЛ УЧЕТА ПРОВИЗИИ
ДОСТУП ЗАПРЕЩЕН
English summary: the challenge is a public Google Sheets document that behaves like a terminal. Exporting it as XLSX reveals that the visible Panel sheet is only the front-end, while the real logic lives in hidden sheets s1, s2, and s3.
After exporting the spreadsheet as export.xlsx, the workbook contains:
Panel — visible terminal UIs1 — password validation logics2 — state update / keystream generators3 — XOR output and bitmap bytesThe visible sheet already tells us what must happen. Panel!B11 is:
=IF(AND(COUNTIF('s1'!$B$4:$I$4,1)=8,COUNTIF('s1'!$J$14:$Q$14,1)=8),"ДОСТУП РАЗРЕШЕН","ДОСТУП ЗАПРЕЩЕН")
So the password must satisfy two conditions:
s1!J12:Q12 must equal the target in s1!A18:H18.The fake terminal is not text output. The panel cells use formulas of the form:
=BITAND(BITRSHIFT(INDEX('s3'!$P$2:$Y$27,ROW()-13,QUOTIENT(COLUMN()-2,8)+1),7-MOD(COLUMN()-2,8)),1)
This means Panel is unpacking bits from the bytes stored in s3!P2:Y27. Since that area is 26 rows by 10 bytes, the final message is an 80 x 26 monochrome bitmap.
s1s1 first maps input letters through A23:B48, which is just the lowercase alphabet to ASCII table (a -> 97, ..., z -> 122). Invalid characters become 0, which immediately fails the first gate.
The second gate is more interesting. The sheet builds three layers modulo 251:
J8:Q8 from the input vector and matrix O30:V37, plus constants E30:L30J10:Q10 from the previous layer, matrix X30:AE37, matrix AG30:AN37, plus constants E31:L31J12:Q12 from matrix AP30:AW37, matrix AY30:BF37, helper values from B6:D6, mixing constants in E34:L36, plus constants E32:L32...
$ grep --similar