pawnfish
# Description
Info:
Fishes are pretty good at chess. nc pawnfish.chal.uiuc.tf 1337
File: handout.tar.gz
TL;DR:
Look around the source code => We have to win 100 times and the current_player
is Black
to get the flag.
wins
variable is signed char
=> We can lose a lot in order to make wins
equals to 100, but what about current_player
?
We have to win a game to turn current_player
to Black
. The file also use stockfish engine => Can’t win easily, we have to find some bugs and take those advantages to win.
Find En Passant
bugs => Find a way to win, put all the things together to get the flag.
# Plan
First of all, I think this is more like a Misc
than RE
challenge, because you need quite chess knowledges to solve this challenge.
The file gave us source code and some files related to chess stuff, so I just check chal.c
. This is a very long source code, I immidiately check the condition to get the flag:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (current_player == Black) {
FILE* flag;
int c;
flag = fopen("flag.txt", "r");
if (flag) {
while ((c = getc(flag)) != EOF) {
putchar(c);
}
putchar('\n');
fclose(flag);
} else {
puts("Flag is missing :/");
}
} else {
puts("How is this possible?? You didn't win the 100th game!");
puts("I won't stand a cheater!!!");
exit(96);
}
And looking around main functions. I know that we also need to make wins
equals 100 to escape the while loop and come to our check condition:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main() {
...
while (wins != 100 || current_player == White) {
...
if (current_player == Black) {
FILE* flag;
int c;
flag = fopen("flag.txt", "r");
if (flag) {
while ((c = getc(flag)) != EOF) {
putchar(c);
}
putchar('\n');
fclose(flag);
}
...
For the wins
condition, we just need to lose a lot, enough to make the wins
equals to 100, that’s the easy part. The hard part is to make current_player
equals to Black
. In order to do that, we have to win a game. But this is stockfish engine, you need Hikaru Nakamura
to defeat this to get us the flag. After a while, I think there has to be some bugs around…
# The Bug
… and indeed, there is. After spending a lot of time to debug, my teammate find the En Passant
flaw: the En Passant
is meant to apply just for pawn. But for some weird reasons, this program applies En Passant
to literally every chess pieces.
This is huge, we can slowly build our way to defeat this engine. After several tries, we finally win one game, and using everything we’ve known so far to write a script:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
from pwn import *
p = remote('pawnfish.chal.uiuc.tf', 1337)
def send_piece(mov1, mov2):
p.recv()
p.sendline(mov1)
p.recv()
p.sendline(mov2)
for i in range(157):
print(i)
send_piece('e2','e4')
send_piece('e1','e2')
send_piece('e2','e3')
send_piece('e3','f4')
send_piece('f4','e5')
p.recvuntil('lose')
p.recvline()
send_piece('e2','e4')
send_piece('c2','c3')
send_piece('e4','e5')
send_piece('e5','d6')
send_piece('g1','f3')
send_piece('d2','d4')
send_piece('c3','d4')
send_piece('d4','e5')
send_piece('f1','e2')
send_piece('e1','g1')
send_piece('e5','d6')
send_piece('h2','h3')
send_piece('e2','f3')
send_piece('d6','c7')
send_piece('f1','e1')
send_piece('c1','e3')
send_piece('d1','e2')
send_piece('e3','c5')
send_piece('e2','e7')
send_piece('e1','e7')
send_piece('e7','a7')
send_piece('a2','a4')
send_piece('a4','b5')
send_piece('b1','c3')
send_piece('b5','b6')
send_piece('b6','b7')
send_piece('a7','a8')
send_piece('f3','b7')
send_piece('a1','b1')
send_piece('b2','b4')
send_piece('c3','a2')
send_piece('b4','b5')
send_piece('b5','b6')
send_piece('a8','a7')
send_piece('a2','c3')
send_piece('c3','d5')
send_piece('d5','e7')
send_piece('e7','c6')
send_piece('b6','b7')
send_piece('h3','g4')
send_piece('g4','f5')
send_piece('b7','b8')
send_piece('b1','b8')
send_piece('g1','h2')
send_piece('b8','f8')
send_piece('f5','f6')
send_piece('h2','h3')
send_piece('g2','g4')
send_piece('h3','g3')
send_piece('c6','e7')
send_piece('f8','d8')
send_piece('a7','c7')
send_piece('e7','d5')
send_piece('d8','b8')
send_piece('f6','f7')
send_piece('c7','a7')
p.interactive()
And the answer:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
$ python3 solve.py
[+] Opening connection to pawnfish.chal.uiuc.tf on port 1337: Done
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
[*] Switching to interactive mode
Location to > Moving WHITE ♖ from row: 1, col: 2, TO row: 1, col: 0
You win :)
uiuctf{strange_the_only_winning_move_is_to_lose}
uiuctf{strange_the_only_winning_move_is_to_lose}