This kind of famous task. You have board with buttons, wich have 2 positions. In Russia there is old quest game with brother pilots and there was the same task to open the fridge with board 4x4. And there was solution remember all buttons in first position. And switch all this buttons one by one. Repeating this algoritm from 1 to 3 times, you will win.
Also it was kind of this task on phdays quals 2013 (I haven't seen it, but heard about it), and kind of this task on defcon quals 2013, but there was the diffrence. There when you were pushing the button raw and column were reversing but the button you push wasn't
On this ctf there was 4 levels of dificulty of this task. First one is the same a wrote (3 times). Second the same but you need to remeber your steps by yourself(3 times more)
But the most difficult was third part. Orgs have changed the conditions and this time button had 3 positions. That was difficult. After some googling, we found better algorythm for 2 position condition (sorry for russian link). The sense is to build weight matrix. I upgraded it, for more than 2 postions. It was kind of lucky upgrade, I wasn't sure it work. So we build matrix where the cell is (-1)*(sum(raw) + sum(column)) mod N (N=3).
# ar is board transfered to ints [[0,1],[1,0]] def wMatr(ar, N=3): cMax = len(ar[0]) rMax = len(ar) wM = deepcopy(ar) for i, raw in enumerate(ar): for j, column in enumerate(raw): # counting weight for cell, last sub is to remove the dublicate of cell with i,j coords wM[i][j] = (sum(raw) + sum(ar[k][j] for k in xrange(rMax)) - ar[i][j]) % N # reverse the value cell if wM[i][j] != 0: wM[i][j] = N - wM[i][j] return wM
And after that we push the buttons according to that matrix. After first applying of this algorytm, we get board with the same raws like:
1111
2222
1111
0000
After applying it more than one time, we get the right answer. But that decision is not optimal. And sometimes, it need too many attemps. But it wroked 90% of times.
The last 4th task was kind of boss, it was board with 2 postitions but with size 200x200. There were some problems with connection, so my script sometimes couldn't get the full board. But after over9000 attemps it worked
Full code of the solution:
import re from socket import create_connection from copy import deepcopy from time import sleep host = "54.198.73.164" host = "54.81.138.191" port = 5555 hSock = create_connection((host, port)) ans = hSock.recv(10240) def invert2(x, y, ar, N=3): t = ar[x][y] for i in range(len(ar[0])): ar[x][i] = (ar[x][i] + 1) % N for i in range(len(ar)): ar[i][y] = (ar[i][y] + 1) % N ar[x][y] = (t+1) % N return ar repl = { 2: { "O": 0, "X": 1 }, 3: { "O": 0, "W": 1, "X": 2 } } def serv(): for asd in range(10000): if asd == 0 or "Lupin hear a sound from safebox" in ans: sleep(1) ans = hSock.recv(102400) print ans x, y = map(int, re.findall("Board>\s+(\d+)\s+(\d+)", ans)[0]) ar = ans.split("\n")[-x-1:-1] N = len(set("".join(ar))) ar = map(list, ar) for i in range(len(ar)): for j in range(len(ar[0])): ar[i][j] = repl[N][ar[i][j]] mine = deepcopy(ar) while True: sleep(1) wM = wMatr(mine, N) for i, raw in enumerate(wM): for j, column in enumerate(raw): for k in range(column): mine = invert2(i, j, mine, N) hSock.send("%s %s\n" % (i, j)); ans = hSock.recv(102400) if len(ans) > 5: print ans #print "\n".join("".join(map((str), c)) for c in mine), "\n" if "Lupin hear a sound from safebox. some layout of button changed" in ans: break if "Too many attempts" in ans: exit(0) if set("".join("".join(map((str), c)) for c in mine)) == set(["0"]): break print hSock.recv(10240) def wMatr(ar, N=3): cMax = len(ar[0]) rMax = len(ar) wM = deepcopy(ar) for i, raw in enumerate(ar): for j, column in enumerate(raw): wM[i][j] = (sum(raw) + sum(ar[k][j] for k in xrange(rMax)) - ar[i][j]) % N if wM[i][j] != 0: wM[i][j] = N - wM[i][j] return wM serv()
Finally we receive message with flag:
Lupin hear a sound from safebox. some layout of button changed There is a beep sound from safebox. we might be on the right way. Some strange noise come out from the safebox.. ' ' ' ' ' ' ' ' ' ' \ ' / ' ' . .-"```"-. . ' \`-._.-`/ - - = \\ | // = - - ' \\|// ' . ' \|/ ' . . ' ` ' . . / . \ . . . . Congrats!!!! Lupin finally got the Cherry Saphhire!! Right behind of the jewel, Lupin found a short memo ----------------------------------------------------- The flag is "THE BEST people are always TAKEN, if you don't STEAL them, you won't HAVE them" (without quote)
So, THE BEST people are always TAKEN, if you don't STEAL them, you won't HAVE them