腾讯极客技术挑战赛-第三期 参赛记录

这几天参加了腾讯极客技术挑战赛-第三期。经历五天挑战,通关挑战,取得第五名。

比赛地址 : http://geek.qq.com/tree

img

最终成绩:

[TOC]

比赛介绍(摘自比赛官网)

极客技术的乐趣,不仅在于满足我们对这个世界刨根问底的探索欲,还在于它能帮助实现很多有意义、有温度的事情。而日益严峻的气候变化与全球变暖,是人类社会面临的一个共同挑战。随着我国提出碳达峰及碳中和的目标,各行各业也在加快推进碳中和规划。而碳中和目标的最终实现,离不开科技的创新和各界的长期努力。

因此,在植树节来临之际,腾讯安全平台部联合腾讯公益、TEG办公室共同发起本期赛题,除了期望为技术爱好者提供一个技术切磋的平台,也希望通过线上线下联动的方式,呼吁和激发更多人参与到低碳环保行动中来,承担起作为互联网科技从业者的社会责任使命与善为担当。比赛结束后,主办方也将线上种树结果转化为线下真正的生态绿荫,在深圳大鹏坝光白沙湾开展滨海流域生态保育工作,为减少地球碳排放贡献一份力量。

赛题描述

本期的比赛秉承了极客技术挑战赛的一贯传统,它非常简单,几乎不需要写代码,你只需要简单地点击最下方种树按钮就可以了,最终谁种的树最多,谁就是冠军!

比赛截止后,种下的树数量越多排名越靠前,如遇数量相同,则按照到达该数量的时间排名。

比赛说明

参加比赛需要使用现代化的浏览器,比如 Chrome / Edge 等,不支持 IE6 等老古董。

为了比赛公平,禁止对比赛机器进行渗透和 DDOS。

PS:成功种一棵树后才能继续种下一棵树,因此开多线程并行刷接口没有意义。

PPS:手速够快可获得神秘力量,倘若你能在一秒之内能种下多棵树,会触发加速BUFF。

PPPS:排行榜是异步更新的,需要稍等一会儿才能看到成功种下的数量。

比赛记录

比赛的形式很简单,点击种树按钮,发送 pull 请求,服务器下发一个 JS 文件名和参数 a,t。

t 是选手的 token,a 作为参数传入 JS 中,JS 经过计算返回答案,将答案与 token push 到服务器。服务器验证正确后,将分数 +1。如果连续提交正确的答案,分数会提升速度会提高100倍。

level 1 - 签到

签到,熟悉环境:

1
window.A274075A=async function({a}){return new Promise(_=>setTimeout(__=>_(a[0]),2000))}
1
2
def calc(a):
return a

level 2 - 白给

白给:

1
2
def calc(a):
return a*a+a

level 3 - 逆元

1
eval(atob("dmFyIF8weGU5MzY9WydBNTQ3Mzc4OCddOyhmdW5jdGlvbihfMHg0OGU4NWMsXzB4ZTkzNmQ4KXt2YXIgXzB4MjNmYzVhPWZ1bmN0aW9uKF8weDI4NThkOSl7d2hpbGUoLS1fMHgyODU4ZDkpe18weDQ4ZTg1Y1sncHVzaCddKF8weDQ4ZTg1Y1snc2hpZnQnXSgpKTt9fTtfMHgyM2ZjNWEoKytfMHhlOTM2ZDgpO30oXzB4ZTkzNiwweDE5NikpO3ZhciBfMHgyM2ZjPWZ1bmN0aW9uKF8weDQ4ZTg1YyxfMHhlOTM2ZDgpe18weDQ4ZTg1Yz1fMHg0OGU4NWMtMHgwO3ZhciBfMHgyM2ZjNWE9XzB4ZTkzNltfMHg0OGU4NWNdO3JldHVybiBfMHgyM2ZjNWE7fTt3aW5kb3dbXzB4MjNmYygnMHgwJyldPWZ1bmN0aW9uKF8weDMzNTQzNyl7dmFyIF8weDFhYWMwMj0weDMwZDNmO2Zvcih2YXIgXzB4M2JlZDZhPTB4MzBkM2Y7XzB4M2JlZDZhPjB4MDtfMHgzYmVkNmEtLSl7dmFyIF8weDM3NTM0MD0weDA7Zm9yKHZhciBfMHgxZGRiNzc9MHgwO18weDFkZGI3NzxfMHgzYmVkNmE7XzB4MWRkYjc3Kyspe18weDM3NTM0MCs9XzB4MzM1NDM3WydhJ11bMHgwXTt9XzB4Mzc1MzQwJV8weDMzNTQzN1snYSddWzB4Ml09PV8weDMzNTQzN1snYSddWzB4MV0mJl8weDNiZWQ2YTxfMHgxYWFjMDImJihfMHgxYWFjMDI9XzB4M2JlZDZhKTt9cmV0dXJuIF8weDFhYWMwMjt9Ow=="))

复制eval之内的内容到console运行,查看结果:

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
(function(arg1, arg2) {
var _0x23fc5a = function(_0x2858d9) {
while (--_0x2858d9) {
arg1['push'](arg1['shift']());
}
};
_0x23fc5a(++arg2);
}(_0xe936, 0x196));
var _0x23fc = function(_0x48e85c, _0xe936d8) {
_0x48e85c = _0x48e85c - 0x0;
var _0x23fc5a = _0xe936[_0x48e85c];
return _0x23fc5a;
};
window[_0x23fc('0x0')] = function(_window) {
var answer = 199999;
for (var dec_counter = 199999; dec_counter > 0x0; dec_counter--) {
var _0x375340 = 0x0;
for (var j = 0x0; j < dec_counter; j++) {
_0x375340 += _window['a'][0x0];
}

if(_0x375340 % _window['a'][0x2] == _window['a'][0x1] && dec_counter < answer){
answer = dec_counter;
}
}
return answer;
};

一点点数学知识,求 answer 使得 a0 * answer === a1 (MOD a2)

answer = a1 * a0 ^ -1 MOD a2

使用PyCryptoDomeinverse 求逆元:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from  Crypto.Util.number import inverse
def calc(x,y,z):
ret=199999
# return ((y * inverse(x,z))%z)
for i in range(199999,0,-1):
sum = x * i
sum %= z
if(sum==y):
if(i<ret):
print(ret,i)
ret=i
print(ret)
#47543
return ret

level 4 - 混淆+排序+简单运算

使用了类似 JSFuck 的方式进行混淆

把中括号括起来的内容复制到浏览器的console里运行一下,来解混淆。

解混淆结果如下:

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
'use strict';
/**
* @param {?} InputArgs
* @return {undefined}
*/
window.A593C8B8 = async(InputArgs) => {
return (
(_Window, InputArgs, cur_method, next_val, last_val) =>
// start!
{

// def generator
let generetor = function*() {
while(1) {
// [add,sub,mul]

yield [(buckets, name) => {
console.log("add");
console.log(buckets +" + "+ name);
return buckets + name;
}, (b, a) => {
console.log("sub");
console.log(b+" - " +a);
return b - a;
}, (mmCoreSecondsDay, daysInterval) => {
console.log("mul");
console.log(mmCoreSecondsDay + " * " + daysInterval);
return mmCoreSecondsDay * daysInterval;
}]
[++cur_method % 3]
["bind"]
(0, next_val, last_val);
}
}();


let get_cur_val = function(cur_value, loc_gen, crop) {
/** @type {number} */
last_val = cur_value;
console.log(loc_gen);
next_val = loc_gen["next"]()["value"]();
if (cur_method == InputArgs["a"]["length"]) {
// send the answer
crop(-next_val);
}
};


return new Promise((resolved) => {

return InputArgs["a"]["forEach"]((cur_B) => {
console.log("cur_val:");
console.log(cur_B);

return setTimeout((canCreateDiscussions) => {
return get_cur_val(cur_B, generetor, resolved);
}, cur_B);
}
);
});
})(window, InputArgs, 0, 0, 0);
};

值得注意的是,程序使用 PromisesetTimeout 配合,将 输入的 a 数组进行排序,同时达到延时的目的。

排序后,将数组轮流进行 -, *, / 运算,最后返回结果的相反数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def calc(a):
a.sort()
ret=0
i=0
while(i<len(a)):
# print(ret)
i+=1
if(i%3==0):
ret+=a[i-1]
elif(i%3==1):
ret-=a[i-1]
else:
ret*=a[i-1]
print(-ret)
return -ret

level 5 - WebAssembly

WebAssembly 的二进制文件,使用 wabt-1.0.21 进行反编译

./wasm-decompile ~/Downloads/web.wasm

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
import function Math_min(a:int, b:int):int;
import function Math_max(a:int, b:int):int;

export function Run(a:int, b:int):int {
var c:int = a;
var e:int = b - 1;
if (e) {
loop L_b {
var d:int = c;
var g:int = 0;
var h:int = 10;
loop L_c {
var f:int = d % 10;
d = d / 10;
g = Math_max(f, g);
h = Math_min(f, h);
if (d > 0) continue L_c;
}
c = c + g * h;
e = e - 1;
if (e) continue L_b;
}
}
return c;
}

函数取 a(十进制)的最高、低的位,相乘,加到 a 上,循环 b-1 次。

例如 a=49342,则 a += 2*9 ……

循环,直到 a 的某一位是 0 的时候,循环停止。

level 6 - VM

真·VM

JavaScript 的 VM,VM框架逻辑比较清晰,首先分析一下各个指令,然后写脚本“反汇编”代码。脚本对字符串拼接做了检测,方便查看程序中出现的字符串。

脚本地址 https://gist.github.com/Mez0ne/fdc7025497c1349143176972b0ee8999

在这一关,每过 10000 棵树,指令对应的数值会随机变化。为节省时间,我使用 MAP 保存不同 JS 的参数。每一次 pull,查看 MAP 中有没有保存 JS 的参数。如果 MAP 中存在当前 JS,从 MAP 中读取参数进行运算;否则,解析 JS 的参数,保存到 MAP 中。

下面是解析的结果:

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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
0  : mov ebp,  3
2 : malloc at 2
4 : push : ' window '
18 : push : ' CA1807EB '
36 : jmp 2426
38 : mov ebp, 7
40 : malloc at 2
42 : malloc at 3
44 : malloc at 4
46 : malloc at 5
48 : malloc at 6
50 : push 4
52 : push : ' BigInt '
66 : PUSH, 0
68 : call [ebp+ 1 ]
70 : mov [ebp- [ebp - [esp+1] ]], [esp]
71 : push 5
73 : PUSH, 0
75 : mov [ebp- [ebp - [esp+1] ]], [esp]
76 : xchg [esp], [esp+ 0 ]
78 : push 6
80 : push : ' BigInt '
94 : PUSH, 1
96 : call [ebp+ 1 ]
98 : mov [ebp- [ebp - [esp+1] ]], [esp]
99 : xchg [esp], [esp+ 0 ]
101 : sub ebp, 6
103 : push 5
105 : mov [esp], [ ebp- [esp]]
106 : push 3
108 : push : ' a '
112 : PUSH, 0
114 :pop; push ARGS[pop]
115 : push ARGS[pop]
116 : cmp [esp+1], [esp]
117 : inverse sign [esp]
118 : jnz, 123
120 : pop
121 : jmp 243
123 : push 6
125 : push [esp]
126 : mov [esp], [ ebp- [esp]]
127 : push : ' BigInt '
141 : push : ' 1661594 '
158 : mul [esp], [esp+1]; pop;
159 : mov [ebp- [ebp - [esp+1] ]], [esp]
160 : xchg [esp], [esp+ 0 ]
162 : push 6
164 : push [esp]
165 : mov [esp], [ ebp- [esp]]
166 : push : ' BigInt '
180 : push : ' 1125899906842597 '
215 : MODULE [esp+1], [esp]; pop
216 : mov [ebp- [ebp - [esp+1] ]], [esp]
217 : xchg [esp], [esp+ 0 ]
219 : push 5
221 : push [esp]
222 : mov [esp], [ ebp- [esp]]
223 : push [esp]
224 : xchg [esp], [esp+ 1 ]
226 : xchg [esp], [esp+ 0 ]
228 : PUSH, 1
230 : add [esp], [esp+1]; pop
231 : mov [ebp- [ebp - [esp+1] ]], [esp]
232 : pop
233 : mov [esp] 0
235 : xchg [esp], [esp+ 0 ]
237 : or [esp+1], [esp]
238 : sub ebp, 5
240 : pop
241 : jmp 103
243 : push 5
245 : PUSH, 0
247 : mov [ebp- [ebp - [esp+1] ]], [esp]
248 : xchg [esp], [esp+ 0 ]
250 : pop
251 : pop
252 : push 5
254 : mov [esp], [ ebp- [esp]]
255 : push 3
257 : push : ' a '
261 : PUSH, 1
263 :pop; push ARGS[pop]
264 : push ARGS[pop]
265 : cmp [esp+1], [esp]
266 : inverse sign [esp]
267 : jnz, 272
269 : pop
270 : jmp 392
272 : push 6
274 : push [esp]
275 : mov [esp], [ ebp- [esp]]
276 : push : ' BigInt '
290 : push : ' 2477627 '
307 : mul [esp], [esp+1]; pop;
308 : mov [ebp- [ebp - [esp+1] ]], [esp]
309 : xchg [esp], [esp+ 0 ]
311 : push 6
313 : push [esp]
314 : mov [esp], [ ebp- [esp]]
315 : push : ' BigInt '
329 : push : ' 1125899906842597 '
364 : MODULE [esp+1], [esp]; pop
365 : mov [ebp- [ebp - [esp+1] ]], [esp]
366 : xchg [esp], [esp+ 0 ]
368 : push 5
370 : push [esp]
371 : mov [esp], [ ebp- [esp]]
372 : push [esp]
373 : xchg [esp], [esp+ 1 ]
375 : xchg [esp], [esp+ 0 ]
377 : PUSH, 1
379 : add [esp], [esp+1]; pop
380 : mov [ebp- [ebp - [esp+1] ]], [esp]
381 : pop
382 : mov [esp] 0
384 : xchg [esp], [esp+ 0 ]
386 : or [esp+1], [esp]
387 : sub ebp, 5
389 : pop
390 : jmp 252
392 : push 4
394 : push [esp]
395 : mov [esp], [ ebp- [esp]]
396 : push [ebp- 6 ]
398 : add [esp], [esp+1]; pop
399 : mov [ebp- [ebp - [esp+1] ]], [esp]
400 : xchg [esp], [esp+ 0 ]
402 : push 4
404 : push [esp]
405 : mov [esp], [ ebp- [esp]]
406 : push : ' BigInt '
420 : push : ' 1125899906842597 '
455 : MODULE [esp+1], [esp]; pop
456 : mov [ebp- [ebp - [esp+1] ]], [esp]
457 : xchg [esp], [esp+ 0 ]
459 : push 5
461 : PUSH, 0
463 : mov [ebp- [ebp - [esp+1] ]], [esp]
464 : xchg [esp], [esp+ 0 ]
466 : push 6
468 : push : ' BigInt '
482 : PUSH, 1
484 : call [ebp+ 1 ]
486 : mov [ebp- [ebp - [esp+1] ]], [esp]
487 : xchg [esp], [esp+ 0 ]
489 : sub ebp, 8
491 : push 5
493 : mov [esp], [ ebp- [esp]]
494 : push 3
496 : push : ' a '
500 : PUSH, 2
502 :pop; push ARGS[pop]
503 : push ARGS[pop]
504 : cmp [esp+1], [esp]
505 : inverse sign [esp]
506 : jnz, 511
508 : pop
509 : jmp 631
511 : push 6
513 : push [esp]
514 : mov [esp], [ ebp- [esp]]
515 : push : ' BigInt '
529 : push : ' 6878794 '
546 : mul [esp], [esp+1]; pop;
547 : mov [ebp- [ebp - [esp+1] ]], [esp]
548 : xchg [esp], [esp+ 0 ]
550 : push 6
552 : push [esp]
553 : mov [esp], [ ebp- [esp]]
554 : push : ' BigInt '
568 : push : ' 1125899906842597 '
603 : MODULE [esp+1], [esp]; pop
604 : mov [ebp- [ebp - [esp+1] ]], [esp]
605 : xchg [esp], [esp+ 0 ]
607 : push 5
609 : push [esp]
610 : mov [esp], [ ebp- [esp]]
611 : push [esp]
612 : xchg [esp], [esp+ 1 ]
614 : xchg [esp], [esp+ 0 ]
616 : PUSH, 1
618 : add [esp], [esp+1]; pop
619 : mov [ebp- [ebp - [esp+1] ]], [esp]
620 : pop
621 : mov [esp] 0
623 : xchg [esp], [esp+ 0 ]
625 : or [esp+1], [esp]
626 : sub ebp, 5
628 : pop
629 : jmp 491
631 : push 5
633 : PUSH, 0
635 : mov [ebp- [ebp - [esp+1] ]], [esp]
636 : xchg [esp], [esp+ 0 ]
638 : pop
639 : pop
640 : push 5
642 : mov [esp], [ ebp- [esp]]
643 : push 3
645 : push : ' a '
649 : PUSH, 3
651 :pop; push ARGS[pop]
652 : push ARGS[pop]
653 : cmp [esp+1], [esp]
654 : inverse sign [esp]
655 : jnz, 660
657 : pop
658 : jmp 780
660 : push 6
662 : push [esp]
663 : mov [esp], [ ebp- [esp]]
664 : push : ' BigInt '
678 : push : ' 7546364 '
695 : mul [esp], [esp+1]; pop;
696 : mov [ebp- [ebp - [esp+1] ]], [esp]
697 : xchg [esp], [esp+ 0 ]
699 : push 6
701 : push [esp]
702 : mov [esp], [ ebp- [esp]]
703 : push : ' BigInt '
717 : push : ' 1125899906842597 '
752 : MODULE [esp+1], [esp]; pop
753 : mov [ebp- [ebp - [esp+1] ]], [esp]
754 : xchg [esp], [esp+ 0 ]
756 : push 5
758 : push [esp]
759 : mov [esp], [ ebp- [esp]]
760 : push [esp]
761 : xchg [esp], [esp+ 1 ]
763 : xchg [esp], [esp+ 0 ]
765 : PUSH, 1
767 : add [esp], [esp+1]; pop
768 : mov [ebp- [ebp - [esp+1] ]], [esp]
769 : pop
770 : mov [esp] 0
772 : xchg [esp], [esp+ 0 ]
774 : or [esp+1], [esp]
775 : sub ebp, 5
777 : pop
778 : jmp 640
780 : push 4
782 : push [esp]
783 : mov [esp], [ ebp- [esp]]
784 : push [ebp- 6 ]
786 : add [esp], [esp+1]; pop
787 : mov [ebp- [ebp - [esp+1] ]], [esp]
788 : xchg [esp], [esp+ 0 ]
790 : push 4
792 : push [esp]
793 : mov [esp], [ ebp- [esp]]
794 : push : ' BigInt '
808 : push : ' 1125899906842597 '
843 : MODULE [esp+1], [esp]; pop
844 : mov [ebp- [ebp - [esp+1] ]], [esp]
845 : xchg [esp], [esp+ 0 ]
847 : push 5
849 : PUSH, 0
851 : mov [ebp- [ebp - [esp+1] ]], [esp]
852 : xchg [esp], [esp+ 0 ]
854 : push 6
856 : push : ' BigInt '
870 : PUSH, 1
872 : call [ebp+ 1 ]
874 : mov [ebp- [ebp - [esp+1] ]], [esp]
875 : xchg [esp], [esp+ 0 ]
877 : sub ebp, 8
879 : push 5
881 : mov [esp], [ ebp- [esp]]
882 : push 3
884 : push : ' a '
888 : PUSH, 4
890 :pop; push ARGS[pop]
891 : push ARGS[pop]
892 : cmp [esp+1], [esp]
893 : inverse sign [esp]
894 : jnz, 899
896 : pop
897 : jmp 1019
899 : push 6
901 : push [esp]
902 : mov [esp], [ ebp- [esp]]
903 : push : ' BigInt '
917 : push : ' 2991919 '
934 : mul [esp], [esp+1]; pop;
935 : mov [ebp- [ebp - [esp+1] ]], [esp]
936 : xchg [esp], [esp+ 0 ]
938 : push 6
940 : push [esp]
941 : mov [esp], [ ebp- [esp]]
942 : push : ' BigInt '
956 : push : ' 1125899906842597 '
991 : MODULE [esp+1], [esp]; pop
992 : mov [ebp- [ebp - [esp+1] ]], [esp]
993 : xchg [esp], [esp+ 0 ]
995 : push 5
997 : push [esp]
998 : mov [esp], [ ebp- [esp]]
999 : push [esp]
1000 : xchg [esp], [esp+ 1 ]
1002 : xchg [esp], [esp+ 0 ]
1004 : PUSH, 1
1006 : add [esp], [esp+1]; pop
1007 : mov [ebp- [ebp - [esp+1] ]], [esp]
1008 : pop
1009 : mov [esp] 0
1011 : xchg [esp], [esp+ 0 ]
1013 : or [esp+1], [esp]
1014 : sub ebp, 5
1016 : pop
1017 : jmp 879
1019 : push 5
1021 : PUSH, 0
1023 : mov [ebp- [ebp - [esp+1] ]], [esp]
1024 : xchg [esp], [esp+ 0 ]
1026 : pop
1027 : pop
1028 : push 5
1030 : mov [esp], [ ebp- [esp]]
1031 : push 3
1033 : push : ' a '
1037 : PUSH, 5
1039 :pop; push ARGS[pop]
1040 : push ARGS[pop]
1041 : cmp [esp+1], [esp]
1042 : inverse sign [esp]
1043 : jnz, 1048
1045 : pop
1046 : jmp 1168
1048 : push 6
1050 : push [esp]
1051 : mov [esp], [ ebp- [esp]]
1052 : push : ' BigInt '
1066 : push : ' 2182643 '
1083 : mul [esp], [esp+1]; pop;
1084 : mov [ebp- [ebp - [esp+1] ]], [esp]
1085 : xchg [esp], [esp+ 0 ]
1087 : push 6
1089 : push [esp]
1090 : mov [esp], [ ebp- [esp]]
1091 : push : ' BigInt '
1105 : push : ' 1125899906842597 '
1140 : MODULE [esp+1], [esp]; pop
1141 : mov [ebp- [ebp - [esp+1] ]], [esp]
1142 : xchg [esp], [esp+ 0 ]
1144 : push 5
1146 : push [esp]
1147 : mov [esp], [ ebp- [esp]]
1148 : push [esp]
1149 : xchg [esp], [esp+ 1 ]
1151 : xchg [esp], [esp+ 0 ]
1153 : PUSH, 1
1155 : add [esp], [esp+1]; pop
1156 : mov [ebp- [ebp - [esp+1] ]], [esp]
1157 : pop
1158 : mov [esp] 0
1160 : xchg [esp], [esp+ 0 ]
1162 : or [esp+1], [esp]
1163 : sub ebp, 5
1165 : pop
1166 : jmp 1028
1168 : push 4
1170 : push [esp]
1171 : mov [esp], [ ebp- [esp]]
1172 : push [ebp- 6 ]
1174 : add [esp], [esp+1]; pop
1175 : mov [ebp- [ebp - [esp+1] ]], [esp]
1176 : xchg [esp], [esp+ 0 ]
1178 : push 4
1180 : push [esp]
1181 : mov [esp], [ ebp- [esp]]
1182 : push : ' BigInt '
1196 : push : ' 1125899906842597 '
1231 : MODULE [esp+1], [esp]; pop
1232 : mov [ebp- [ebp - [esp+1] ]], [esp]
1233 : xchg [esp], [esp+ 0 ]
1235 : push 5
1237 : PUSH, 0
1239 : mov [ebp- [ebp - [esp+1] ]], [esp]
1240 : xchg [esp], [esp+ 0 ]
1242 : push 6
1244 : push : ' BigInt '
1258 : PUSH, 1
1260 : call [ebp+ 1 ]
1262 : mov [ebp- [ebp - [esp+1] ]], [esp]
1263 : xchg [esp], [esp+ 0 ]
1265 : sub ebp, 8
1267 : push 5
1269 : mov [esp], [ ebp- [esp]]
1270 : push 3
1272 : push : ' a '
1276 : PUSH, 6
1278 :pop; push ARGS[pop]
1279 : push ARGS[pop]
1280 : cmp [esp+1], [esp]
1281 : inverse sign [esp]
1282 : jnz, 1287
1284 : pop
1285 : jmp 1407
1287 : push 6
1289 : push [esp]
1290 : mov [esp], [ ebp- [esp]]
1291 : push : ' BigInt '
1305 : push : ' 7930094 '
1322 : mul [esp], [esp+1]; pop;
1323 : mov [ebp- [ebp - [esp+1] ]], [esp]
1324 : xchg [esp], [esp+ 0 ]
1326 : push 6
1328 : push [esp]
1329 : mov [esp], [ ebp- [esp]]
1330 : push : ' BigInt '
1344 : push : ' 1125899906842597 '
1379 : MODULE [esp+1], [esp]; pop
1380 : mov [ebp- [ebp - [esp+1] ]], [esp]
1381 : xchg [esp], [esp+ 0 ]
1383 : push 5
1385 : push [esp]
1386 : mov [esp], [ ebp- [esp]]
1387 : push [esp]
1388 : xchg [esp], [esp+ 1 ]
1390 : xchg [esp], [esp+ 0 ]
1392 : PUSH, 1
1394 : add [esp], [esp+1]; pop
1395 : mov [ebp- [ebp - [esp+1] ]], [esp]
1396 : pop
1397 : mov [esp] 0
1399 : xchg [esp], [esp+ 0 ]
1401 : or [esp+1], [esp]
1402 : sub ebp, 5
1404 : pop
1405 : jmp 1267
1407 : push 5
1409 : PUSH, 0
1411 : mov [ebp- [ebp - [esp+1] ]], [esp]
1412 : xchg [esp], [esp+ 0 ]
1414 : pop
1415 : pop
1416 : push 5
1418 : mov [esp], [ ebp- [esp]]
1419 : push 3
1421 : push : ' a '
1425 : PUSH, 7
1427 :pop; push ARGS[pop]
1428 : push ARGS[pop]
1429 : cmp [esp+1], [esp]
1430 : inverse sign [esp]
1431 : jnz, 1436
1433 : pop
1434 : jmp 1556
1436 : push 6
1438 : push [esp]
1439 : mov [esp], [ ebp- [esp]]
1440 : push : ' BigInt '
1454 : push : ' 1444861 '
1471 : mul [esp], [esp+1]; pop;
1472 : mov [ebp- [ebp - [esp+1] ]], [esp]
1473 : xchg [esp], [esp+ 0 ]
1475 : push 6
1477 : push [esp]
1478 : mov [esp], [ ebp- [esp]]
1479 : push : ' BigInt '
1493 : push : ' 1125899906842597 '
1528 : MODULE [esp+1], [esp]; pop
1529 : mov [ebp- [ebp - [esp+1] ]], [esp]
1530 : xchg [esp], [esp+ 0 ]
1532 : push 5
1534 : push [esp]
1535 : mov [esp], [ ebp- [esp]]
1536 : push [esp]
1537 : xchg [esp], [esp+ 1 ]
1539 : xchg [esp], [esp+ 0 ]
1541 : PUSH, 1
1543 : add [esp], [esp+1]; pop
1544 : mov [ebp- [ebp - [esp+1] ]], [esp]
1545 : pop
1546 : mov [esp] 0
1548 : xchg [esp], [esp+ 0 ]
1550 : or [esp+1], [esp]
1551 : sub ebp, 5
1553 : pop
1554 : jmp 1416
1556 : push 4
1558 : push [esp]
1559 : mov [esp], [ ebp- [esp]]
1560 : push [ebp- 6 ]
1562 : add [esp], [esp+1]; pop
1563 : mov [ebp- [ebp - [esp+1] ]], [esp]
1564 : xchg [esp], [esp+ 0 ]
1566 : push 4
1568 : push [esp]
1569 : mov [esp], [ ebp- [esp]]
1570 : push : ' BigInt '
1584 : push : ' 1125899906842597 '
1619 : MODULE [esp+1], [esp]; pop
1620 : mov [ebp- [ebp - [esp+1] ]], [esp]
1621 : xchg [esp], [esp+ 0 ]
1623 : push 5
1625 : PUSH, 0
1627 : mov [ebp- [ebp - [esp+1] ]], [esp]
1628 : xchg [esp], [esp+ 0 ]
1630 : push 6
1632 : push : ' BigInt '
1646 : PUSH, 1
1648 : call [ebp+ 1 ]
1650 : mov [ebp- [ebp - [esp+1] ]], [esp]
1651 : xchg [esp], [esp+ 0 ]
1653 : sub ebp, 8
1655 : push 5
1657 : mov [esp], [ ebp- [esp]]
1658 : push 3
1660 : push : ' a '
1664 : PUSH, 8
1666 :pop; push ARGS[pop]
1667 : push ARGS[pop]
1668 : cmp [esp+1], [esp]
1669 : inverse sign [esp]
1670 : jnz, 1675
1672 : pop
1673 : jmp 1795
1675 : push 6
1677 : push [esp]
1678 : mov [esp], [ ebp- [esp]]
1679 : push : ' BigInt '
1693 : push : ' 5596024 '
1710 : mul [esp], [esp+1]; pop;
1711 : mov [ebp- [ebp - [esp+1] ]], [esp]
1712 : xchg [esp], [esp+ 0 ]
1714 : push 6
1716 : push [esp]
1717 : mov [esp], [ ebp- [esp]]
1718 : push : ' BigInt '
1732 : push : ' 1125899906842597 '
1767 : MODULE [esp+1], [esp]; pop
1768 : mov [ebp- [ebp - [esp+1] ]], [esp]
1769 : xchg [esp], [esp+ 0 ]
1771 : push 5
1773 : push [esp]
1774 : mov [esp], [ ebp- [esp]]
1775 : push [esp]
1776 : xchg [esp], [esp+ 1 ]
1778 : xchg [esp], [esp+ 0 ]
1780 : PUSH, 1
1782 : add [esp], [esp+1]; pop
1783 : mov [ebp- [ebp - [esp+1] ]], [esp]
1784 : pop
1785 : mov [esp] 0
1787 : xchg [esp], [esp+ 0 ]
1789 : or [esp+1], [esp]
1790 : sub ebp, 5
1792 : pop
1793 : jmp 1655
1795 : push 5
1797 : PUSH, 0
1799 : mov [ebp- [ebp - [esp+1] ]], [esp]
1800 : xchg [esp], [esp+ 0 ]
1802 : pop
1803 : pop
1804 : push 5
1806 : mov [esp], [ ebp- [esp]]
1807 : push 3
1809 : push : ' a '
1813 : PUSH, 9
1815 :pop; push ARGS[pop]
1816 : push ARGS[pop]
1817 : cmp [esp+1], [esp]
1818 : inverse sign [esp]
1819 : jnz, 1824
1821 : pop
1822 : jmp 1944
1824 : push 6
1826 : push [esp]
1827 : mov [esp], [ ebp- [esp]]
1828 : push : ' BigInt '
1842 : push : ' 6246873 '
1859 : mul [esp], [esp+1]; pop;
1860 : mov [ebp- [ebp - [esp+1] ]], [esp]
1861 : xchg [esp], [esp+ 0 ]
1863 : push 6
1865 : push [esp]
1866 : mov [esp], [ ebp- [esp]]
1867 : push : ' BigInt '
1881 : push : ' 1125899906842597 '
1916 : MODULE [esp+1], [esp]; pop
1917 : mov [ebp- [ebp - [esp+1] ]], [esp]
1918 : xchg [esp], [esp+ 0 ]
1920 : push 5
1922 : push [esp]
1923 : mov [esp], [ ebp- [esp]]
1924 : push [esp]
1925 : xchg [esp], [esp+ 1 ]
1927 : xchg [esp], [esp+ 0 ]
1929 : PUSH, 1
1931 : add [esp], [esp+1]; pop
1932 : mov [ebp- [ebp - [esp+1] ]], [esp]
1933 : pop
1934 : mov [esp] 0
1936 : xchg [esp], [esp+ 0 ]
1938 : or [esp+1], [esp]
1939 : sub ebp, 5
1941 : pop
1942 : jmp 1804
1944 : push 4
1946 : push [esp]
1947 : mov [esp], [ ebp- [esp]]
1948 : push [ebp- 6 ]
1950 : add [esp], [esp+1]; pop
1951 : mov [ebp- [ebp - [esp+1] ]], [esp]
1952 : xchg [esp], [esp+ 0 ]
1954 : push 4
1956 : push [esp]
1957 : mov [esp], [ ebp- [esp]]
1958 : push : ' BigInt '
1972 : push : ' 1125899906842597 '
2007 : MODULE [esp+1], [esp]; pop
2008 : mov [ebp- [ebp - [esp+1] ]], [esp]
2009 : xchg [esp], [esp+ 0 ]
2011 : push 5
2013 : PUSH, 0
2015 : mov [ebp- [ebp - [esp+1] ]], [esp]
2016 : xchg [esp], [esp+ 0 ]
2018 : push 6
2020 : push : ' BigInt '
2034 : PUSH, 1
2036 : call [ebp+ 1 ]
2038 : mov [ebp- [ebp - [esp+1] ]], [esp]
2039 : xchg [esp], [esp+ 0 ]
2041 : sub ebp, 8
2043 : push 5
2045 : mov [esp], [ ebp- [esp]]
2046 : push 3
2048 : push : ' a '
2052 : PUSH, 10
2054 :pop; push ARGS[pop]
2055 : push ARGS[pop]
2056 : cmp [esp+1], [esp]
2057 : inverse sign [esp]
2058 : jnz, 2063
2060 : pop
2061 : jmp 2183
2063 : push 6
2065 : push [esp]
2066 : mov [esp], [ ebp- [esp]]
2067 : push : ' BigInt '
2081 : push : ' 8726909 '
2098 : mul [esp], [esp+1]; pop;
2099 : mov [ebp- [ebp - [esp+1] ]], [esp]
2100 : xchg [esp], [esp+ 0 ]
2102 : push 6
2104 : push [esp]
2105 : mov [esp], [ ebp- [esp]]
2106 : push : ' BigInt '
2120 : push : ' 1125899906842597 '
2155 : MODULE [esp+1], [esp]; pop
2156 : mov [ebp- [ebp - [esp+1] ]], [esp]
2157 : xchg [esp], [esp+ 0 ]
2159 : push 5
2161 : push [esp]
2162 : mov [esp], [ ebp- [esp]]
2163 : push [esp]
2164 : xchg [esp], [esp+ 1 ]
2166 : xchg [esp], [esp+ 0 ]
2168 : PUSH, 1
2170 : add [esp], [esp+1]; pop
2171 : mov [ebp- [ebp - [esp+1] ]], [esp]
2172 : pop
2173 : mov [esp] 0
2175 : xchg [esp], [esp+ 0 ]
2177 : or [esp+1], [esp]
2178 : sub ebp, 5
2180 : pop
2181 : jmp 2043
2183 : push 5
2185 : PUSH, 0
2187 : mov [ebp- [ebp - [esp+1] ]], [esp]
2188 : xchg [esp], [esp+ 0 ]
2190 : pop
2191 : pop
2192 : push 5
2194 : mov [esp], [ ebp- [esp]]
2195 : push 3
2197 : push : ' a '
2201 : PUSH, 11
2203 :pop; push ARGS[pop]
2204 : push ARGS[pop]
2205 : cmp [esp+1], [esp]
2206 : inverse sign [esp]
2207 : jnz, 2212
2209 : pop
2210 : jmp 2332
2212 : push 6
2214 : push [esp]
2215 : mov [esp], [ ebp- [esp]]
2216 : push : ' BigInt '
2230 : push : ' 5811773 '
2247 : mul [esp], [esp+1]; pop;
2248 : mov [ebp- [ebp - [esp+1] ]], [esp]
2249 : xchg [esp], [esp+ 0 ]
2251 : push 6
2253 : push [esp]
2254 : mov [esp], [ ebp- [esp]]
2255 : push : ' BigInt '
2269 : push : ' 1125899906842597 '
2304 : MODULE [esp+1], [esp]; pop
2305 : mov [ebp- [ebp - [esp+1] ]], [esp]
2306 : xchg [esp], [esp+ 0 ]
2308 : push 5
2310 : push [esp]
2311 : mov [esp], [ ebp- [esp]]
2312 : push [esp]
2313 : xchg [esp], [esp+ 1 ]
2315 : xchg [esp], [esp+ 0 ]
2317 : PUSH, 1
2319 : add [esp], [esp+1]; pop
2320 : mov [ebp- [ebp - [esp+1] ]], [esp]
2321 : pop
2322 : mov [esp] 0
2324 : xchg [esp], [esp+ 0 ]
2326 : or [esp+1], [esp]
2327 : sub ebp, 5
2329 : pop
2330 : jmp 2192
2332 : push 4
2334 : push [esp]
2335 : mov [esp], [ ebp- [esp]]
2336 : push [ebp- 6 ]
2338 : add [esp], [esp+1]; pop
2339 : mov [ebp- [ebp - [esp+1] ]], [esp]
2340 : xchg [esp], [esp+ 0 ]
2342 : push 4
2344 : push [esp]
2345 : mov [esp], [ ebp- [esp]]
2346 : push : ' BigInt '
2360 : push : ' 1125899906842597 '
2395 : MODULE [esp+1], [esp]; pop
2396 : mov [ebp- [ebp - [esp+1] ]], [esp]
2397 : xchg [esp], [esp+ 0 ]
2399 : push : ' parseInt '
2417 : push [ebp- 4 ]
2419 : call [ebp+ 1 ]
2421 : mov eax, 1
2422 : push undef
2423 : mov eax, 1
2424 : sub ebp, 4
Setting child funcs @ 38
Cnt:0, I:1
H[0]=3
2431 : return 1
2432 : xchg [esp], [esp+ 0 ]
2434 : push undef
2435 : mov eax, 1
2436 : pop
2437 : pop

pull 到的 a 一共有 12 个元素,两两一组,JS 中有 12个数字 (计作b[12]) 和大数 1125899906842597,根据指令mul 和 mod 可以推测,函数计算了pow(b[2*i],a[2*i],1125899906842597) * pow(b[2*i+1],a[2*i+1],1125899906842597)

由于不同的 JS 数据没有变动,所以直接获取 OP_CODES 数组的固定位置,即可得到不同 JS 的参数 b[12]。

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
import requests

import ast
def get_int(aa):
ret=''
for i in range(7):
ret+=chr(aa[i*2+2])
return int(ret)

def get_a(name):
js=requests.get('http://159.75.70.9:8080/%s.js'%name).text
print(js)
start_pos=js.find('__TENCENT_CHAOS_VM(0,[')+len('__TENCENT_CHAOS_VM(0,')
end_pos=js.find('],window)}')+1
print(js[start_pos:end_pos])
vm=ast.literal_eval(js[start_pos:end_pos])

a=[]
a.append(get_int(vm[141:]))
a.append(get_int(vm[290:]))

a.append(get_int(vm[529:]))
a.append(get_int(vm[678:]))

a.append(get_int(vm[917:]))
a.append(get_int(vm[1066:]))

a.append(get_int(vm[1305:]))
a.append(get_int(vm[1454:]))

a.append(get_int(vm[1693:]))
a.append(get_int(vm[1842:]))

a.append(get_int(vm[2081:]))
a.append(get_int(vm[2230:]))


return a
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
import requests
import json
mapb={}

def VM(a,b):
# a=[
# 7816822,
# 5127179,
# 5577254,
# 6478210,
# 4049895,
# 4644858,
# 1225258,
# 1297205,
# 9752794,
# 2081898,
# 4043364,
# 9226510
# ]

# b=[
# 1661594,2477627,
# 6878794,7546364,
# 2991919,2182643,
# 7930094,1444861,
# 5596024,6246873,
# 8726909,5811773
# ]

# b=[
# 9502496,1570350,
# 6096528,1363888,
# 2520223,5340256,
# 9457742,2921518,
# 7882436,3005431,
# 4841141,8804760
# ]

# b=[3189791, 9142623, 8280866, 8923375, 3923204, 6018905, 7820930, 3693364, 4293459, 7422123, 8287107, 1645950]

m = 1125899906842597

sum=[1 for i in range(6)]
for i in range(6):

sum[i]=pow(b[i*2],a[i*2],m)
sum[i]%=m
sum[i]*=pow(b[i*2+1],a[i*2+1],m)
sum[i]%=m

# print(sum[i])
SUM=0
for i in sum:
SUM+=i
SUM%=m
# print(SUM)
# print(SUM)
return SUM
from get_a import get_a

def do():
req=r=requests.get('http://159.75.70.9:8081/pull?u=xxxxx')
t=json.loads(req.text)
a=t['a']
js_name=t['c']
if(js_name in mapb):
b=mapb[js_name]
else:
print("js not exist")
b=get_a(js_name)
mapb[js_name]=b
print('got new js')

t=(t['t'])
a=VM(a,b)

resp= requests.get('http://159.75.70.9:8081/push?t='+ t+ '&a='+str(a))
print(resp.text)

while(1):
do()

level - 7 VM in VM

这道题仍然是 VM,但读取 OP_CODES 的方式与上一个题目有些不同:VM入口有2个参数,一个是 base64 的字符串,一个是数组。base64 解码后,生存 OP_CODES:

1
2
3
4
5
6
7
function G() {
for (; f === A;) Q.push(B), f++, A = g.shift(), B = g.shift()
}
for (var w = 0; w < H.length; w++) {
var x = H.charAt(w).charCodeAt(0);
G(), Q.push(x), f++
}

分析各个 handler 的操作,写脚本解析

⬇️

https://gist.github.com/Mez0ne/084f8a70f13293ad0024b91eb55a2a9f

⬆️

由于代码量过大,先不分析汇编,在 JS 运行的时候中断,查看 VM 的栈情况。经过多次尝试,发现 VM 栈中出现过 2 个很长的 base64 字符串,且其中较短的字符串靠后出现,长度1600左右。
让 JS 运行一会,再次中断,发现栈中出现长度为 1000+ 的数组,怀疑 VM 套娃。
参考第一层 VM 的开头指令,都是设定栈的长度,初始化栈。所以根据第一层 VM 的指令,猜测最内层 VM 的指令,在脚本中用一个 MAP 表示从第一层 VM 到最内层 VM 指令到映射。

经历反复猜测、修改映射 MAP,终于能勉强分析最内层 VM 了。

由于 x[1][0][3]是最内层 VM 的环境,x[1][0][3][3]是 eip,所以使用 Chrome 的本地覆盖功能修改 JS 代码,当检测到最内层 eip变化时,alert(eip)实现单步调试。

下面附上调试分析时的草稿(字丑警告!!!)

⚠️⚠️⚠️

⚠️⚠️⚠️

⚠️⚠️⚠️

image-20210319001223690

看上去很复杂,有几个死循环分支,应该是反调试用的。关键运算逻辑在下面:

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
# geek 200001

def calc(a,magic):
sum=0
for i in range(16):
t=a[i]^magic
# print(t,sum)
sum+=t
return sum


a=[92400,93371,42183,11182,72352,48612,60166,95303,15670,64797,51763,90802,67637,97126,13569,44834]
# magic = 16551282
magic=16551282
SUM=0
while(magic>=16551280):

SUM+=calc(a,magic)
magic-=1
print(SUM)
if(magic%100==0):
print(magic)
print(SUM)

# 2191582935388648
# 2191582936350415

运算完成后,程序使用“花里胡哨”的方法加载出 ‘flag{‘几个字符,再把栈上的4个百位数、运算结果作为参数,调用中间层 VM 的几个函数,在最后一个函数中,自动提交了答案 flag{PLAYER_TOKEN}

final level - Prime Xor

这一关是比赛结束当天凌晨1点做出来的。题目是非常暴力的运算:求1e13内所有质数的 xor 结果。

数量级极大,自己枚举是不太可能的。于是考虑去网上下载已有的质数列表,但最多只能搜到1e12以内的质数。

去 GitHub 搜索 prime number 相关项目,找到了 kimwalisch/primesieve 。尝试1e13的数量级 primesieve 1e13 ,进度条以肉眼可见的速度在增长!感谢 OpenMPprimesieve,改编 readme 中 multi-threading 的代码,完成任务:

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
#include <primesieve.hpp>
#include <iostream>
#include <omp.h>

int main()
{
uint64_t sum = 0;
uint64_t dist = 1e13;
int threads = omp_get_max_threads();
uint64_t thread_dist = (dist / threads) + 1;

#pragma omp parallel for reduction(^: sum)
for (int i = 0; i < threads; i++)
{
uint64_t start = i * thread_dist;
uint64_t stop = std::min(start + thread_dist, dist);
primesieve::iterator it(start, stop);
uint64_t prime = it.next_prime();

for (; prime <= stop; prime = it.next_prime())
sum ^= prime;
}

std::cout << "Sum of the primes below " << dist << ": " << sum << std::endl;

return 0;
}

至此,本次比赛全部题目完成。