Hackergame2022 Writeup
还有很多可写的 math 题,被各种琐事缠身没有空去继续打,非常可惜。
Xcaptcha
使用 js 来模拟表格的填写并提交表格。
首先解析 html 格式,然后用 DOM 来获取内容并填写表格
var inputs = document .getElementsByTagName ("input" )var labels = document .getElementsByTagName ("lable" )for (let index = 0 ; index < 3 ; index++) { console .log (inputs[index].value ) console .log (labels[index].innerText ) let text = labels[index].innerText let reg = /(\d+)\+(\d+)/ let mt = text.match (reg) let num = BigInt (mt[1 ]) + BigInt (mt[2 ]) let str = String (num) inputs[index].value = str }
蒙特卡罗轮盘赌
观察代码发现随机数种子是跟当前时间戳相关的。可以通过乱猜得到前两个的值,然后在时间戳附近找到随机数种子就能求出后面的三个值。
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 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> double rand01 () { return (double )rand () / RAND_MAX; }char guess[2 ][10 ] = {"3.14155" , "3.14656" };unsigned int mid =1666722488 ; int check (unsigned seed) { srand (seed); int games = 2 ; int win = 0 ; int lose = 0 ; char target[20 ]; int cnt = 0 ; for (int i = 0 ; i < games; i++) { int M = 0 ; int N = 400000 ; for (int j = 0 ; j < N; j++) { double x = rand01 (); double y = rand01 (); if (x*x + y*y < 1 ) M++; } double pi = (double )M / N * 4 ; sprintf (target, "%1.5f" , pi); if (strcmp (target, guess[i]) == 0 ) { } else return 0 ; } return 1 ; }void getAns (unsigned int seed) { srand (seed); int games = 5 ; int win = 0 ; int lose = 0 ; char target[20 ]; for (int i = games; i > 0 ; i--) { int M = 0 ; int N = 400000 ; for (int j = 0 ; j < N; j++) { double x = rand01 (); double y = rand01 (); if (x*x + y*y < 1 ) M++; } double pi = (double )M / N * 4 ; sprintf (target, "%1.5f" , pi); printf ("%1.5f " , pi); } }int main () { guess[0 ][7 ] = guess[1 ][7 ] = 0 ; setvbuf (stdin, NULL , _IONBF, 0 ); setvbuf (stdout, NULL , _IONBF, 0 ); setvbuf (stderr, NULL , _IONBF, 0 ); unsigned int ans; for (unsigned int i = mid - 2000 ; i <= mid + 2000 ; ++i) { if (check (i)) { printf ("ok %d\n" , i); ans = i; break ; } } getAns (ans); return 0 ; }
企鹅拼盘
前两题,枚举所有的可能,总共有2 16 2^{16} 2 1 6 种可能性
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 import jsonclass Board : def __init__ (self, branches ): self.b = [[i*4 +j for j in range (4 )] for i in range (4 )] self.branches = branches def _blkpos (self ): for i in range (4 ): for j in range (4 ): if self.b[i][j] == 15 : return (i, j) def reset (self ): for i in range (4 ): for j in range (4 ): self.b[i][j] = i*4 + j def move (self, moves ): for m in moves: i, j = self._blkpos() if m == 'L' : self.b[i][j] = self.b[i][j-1 ] self.b[i][j-1 ] = 15 elif m == 'R' : self.b[i][j] = self.b[i][j+1 ] self.b[i][j+1 ] = 15 elif m == 'U' : self.b[i][j] = self.b[i-1 ][j] self.b[i-1 ][j] = 15 else : self.b[i][j] = self.b[i+1 ][j] self.b[i+1 ][j] = 15 def __bool__ (self ): for i in range (4 ): for j in range (4 ): if self.b[i][j] != i*4 + j: return True return False def solve (self, inbits ): self.reset() for branch in self.branches[:]: self.move(branch[1 ] if inbits[branch[0 ]] else branch[2 ]) return self.__bool__()def chal (bitlength, obf ): filename = f'chals/b{bitlength} {"_obf" if obf else "" } .json' with open (filename) as f: branches = json.load(f) global success_flag success_flag = 0 board = Board(branches) num = [x for x in range (2 **16 )] strs = ['{0:016b}' .format (x) for x in num] inbits = [list (map (int , str )) for str in strs] for inbit in inbits: if board.solve(inbit) == True : print (inbit) break chal(16 , True )