Rating:
# CSAW 2018 Qualifier - McGriddle
> Forensics - 43 Solves
> mcgriddle
>
> All CTF players are squares
>
> Edit (09/14 8:22 PM) - Uploaded new pcap file
>
> Edit (09/15 12:10 AM) - Uploaded new pcap file
`final.pcap` contains 204 HTTP sessions to http://red-dev.csaw.io:5000 alternating between:
* POST requests to `/move` where the request and response both contain chess moves, e.g.:
```http
POST /move HTTP/1.1
Host: red-dev.csaw.io:5000
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: python-requests/2.19.1
Content-Length: 8
Content-Type: application/x-www-form-urlencoded
move=Nf6
```
```http
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 2
Server: Werkzeug/0.14.1 Python/3.5.2
Date: Sat, 15 Sep 2018 02:45:32 GMT
d4
```
* POST requests to `/image` uploading an SVG image depicting an 8x8 grid of characters, e.g.:
```http
POST /image HTTP/1.1
Host: red-dev.csaw.io:5000
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: python-requests/2.19.1
Content-Length: 740
Content-Type: multipart/form-data; boundary=6ff49c0c503791a4d8f5342e01f77fee
--6ff49c0c503791a4d8f5342e01f77fee
Content-Disposition: form-data; name="media"; filename="2.svg"
<svg baseProfile="full" height="100" version="1.1" width="100" xmlns="http://www.w3.org/2000/svg" xmlns:
ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink"><defs /><g font-size="
14"><text x="4" y="20">H q 7 J u w d i </text><text x="4" y="30">r 0 M u q N w 2 </text><text x="4" y="4
0">W F t I G 3 1 h </text><text x="4" y="50">c 3 N h I H N 1 </text><text x="4" y="60">c 2 N I p c G l <
/text><text x="4" y="70">0 I G N 1 D c n </text><text x="4" y="80">o Q v N Z Z L w </text><text x="4" y=
"90">l U k r H 5 1 T </text></g></svg>
--6ff49c0c503791a4d8f5342e01f77fee--
```
```http
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 6
Server: Werkzeug/0.14.1 Python/3.5.2
Date: Sat, 15 Sep 2018 02:45:32 GMT
Noted.
```
Sessions can be extracted on the command line using a tool such as `tshark`.
The moves can be extracted and combined into a valid PGN format chess game (once the urlquoted characters such as `%2B` are converted back to ascii):
```
1. Nf3 Nf6 2. d4 e6 3. Nc3 d5 4. Bg5 Bb4 5. e3 h6 6. Bxf6 Qxf6 7. Bb5+ Bd7 8. O-O O-O 9. Ne5 Qe7 10. Bd3 Nc6 11. Nxd7 Qxd7 12. Ne2 Qe7 13. c4 dxc4 14. Bxc4 Qh4 15. Rc1 Rfd8 16. Ng3 a6 17. f4 Bd6 18. Ne4 Kh8 19. Nxd6 Rxd6 20. Be2 Qd8 21. Qb3 Rb8 22. Rf2 Ne7 23. Bh5 Kg8 24. Qd3 Nd5 25. a3 c6 26. Bf3 Qe7 27. Rfc2 Rc8 28. Rc5 Re8 29. Qd2 Qf6 30. Be4 h5 31. Qe2 h4 32. Qf3 Rd7 33. Bd3 Red8 34. Re1 Kf8 35. Qh5 Nxf4 36. exf4 Qxd4+ 37. Kh1 Qxd3 38. Qh8+ Ke7 39. Qxh4+ Kd6 40. Rc3 Qd2 41. Qg3 Kc7 42. f5+ Kc8 43. fxe6 fxe6 44. Rce3 Qxb2 45. Rxe6 Rd1 46. h3 Rxe1+ 47. Rxe1 Qf6 48. a4 Qf7 49. a5 Rd5 50. Qg4+ Kb8 51. Qg3+ Ka8 52. Re5 Qd7 53. Kg1 Ka7 54. Kh2 Rb5 55. Rxb5 axb5 56. Qe3+ Kb8 57. Qc5 Kc7 58. Kg1 Qd1+ 59. Kf2 Qd6 60. Qc3 Qf8+ 61. Kg1 b6 62. Qd4 Qc5 63. Qxc5 bxc5 64. Kf2 Kb7 65. Ke3 Ka6 66. h4 Kxa5 67. h5 c4 68. Kd2 Kb4 69. g4 Kb3 70. g5 Kb2 71. Ke2 c3 72. h6 gxh6 73. gxh6 c2 74. h7 c1=Q 75. h8=Q+ Qc3 76. Qf8 b4 77. Qf4 Qc2+ 78. Kf3 b3 79. Qd6 c5 80. Ke3 c4 81. Qe6 Qd3+ 82. Kf4 c3 83. Qe5 Ka3 84. Qa5+ Kb2 85. Qe5 Kc1 86. Qc5 b2 87. Qg1+ Kd2 88. Qg2+ Kd1 89. Qg4+ Kc2 90. Qg1 Qd6+ 91. Ke4 Qb4+ 92. Kf3 Qb7+ 93. Kf4 b1=Q 94. Qe3 Kb3 95. Kg5 Qd5+ 96. Kf4 Qbf5+ 97. Kg3 Qd6+ 98. Kg2 Qd2+ 99. Qxd2 cxd2 100. Kg1 d1=Q+ 101. Kg2 Qd2+ 102. Kg3 Qdf2#
```
This game can be replayed using an application such as ChessX or online, e.g. http://www.caissa.com/chess-tools/chess-game-viewer.php
The character grids can be extracted from the svg files giving 102 8x8 arrays like the one below:
```
m S 8 Q G Y / U
G a s V d r Z d
C l B l b G x l
b n R l c 3 F 1
Z S B s Y W 9 y
Z W V 0 I y G l
9 P j U S V 0 8
t 7 x I e o h V
```
A quick visual inspection shows that the characters are alphanumeric with `+` and `/` characters. The characters `= =` can be seen in session 193 suggesting that the data is base64 encoded:
```
c j N h T E x M
e V 9 o Y X Q z
X 2 N o Z X N z
X 3 R Z i 8 a H
0 K C g = = C l
B E F l T b Y G
x l b n R l c 3
F 1 Z S B s Y W
```
Base64 decoding this board shows what appears to be a snippet of a flag but also gives errors, suggesting that more work is required:
```bash
# cat 193.out | tr -d ' ' | base64 -d | xxd -c 8
00000000: 7233 614c 4c4c 795f r3aLLLy_
00000008: 6861 7433 5f63 6865 hat3_che
00000010: 7373 5f74 598b c687 ss_tY...
00000018: d0a0 a0 ...
base64: invalid input
```
Decoding other boards gives snippets of latin text, with the first board giving errors at the beginning and end which appear to correspond to the starting positions of the peices on the board - could this be a clue?
```bash
# cat 001.out
m S 8 Q G Y / U
G a s V d r Z d
C l B l b G x l
b n R l c 3 F 1
Z S B s Y W 9 y
Z W V 0 I y G l
9 P j U S V 0 8
t 7 x I e o h V
# cat 001.board
r n b q k b n r
p p p p p p p p
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . N . .
P P P P P P P P
R N B Q K B . R
# base64 -d <<< ClBlbGxlbnRlc3F1ZSBsYW9yZWV0IGlh
Pellentesque laoreet ia
```
That seems promising.
We can use the `python-chess` library to replay the chess game, generating the peice locations after each move, e.g.:
```python
import chess
...
board = chess.Board()
for move in moves:
board.push_san(move)
print board
```
We can then apply the empty spaces on the board to the character grids we extracted from the SVG files, which works for the first six grids but then starts to throw regular errors after that. Here is the board layout and svg grid characters for the first seven moves and the resulting `base64 -d` output:
```bash
rnbqkbnrpppppppp.............................N..PPPPPPPPRNBQKB.R
mS8QGY/UGasVdrZdClBlbGxlbnRlc3F1ZSBsYW9yZWV0IyGl9PjUSV08t7xIeohV
rnbqkb.rpppppppp.....n.............P.........N..PPP.PPPPRNBQKB.R
Hq7Juwdir0MuqNw2WFtIG31hc3NhIHN1c2NIpcGl0IGN1DcnoQvNZZLwlUkrH51T
rnbqkb.rpppp.ppp....pn.............P......N..N..PPP.PPPPR.BQKB.R
NgEZSqbB33VzS9kaBsYWmZN1cy4gQ3JhcyBdhIHBvce3VFlc/n/mayMITUwHVKgp
rnbqkb.rppp..ppp....pn.....p..B....P......N..N..PPP.PPPPR..QKB.R
PqDGQQIib88FBw5zoYXN4xlbGx1WcyXBjb2D5zZWN0MZXQR1D08cOJz0JiBZyZpn
rnbqk..rppp..ppp....pn.....p..B..b.P......N.PN..PPP..PPPR..QKB.R
GfkwhbHn+G8VtxszIHN1ijc2Npc1GlS0LVCyBsYWN19clMyB9PmldT7tpSBy8Gma
rnbqk..rppp..pp.....pB.p...p.....b.P......N.PN..PPP..PPPR..QKB.R
LWNxocyffs+BlWGbmltITpHdZhccml1cyxBjqdXN0bVyIJwg3EFYSOMn4B2RtVaV
rnb.k..rppp..pp.....pq.p.B.p.....b.P......N.PN..PPP..PPPR..QK..R
p731rbmnY9LMgI+dWx0cghmglRjDaWVzI4HZN1c2NpAcDUGlSCe0IbPiyG9uBkaf
```
```
Pellentesque laoreet iauam massa suscipit cursum lacus. Cras a posuere Phasellus consectetur ilum suscipit, lacus eu fs enim varius justo, a vkV�2V�G&�6�W27W66��B�Fbase64: invalid input
```
Maybe I'm on the right track? Let's try it on the layout/grid for session 193:
```bash
...........................q.q...........kp.Q.K.................
cjNhTExMeV9oYXQzX2NoZXNzX3RZi8aH0KCg==ClBEFlTbYGxlbnRlc3F1ZSBsYW
```
```
r3aLLLy_hat3_chess_tbh}
Pellentesque labase64: invalid input
```
That's half a flag. Unfortunately I do not get the same success from the previous session:
```
...........................q.........K...kp.Q............q......
IHB1cnVzLCB2ZWwgYXVjdG9yIG53lcXVlIG51GbGxjbhcIGF0IGVyYXQu8IFNlZC
```
```
purus, vel auctor neque nulla at erat. Sedbase64: invalid input
```
Further investigation fails to find any trace of the rest of the flag. At this point it appears that the challenge might be bugged - this is their third version of the PCAP file after all.
The second version of the pcap file - `output.pcap` - contains the same character grid we previously saw in session 193, this time in session 289. The previous SVG file appears to contain more of the flag:
```bash
# less 287 | tr -d ' \n' | base64 -d
ƗVWB�WGW2WR�W}�s.
dY����{3y3_actuAllY_
```
Remember, however that this file was replaced and when we look at the chess moves we see why: each POST request to `/move` seems to repeat the move returns from the previous response and the sequence gets to `O-O` and then gets stuck in a loop, repeating that move for the rest of the pcap file so the game looks like `1. Nf3 Nf6 2. d4 e6 3. Nc3 d5 4. Bg5 Bb4 5. e3 h6 6. Bxf6 Qxf6 7. Bb5+ Bd7 8. O-O O-O 9. O-O O-O 10. ...`
The SVG grids are also different - there are two POSTS to `/image` for each POST to `/move` giving us a total of 204 grids which would suggest there is a grid for each move in the chess game. If we use the game from `final.pcap` we can guess that the board layout for the grid in `output.pcap` session 287 should be:
```
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . q . q . .
. . . . . K . .
. k p . Q . . .
. . . . . . . .
. . . . . . . .
```
Which we can combine with the grid and decode with `base64 -d` to get...
```
...........................q.q.......K...kp.Q...................
BhbGlxdWV0IG1ldHVzIGV1IG1ld9HtVzLiAKZFmxhbUZn3szeTNfYWN0dUFsbFlf
```
```
����ՕЁ����́�ԁ����̸�)��������}������ebase64: invalid input
```
...an error? Don't worry - it's just an alignment issue, if we drop 3 characters from the front of the string we get:
```bash
# base64 -d <<< bGlxdWV0IG1ldHVzIGV1IG1ldHVzLiAKZmxhZ3szeTNfYWN0dUFsbFlf
liquet metus eu metus.
flag{3y3_actuAllY_
```
and the output of sessions 287 and 289 combined give:
```
...........................q.q.......K...kp.Q...................
BhbGlxdWV0IG1ldHVzIGV1IG1ld9HtVzLiAKZFmxhbUZn3szeTNfYWN0dUFsbFlf
...........................q.q...........kp.Q.K.................
cjNhTExMeV9oYXQzX2NoZXNzX3RZi8aH0KCg==ClBEFlTbYGxlbnRlc3F1ZSBsYW
```
```
liquet metus eu metus.
flag{3y3_actuAllY_r3aLLLy_hat3_chess_tbh}
Pellentesque labase64: invalid input
```
Full credit to the 43 teams who solved it on the day - we only figured it out afterwards.