Hackergame2022 Writeup

Hackergame2022 Writeup

还有很多可写的 math 题,被各种琐事缠身没有空去继续打,非常可惜。

Xcaptcha

使用 js 来模拟表格的填写并提交表格。
首先解析 html 格式,然后用 DOM 来获取内容并填写表格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);
// printf("%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;
// disable buffering
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;
}

企鹅拼盘

前两题,枚举所有的可能,总共有2162^{16}种可能性

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 json

class 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
# print(inbit)



# chal(4, False)
chal(16, True)

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!