dump

原程序是一个命令行工具,需要用命令行参数来进行使用,使用方法是在命令行输入以下命令

1
re.exe [data]

我们输入的数据会被加密,我们尝试输入几个字符就可以发现每个字符加密的对应结果是相同的,也就是单字节加密,那么我们就可以输入所有可打印字符得到加密后的结果,再把结果和原字符的数据映射起来就可以依据密文得出明文。

在这里密文被以二进制的形式保存都在flag文件中,我们需要用读文件的方式把密文读入。

脚本如下

在这个脚本中我尝试直接获得可打印字符,但是最后对比了其他人的wp,发现引号是不会被re.exe输出的,也就是如果你把引号也输入进去获取映射表,那么你的获得的映射表就会少一位,导致映射错误。在最后我们会发现还缺少了一个字符,但是base64编码的样子已经出来了,我们手动添加一个字符解码看看规律。

image-20241225234809411

解码后我们会发现很多奇怪的数字,感觉上像是一个时间戳,于是我们过滤掉那些含有符号的结果,最终找到上面的结果,把每个都输入一下就可以发现flag就是(原题中告诉了我们第十三位为4,我们假设不知道,分析数据解决)

flag{MTczMDc4MzQ2Ng==}

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
import base64
from base64 import b64decode
from idlelib.iomenu import encoding
from logging import exception
import time
from cli_helpers.utils import bytes_to_string
from mpmath.calculus.calculus import defun


def decrypt_cipher(enc_chars, text):
# 可打印字符
chars = "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ "
# chars = "".join(chr(i) for i in range(32,127)) //直接获得可打印字符

# 对应的密文
mp = {}
for i, char in enumerate(chars): #迭代器,返回索引和迭代元素
hex_char = enc_chars[2 * i:2 * i + 2] # 每两个字符为一组
mp[bytes.fromhex(hex_char)] = char
print(mp)

# 解密过程
plaintext = ""
for b in text:
plaintext += mp.get(bytes([b]), '?') # 用get获取键的值,如果没有匹配,使用占位符

return plaintext

# 从二进制文件读取密文
def readf(filepath):
with open(filepath, 'rb') as file:
return file.read()

# 文件路径
path = r"E:\CTF\国赛1\dump_a3645b5eeb8783766cf2f413837dfc77\bin\flag"

# 读取密文
text = readf(path)

# 解密
flag = decrypt_cipher(
"0000000000000000000000000000001c1d000000000000000000000100000002030405060708090a0b0c0d0e0f101112131415161718191a1b0000000000001e1f202122232425262728292a2b2c2d2e2f30313233343536373800390000",
text
)

print(flag)
for i in range(43,122):
bflag = bytes(flag.replace(' ', ''.join(chr(i))), encoding='UTF-8')[5:len(flag) -1:] #手动插入字符
try:
decflag = bytes_to_string(base64.decodebytes(bflag))
if(decflag.isdigit()):
print(f"flag为:flag{{{bytes_to_string(bflag)}}},flag{{{decflag}}}")
timestamp = int(decflag)
time_local = time.localtime(timestamp)
dt = time.strftime("%Y-%m-%d %H:%M:%S", time_local)
print(dt)

except:
continue


cython

key在python的test1pyc文件中,用pycdas人工或者AI读字节码,得到大概逻辑如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import ez

flag = input("flag")
flag1 = list(flag)
value = []
b = 0
ck = 0
if(len(flag1) != 24):
return 0
for i in range(0,len(flag1),4):
b = ord(flag1[i]) << 24 or ord(flag1[i+1]) << 16 or ord(flag1[i+2]) << 8 or ord(flag1[i+3])
value.append(b)
key =[102, 108, 97, 103]
flag_encrypt = []
for i in range(0,6,2):
res = ez.encrypt(value[i],value[i+1],key)
flag_encrypt.append(res)
ck = ez.check(flag_encrypt)
if ck == 3:
print("yes!!!,you get right flag")
else:
print("wrong")

分析pyd模块,创建一个python3.11的cython模块(有附件)用bindiff恢复符号。

恢复结构体

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
typedef struct __strings {
__int64* int_0;
__int64* int_1;
__int64* int_2;
__int64* int_3;
__int64* int_4;
__int64* int_5;
__int64* int_6;
__int64* str_xinxin;
__int64* str_v0;
__int64* str_v1;
__int64* str_wenhao;
__int64* str_asyncio;
__int64* str_c_uubt32;
__int64* str_check;
__int64* str___class_getitem;
__int64* str_cline_in_traceback;
__int64* str_ctypes;
__int64* str_data;
__int64* str_delta;
__int64* str_encrypt;
__int64* str_ez;
__int64* str_ez_py;
__int64* str_flag_encrypt;
__int64* str_i;
__int64* str__inport_;
__int64* str__is_continue;
__int64* str_key;
__int64* str_main;
__int64* str_name;
__int64* str_range;
__int64* str_test;
__int64* str_total;
__int64* str_unk;
__int64* str_v1;
__int64* str_value;
__int64* int_0a
__int64* int_1a
__int64* int_3a
__int64* int_6a
__int64* int_11a
__int64* int_345309213a
__int64* int_947843023a
__int64* int_1415865428a
__int64* int_1592923520a
__int64* int_2248247555s;
__int64* int_3785781401s;
__int64* int_3805970057s;
__int64* int_47;
__int64* int_48;
__int64* int_49;
__int64* int_50;
__int64* int_51;
__int64* int_52;
__int64* int_53;
__int64* int_54;
__int64* int_55;
__int64* int_56;
__int64* int_57;
__int64* int_58;
__int64* int_59;
__int64* int_60;
__int64* int_61;
__int64* int_62;
__int64* int_63;
} str;

分析加密函数,函数名受到了恢复符号的影响,通过ez.encrypt这个字符串寻找就行,_Pyx_PyVectorcall_FastCallDict_kw函数是由__pyx_pymod_exec_ez函数调用的,把v0,v1,key通过参数传入_Pyx_PyVectorcall_FastCallDict_kw。

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
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
__int64 __fastcall _Pyx_PyVectorcall_FastCallDict_kw(__int64 a1, __int64 v0, __int64 v1, __int64 a4)
{
_QWORD *v4; // rbp
_QWORD *v5; // rbx
__int64 v6; // rsi
_QWORD *AttrStrNoError; // r15
_QWORD *v111; // r13
__int64 *str_c_uint32; // rdi
__int64 *v12; // rdi
int v13; // ecx
_QWORD *v14; // rax
_QWORD *v15; // rcx
bool v16; // zf
_QWORD *v000; // rdi
unsigned int v18; // r12d
unsigned int v19; // r14d
__int64 *v20; // rbp
__int64 *v21; // rbp
int v22; // ecx
_QWORD *v23; // rax
_QWORD *v24; // rcx
__strings *data3; // r8
_QWORD *v1111; // r14
__int64 *int_1415865428a; // rsi
__int64 *v28; // rbx
__int64 *v29; // rbx
_QWORD *Item_KnownHash; // rax
_QWORD *v31; // rbx
unsigned int v32; // ecx
_QWORD *v33; // rax
_QWORD *v34; // rcx
_QWORD *v35; // rbp
__int64 *v36; // rbx
__int64 v37; // rdi
__int64 *str_value; // rdx
__int64 (__fastcall *v40)(_QWORD *, __int64 *); // r8
__int64 Attr; // rax
__int64 *v42; // rdx
__int64 (__fastcall *v43)(_QWORD *, __int64 *); // r8
unsigned __int64 v1_value; // rax
__int64 *v45; // rdx
__int64 (__fastcall *v46)(_QWORD *, __int64 *); // r8
__int64 v47; // rax
__int64 *v48; // rdx
__int64 (__fastcall *v49)(_QWORD *, __int64 *); // r8
__int64 v1_value2; // rax
__int64 *v51; // rdx
__int64 (__fastcall *v52)(__int64, __int64 *); // r8
__int64 sum_value; // rax
__int64 *v54; // rdx
__int64 (__fastcall *v55)(__int64, __int64 *); // r8
__int64 sum_value1; // rax
int v57; // ecx
__int64 sum_and_3; // rax
__int64 *v59; // rdx
__int64 (__fastcall *v60)(_QWORD *, __int64 *, _QWORD *); // r9
int v61; // eax
__int64 *v62; // rdx
__int64 (__fastcall *v63)(__int64, __int64 *); // r8
__int64 v64; // rax
__int64 *v65; // rdx
__int64 (__fastcall *v66)(__int64, __int64 *, _QWORD *); // r9
int v67; // eax
__int64 *v68; // rdx
__int64 (__fastcall *v69)(_QWORD *, __int64 *); // r8
__int64 v1_value3; // rax
__int64 *v71; // rdx
__int64 (__fastcall *v72)(_QWORD *, __int64 *); // r8
unsigned __int64 v0_value; // rax
__int64 *v74; // rdx
__int64 (__fastcall *v75)(_QWORD *, __int64 *); // r8
__int64 v76; // rax
__int64 *v77; // rdx
__int64 (__fastcall *v78)(_QWORD *, __int64 *); // r8
__int64 v0_value2; // rax
__int64 *v80; // rdx
__int64 (__fastcall *v81)(__int64, __int64 *); // r8
__int64 sum_value2; // rax
__int64 *v83; // rdx
__int64 (__fastcall *v84)(__int64, __int64 *); // r8
__int64 sum_value3; // rax
int v86; // ecx
__int64 v87; // rax
__int64 *v88; // rdx
__int64 (__fastcall *v89)(_QWORD *, __int64 *, _QWORD *); // r9
int v90; // eax
__int64 *v91; // rdx
__int64 (__fastcall *v92)(_QWORD *, __int64 *); // r8
__int64 v93; // rax
__int64 *v94; // rdx
__int64 (__fastcall *v95)(_QWORD *, __int64 *); // r8
__int64 v96; // rax
__int64 v97; // rax
_QWORD *v98; // [rsp+30h] [rbp-88h]
__int64 *delta; // [rsp+38h] [rbp-80h]
_QWORD *v100; // [rsp+40h] [rbp-78h]
__int64 sum; // [rsp+48h] [rbp-70h]
_QWORD v00[2]; // [rsp+58h] [rbp-60h] BYREF
_QWORD v11[2]; // [rsp+68h] [rbp-50h] BYREF
__int64 *int_0a; // [rsp+78h] [rbp-40h] BYREF
int v105; // [rsp+C0h] [rbp+8h]

v4 = 0LL;
v5 = 0LL;
v6 = 0LL;
AttrStrNoError = 0LL;
v98 = 0LL;
v100 = 0LL;
delta = 0LL;
sum = 0LL;
if ( qword_18000CEA8 == data->int_0[3] )
{
if ( qword_18000CE80 )
{
++*(_QWORD *)qword_18000CE80;
v111 = (_QWORD *)qword_18000CE80;
}
else
{
str_c_uint32 = data->str_c_uint32;
v111 = (_QWORD *)_Pyx_PyObject_GetAttrStrNoError(data->int_1, str_c_uint32);
if ( !v111 && !PyErr_Occurred() )
PyErr_Format(PyExc_NameError, "name '%U' is not defined", str_c_uint32);
}
goto LABEL_11;
}
v12 = data->str_c_uint32;
v111 = (_QWORD *)PyDict_GetItem_KnownHash(data->int_0, v12, v12[3]);// 从data->int_0(一个字典,通过键的哈希查找)加载方法(uint32)到attrstrnoerror中
qword_18000CEA8 = data->int_0[3];
qword_18000CE80 = (__int64)v111;
if ( !v111 )
{
if ( PyErr_Occurred() )
goto LABEL_320;
v111 = (_QWORD *)_Pyx_CyFunction_Vectorcall_CheckArgs(v12);// 检查参数
LABEL_11:
if ( v111 )
goto LABEL_12;
LABEL_320:
v18 = 5;
v19 = 2620;
goto LABEL_72;
}
++*v111;
LABEL_12:
v13 = 0;
if ( v111[1] == PyMethod_Type )
{
v4 = (_QWORD *)v111[3];
if ( v4 )
{
v14 = (_QWORD *)v111[2];
v15 = v111;
++*v4;
v111 = v14;
++*v14;
v16 = (*v15)-- == 1LL;
if ( v16 )
Py_Dealloc(v15);
v13 = 1;
}
}
v00[0] = v0;
v000 = (_QWORD *)callfunc((__int64)v111, &v00[-v13], (unsigned int)(v13 + 1));// c_uint32(v0)
if ( v4 ) //callfunc是自己命名的,进去分析一下猜的
{
v16 = (*v4)-- == 1LL;
if ( v16 )
Py_Dealloc(v4);
}
if ( !v000 )
{
v18 = 5;
v19 = 2640;
goto LABEL_300;
}
v16 = (*v111)-- == 1LL;
if ( v16 )
Py_Dealloc(v111);
v111 = 0LL;
if ( qword_18000CEC0 == data->int_0[3] )
{
if ( qword_18000CE70 )
{
++*(_QWORD *)qword_18000CE70;
AttrStrNoError = (_QWORD *)qword_18000CE70;
}
else
{
v20 = data->str_c_uint32;
AttrStrNoError = (_QWORD *)_Pyx_PyObject_GetAttrStrNoError(data->int_1, v20);
if ( !AttrStrNoError && !PyErr_Occurred() )
PyErr_Format(PyExc_NameError, "name '%U' is not defined", v20);
}
}
else
{
v21 = data->str_c_uint32;
AttrStrNoError = (_QWORD *)PyDict_GetItem_KnownHash(data->int_0, v21, v21[3]);// 同上加载uint32
qword_18000CEC0 = data->int_0[3];
qword_18000CE70 = (__int64)AttrStrNoError;
if ( AttrStrNoError )
{
++*AttrStrNoError;
goto LABEL_32;
}
if ( PyErr_Occurred() )
{
AttrStrNoError = 0LL;
v19 = 2644;
v18 = 5;
goto LABEL_298;
}
AttrStrNoError = (_QWORD *)_Pyx_CyFunction_Vectorcall_CheckArgs(v21);
}
if ( !AttrStrNoError )
{
v18 = 5;
v19 = 2644;
LABEL_298:
v16 = (*v000)-- == 1LL;
if ( v16 )
Py_Dealloc(v000);
LABEL_300:
if ( !v111 )
goto LABEL_308;
goto LABEL_306;
}
LABEL_32:
v22 = 0;
if ( AttrStrNoError[1] == PyMethod_Type )
{
v6 = AttrStrNoError[3];
if ( v6 )
{
v23 = (_QWORD *)AttrStrNoError[2];
v24 = AttrStrNoError;
++*(_QWORD *)v6;
AttrStrNoError = v23;
++*v23;
v16 = (*v24)-- == 1LL;
if ( v16 )
Py_Dealloc(v24);
v22 = 1;
}
}
v00[1] = v6;
v11[0] = v1;
v111 = (_QWORD *)callfunc((__int64)AttrStrNoError, &v11[-v22], (unsigned int)(v22 + 1));// c_uint32(v1)
if ( v6 )
{
v16 = (*(_QWORD *)v6)-- == 1LL;
if ( v16 )
Py_Dealloc(v6);
}
v6 = 0LL;
if ( !v111 )
{
v18 = 5;
v19 = 2664;
goto LABEL_298;
}
v16 = (*AttrStrNoError)-- == 1LL;
if ( v16 )
Py_Dealloc(AttrStrNoError);
data3 = data;
AttrStrNoError = v000; // 赋值v0给 attrstr...
v98 = v000; // 赋值v0到v98
v1111 = v111;
v100 = v111;
++*data->int_1415865428a;
int_1415865428a = data3->int_1415865428a;
delta = int_1415865428a;
if ( qword_18000CE68 == data3->int_0[3] )
{
if ( qword_18000CE90 )
{
++*(_QWORD *)qword_18000CE90;
v000 = (_QWORD *)qword_18000CE90;
goto LABEL_60;
}
v28 = data3->str_c_uint32;
v000 = (_QWORD *)_Pyx_PyObject_GetAttrStrNoError(data3->int_1, v28);
if ( !v000 && !PyErr_Occurred() )
PyErr_Format(PyExc_NameError, "name '%U' is not defined", v28);
}
else
{
v29 = data3->str_c_uint32;
Item_KnownHash = (_QWORD *)PyDict_GetItem_KnownHash(data3->int_0, v29, v29[3]);
data3 = data;
v000 = Item_KnownHash;
qword_18000CE68 = data->int_0[3];
qword_18000CE90 = (__int64)Item_KnownHash;
if ( Item_KnownHash )
{
++*Item_KnownHash;
goto LABEL_61;
}
if ( PyErr_Occurred() )
{
LABEL_319:
v18 = 8;
v19 = 2690;
goto LABEL_72;
}
v000 = (_QWORD *)_Pyx_CyFunction_Vectorcall_CheckArgs(v29);
}
data3 = data;
LABEL_60:
if ( !v000 )
goto LABEL_319;
LABEL_61:
v31 = 0LL;
v32 = 0;
if ( v000[1] == PyMethod_Type )
{
v31 = (_QWORD *)v000[3];
if ( v31 )
{
v33 = (_QWORD *)v000[2];
v34 = v000;
++*v31;
v000 = v33;
++*v33;
v16 = (*v34)-- == 1LL;
if ( v16 )
{
Py_Dealloc(v34);
data3 = data;
}
v32 = 1;
}
}
int_0a = data3->int_0a;
v11[1] = v31;
sum = callfunc((__int64)v000, &(&int_0a)[-v32], v32 + 1);// 同上加载一个初始为0的变量int_0a到sum中 uint32(int_0a),从下面的相加中可以看出是sum
v35 = (_QWORD *)sum;
v111 = (_QWORD *)sum; // 赋值sum给v111
if ( v31 )
{
v16 = (*v31)-- == 1LL;
if ( v16 )
Py_Dealloc(v31);
}
if ( !sum )
{
v98 = AttrStrNoError;
AttrStrNoError = 0LL;
delta = int_1415865428a;
v6 = 0LL;
v100 = v1111;
v5 = 0LL;
sum = 0LL;
v18 = 8;
v19 = 2710;
if ( !v000 )
goto LABEL_71;
goto LABEL_298;
}
v16 = (*v000)-- == 1LL;
if ( v16 )
Py_Dealloc(v000);
v105 = 0;
v18 = 11;
do // 开始加密循环
{
str_value = data->str_value;
v40 = *(__int64 (__fastcall **)(_QWORD *, __int64 *))(AttrStrNoError[1] + 144LL);
if ( v40 )
Attr = v40(AttrStrNoError, str_value);
else
Attr = PyObject_GetAttr(AttrStrNoError, str_value);// 这里的attr...是v0,获取v0.value到Attr中
v111 = (_QWORD *)Attr; // 赋值Attr到v111
if ( !Attr )
{
v18 = 10;
v19 = 2734;
goto LABEL_72;
}
v42 = data->str_value;
v43 = *(__int64 (__fastcall **)(_QWORD *, __int64 *))(v1111[1] + 144LL);
if ( v43 )
v1_value = v43(v1111, v42);
else
v1_value = PyObject_GetAttr(v1111, v42);
v000 = (_QWORD *)v1_value;
if ( !v1_value )
{
v19 = 2736;
AttrStrNoError = 0LL;
goto LABEL_303;
}
AttrStrNoError = (_QWORD *)sub_180005330(v1_value, (__int64)data->int_3a);// 进去看一眼就是PyNumber_Lshift(v2, a2),这里就是v1<<3
if ( !AttrStrNoError )
{
v6 = 0LL;
v19 = 2738;
goto LABEL_296;
}
v16 = (*v000)-- == 1LL;
if ( v16 )
Py_Dealloc(v000);
v45 = data->str_value;
v46 = *(__int64 (__fastcall **)(_QWORD *, __int64 *))(v1111[1] + 144LL);
if ( v46 )
v47 = v46(v1111, v45);
else
v47 = PyObject_GetAttr(v1111, v45);
v000 = (_QWORD *)v47;
if ( !v47 )
{
v19 = 2741;
LABEL_303:
v6 = 0LL;
goto LABEL_304;
}
v6 = sub_180005440(v47, data->int_6a, 6LL); // PyNumber_Rshift(),v1>>6
if ( !v6 )
{
v19 = 2743;
goto LABEL_296;
}
v16 = (*v000)-- == 1LL;
if ( v16 )
Py_Dealloc(v000);
v000 = (_QWORD *)PyNumber_Xor(AttrStrNoError, v6);// 两个结果异或 (v1<<3)^(v1>>6),结果存到v000中
if ( !v000 )
{
v19 = 2746;
goto LABEL_304;
}
v16 = (*AttrStrNoError)-- == 1LL;
if ( v16 )
Py_Dealloc(AttrStrNoError);
AttrStrNoError = 0LL;
v16 = (*(_QWORD *)v6)-- == 1LL;
if ( v16 )
Py_Dealloc(v6);
v48 = data->str_value;
v49 = *(__int64 (__fastcall **)(_QWORD *, __int64 *))(v1111[1] + 144LL);
if ( v49 )
v1_value2 = v49(v1111, v48);
else
v1_value2 = PyObject_GetAttr(v1111, v48); // v1.value
v6 = v1_value2;
if ( !v1_value2 )
{
v19 = 2750;
goto LABEL_296;
}
AttrStrNoError = (_QWORD *)PyNumber_Add(v000, v1_value2);// 把上面的结果与v1相加 (v1<<3)^(v1>>6) + v1
if ( !AttrStrNoError )
{
v19 = 2752;
LABEL_296:
v5 = 0LL;
goto LABEL_297;
}
v16 = (*v000)-- == 1LL;
if ( v16 )
Py_Dealloc(v000);
v16 = (*(_QWORD *)v6)-- == 1LL;
if ( v16 )
Py_Dealloc(v6);
v51 = data->str_value;
v52 = *(__int64 (__fastcall **)(__int64, __int64 *))(*(_QWORD *)(sum + 8) + 144LL);
if ( v52 )
sum_value = v52(sum, v51);
else
sum_value = PyObject_GetAttr(sum, v51); // sum.value
v6 = sum_value;
if ( !sum_value )
{
v19 = 2756;
goto LABEL_304;
}
v54 = data->str_value;
v55 = *(__int64 (__fastcall **)(__int64, __int64 *))(*(_QWORD *)(sum + 8) + 144LL);
if ( v55 )
sum_value1 = v55(sum, v54);
else
sum_value1 = PyObject_GetAttr(sum, v54); // 再获取一个sum.value
v000 = (_QWORD *)sum_value1;
if ( !sum_value1 )
{
v19 = 2758;
LABEL_304:
v5 = 0LL;
goto LABEL_305;
}
if ( *(_QWORD *)(sum_value1 + 8) == PyLong_Type[0] )
{
v57 = *(_DWORD *)(sum_value1 + 24);
if ( *(__int64 *)(sum_value1 + 16) <= 0 )
LOBYTE(v57) = -(char)v57;
sum_and_3 = PyLong_FromLong(v57 & 3);
}
else
{
sum_and_3 = PyNumber_And(sum_value1, data->int_3a);// sum & 3
}
v5 = (_QWORD *)sum_and_3;
if ( !sum_and_3 )
{
v19 = 2760;
goto LABEL_297;
}
v16 = (*v000)-- == 1LL;
if ( v16 )
Py_Dealloc(v000);
v000 = (_QWORD *)_Pyx_CyFunction_Init(a4, (__int64)v5);// 这里看似初始化一个函数其实是在通过索引寻找一个值,分析一下这个函数可以看到str___class_getitem,和一些index
// 这里是传进来的key[sum & 3]
if ( !v000 )
{
v19 = 2763;
goto LABEL_305;
}
v16 = (*v5)-- == 1LL;
if ( v16 )
Py_Dealloc(v5);
v5 = (_QWORD *)PyNumber_Add(v6, v000); // 把结果相加v6是sum,这里实现了sum + key[sum&3]
if ( !v5 )
{
v19 = 2766;
goto LABEL_297;
}
v16 = (*(_QWORD *)v6)-- == 1LL;
if ( v16 )
Py_Dealloc(v6);
v6 = 0LL;
v16 = (*v000)-- == 1LL;
if ( v16 )
Py_Dealloc(v000);
v000 = (_QWORD *)PyNumber_Xor(AttrStrNoError, v5);// 异或最终结果 这里实现了 ((v1<<3)^(v1>>6) + v1) ^ (sum + key[sum & 3])
if ( !v000 )
{
v19 = 2770;
LABEL_305:
v18 = 10;
LABEL_306:
v16 = (*v111)-- == 1LL;
if ( v16 )
Py_Dealloc(v111);
LABEL_308:
if ( AttrStrNoError )
{
v16 = (*AttrStrNoError)-- == 1LL;
if ( v16 )
Py_Dealloc(AttrStrNoError);
}
if ( v6 )
{
LABEL_312:
v16 = (*(_QWORD *)v6)-- == 1LL;
if ( v16 )
Py_Dealloc(v6);
}
if ( v5 )
{
LABEL_315:
AttrStrNoError = v98;
LABEL_316:
v16 = (*v5)-- == 1LL;
if ( v16 )
Py_Dealloc(v5);
LABEL_72:
v36 = delta;
_pyx_find_code_object("ez.encrypt", v19, v18, "ez.py");
v1111 = v100;
v37 = 0LL;
v35 = (_QWORD *)sum;
if ( AttrStrNoError )
goto LABEL_73;
goto LABEL_75;
}
LABEL_71:
AttrStrNoError = v98;
goto LABEL_72;
}
v16 = (*AttrStrNoError)-- == 1LL;
if ( v16 )
Py_Dealloc(AttrStrNoError);
AttrStrNoError = 0LL;
v16 = (*v5)-- == 1LL;
if ( v16 )
Py_Dealloc(v5);
v5 = (_QWORD *)PyNumber_InPlaceAdd(v111, v000);// v111是v0,v000是上面的最终结果,这里是v0 += v000
// v0 += ((v1<<3)^(v1>>6) + v1) ^ (sum + key[sum & 3])
if ( !v5 )
{
v19 = 2774;
LABEL_297:
v18 = 10;
goto LABEL_298;
}
v16 = (*v111)-- == 1LL;
if ( v16 )
Py_Dealloc(v111);
v111 = 0LL;
v16 = (*v000)-- == 1LL;
if ( v16 )
Py_Dealloc(v000);
v59 = data->str_value;
v60 = *(__int64 (__fastcall **)(_QWORD *, __int64 *, _QWORD *))(v98[1] + 152LL);
if ( v60 )
v61 = v60(v98, v59, v5);
else
v61 = PyObject_SetAttr(v98, v59, v5); // 设置v0.value为v5也就是上面相加的结果
if ( v61 < 0 )
{
v18 = 10;
v19 = 2778;
goto LABEL_315;
}
v16 = (*v5)-- == 1LL;
if ( v16 )
Py_Dealloc(v5);
v62 = data->str_value;
v63 = *(__int64 (__fastcall **)(__int64, __int64 *))(*(_QWORD *)(sum + 8) + 144LL);
if ( v63 )
v64 = v63(sum, v62);
else
v64 = PyObject_GetAttr(sum, v62); // sum.value
v5 = (_QWORD *)v64;
if ( !v64 )
{
v19 = 2788;
goto LABEL_71;
}
v000 = (_QWORD *)PyNumber_InPlaceAdd(v64, delta);// sum += delta
if ( !v000 )
{
v19 = 2790;
goto LABEL_315;
}
v16 = (*v5)-- == 1LL;
if ( v16 )
Py_Dealloc(v5);
v5 = 0LL;
v65 = data->str_value;
v66 = *(__int64 (__fastcall **)(__int64, __int64 *, _QWORD *))(*(_QWORD *)(sum + 8) + 152LL);
if ( v66 )
v67 = v66(sum, v65, v000);
else
v67 = PyObject_SetAttr(sum, v65, v000); // 设置sum.value的值为上面的结果
if ( v67 < 0 )
{
v19 = 2793;
goto LABEL_298;
}
v16 = (*v000)-- == 1LL;
if ( v16 )
Py_Dealloc(v000);
v68 = data->str_value;
v69 = *(__int64 (__fastcall **)(_QWORD *, __int64 *))(v1111[1] + 144LL);
if ( v69 )
v1_value3 = v69(v1111, v68);
else
v1_value3 = PyObject_GetAttr(v1111, v68); // v1.value
v000 = (_QWORD *)v1_value3;
if ( !v1_value3 )
{
v18 = 12;
v19 = 2803;
goto LABEL_71;
}
v71 = data->str_value;
v72 = *(__int64 (__fastcall **)(_QWORD *, __int64 *))(v98[1] + 144LL);
if ( v72 )
v0_value = v72(v98, v71);
else
v0_value = PyObject_GetAttr(v98, v71); // v0.value
v5 = (_QWORD *)v0_value;
if ( !v0_value )
{
v18 = 12;
v19 = 2805;
goto LABEL_298;
}
v111 = (_QWORD *)sub_180005330(v0_value, (__int64)data->int_3a);// lshift, v0 << 3
if ( !v111 )
{
v18 = 12;
v19 = 2807;
goto LABEL_298;
}
v16 = (*v5)-- == 1LL;
if ( v16 )
Py_Dealloc(v5);
v74 = data->str_value;
v75 = *(__int64 (__fastcall **)(_QWORD *, __int64 *))(v98[1] + 144LL);
if ( v75 )
v76 = v75(v98, v74);
else
v76 = PyObject_GetAttr(v98, v74);
v5 = (_QWORD *)v76;
if ( !v76 )
{
v18 = 12;
v19 = 2810;
goto LABEL_298;
}
AttrStrNoError = (_QWORD *)sub_180005440(v76, data->int_6a, 6LL);// rshift,v0 >> 6
if ( !AttrStrNoError )
{
v18 = 12;
v19 = 2812;
goto LABEL_298;
}
v16 = (*v5)-- == 1LL;
if ( v16 )
Py_Dealloc(v5);
v5 = (_QWORD *)PyNumber_Xor(v111, AttrStrNoError);// (v0 << 3) ^ (v0 >> 6)
if ( !v5 )
{
v18 = 12;
v19 = 2815;
goto LABEL_298;
}
v16 = (*v111)-- == 1LL;
if ( v16 )
Py_Dealloc(v111);
v111 = 0LL;
v16 = (*AttrStrNoError)-- == 1LL;
if ( v16 )
Py_Dealloc(AttrStrNoError);
v77 = data->str_value;
v78 = *(__int64 (__fastcall **)(_QWORD *, __int64 *))(v98[1] + 144LL);
if ( v78 )
v0_value2 = v78(v98, v77);
else
v0_value2 = PyObject_GetAttr(v98, v77); // v0.value
AttrStrNoError = (_QWORD *)v0_value2;
if ( !v0_value2 )
{
v18 = 12;
v19 = 2819;
goto LABEL_298;
}
v111 = (_QWORD *)PyNumber_Add(v5, v0_value2);// (v0 << 3) ^ (v0 >> 6) + v0
if ( !v111 )
{
v18 = 12;
v19 = 2821;
goto LABEL_298;
}
v16 = (*v5)-- == 1LL;
if ( v16 )
Py_Dealloc(v5);
v5 = 0LL;
v16 = (*AttrStrNoError)-- == 1LL;
if ( v16 )
Py_Dealloc(AttrStrNoError);
v80 = data->str_value;
v81 = *(__int64 (__fastcall **)(__int64, __int64 *))(*(_QWORD *)(sum + 8) + 144LL);
if ( v81 )
sum_value2 = v81(sum, v80);
else
sum_value2 = PyObject_GetAttr(sum, v80); // sum.value
AttrStrNoError = (_QWORD *)sum_value2;
if ( !sum_value2 )
{
v18 = 12;
v19 = 2825;
goto LABEL_298;
}
v83 = data->str_value;
v84 = *(__int64 (__fastcall **)(__int64, __int64 *))(*(_QWORD *)(sum + 8) + 144LL);
if ( v84 )
sum_value3 = v84(sum, v83);
else
sum_value3 = PyObject_GetAttr(sum, v83); // sum.value3
v5 = (_QWORD *)sum_value3;
if ( !sum_value3 )
{
v18 = 12;
v19 = 2827;
goto LABEL_298;
}
v6 = sub_180005440(sum_value3, data->int_11a, 11LL);// rshift,sum >> 11
if ( !v6 )
{
v18 = 12;
v19 = 2829;
goto LABEL_298;
}
v16 = (*v5)-- == 1LL;
if ( v16 )
Py_Dealloc(v5);
if ( *(_QWORD *)(v6 + 8) == PyLong_Type[0] )
{
v86 = *(_DWORD *)(v6 + 24);
if ( *(__int64 *)(v6 + 16) <= 0 )
LOBYTE(v86) = -(char)v86;
v87 = PyLong_FromLong(v86 & 3);
}
else
{
v87 = PyNumber_And(v6, data->int_3a); // (sum >> 11) & 3
}
v5 = (_QWORD *)v87;
if ( !v87 )
{
v18 = 12;
v19 = 2832;
goto LABEL_298;
}
v16 = (*(_QWORD *)v6)-- == 1LL;
if ( v16 )
Py_Dealloc(v6);
v6 = _Pyx_CyFunction_Init(a4, (__int64)v5); // key[(sum >> 11) & 3]
if ( !v6 )
{
v18 = 12;
v19 = 2835;
goto LABEL_298;
}
v16 = (*v5)-- == 1LL;
if ( v16 )
Py_Dealloc(v5);
v5 = (_QWORD *)PyNumber_Add(AttrStrNoError, v6);// sum + key[(sum >> 11) & 3]
if ( !v5 )
{
v18 = 12;
v19 = 2838;
goto LABEL_298;
}
v16 = (*AttrStrNoError)-- == 1LL;
if ( v16 )
Py_Dealloc(AttrStrNoError);
AttrStrNoError = 0LL;
v16 = (*(_QWORD *)v6)-- == 1LL;
if ( v16 )
Py_Dealloc(v6);
v6 = PyNumber_Xor(v111, v5); // ((v0 << 3) ^ (v0 >> 6) + v0) ^ (sum + key[(sum >> 11) & 3])
if ( !v6 )
{
v18 = 12;
v19 = 2842;
goto LABEL_298;
}
v16 = (*v111)-- == 1LL;
if ( v16 )
Py_Dealloc(v111);
v111 = 0LL;
v16 = (*v5)-- == 1LL;
if ( v16 )
Py_Dealloc(v5);
v5 = (_QWORD *)PyNumber_InPlaceAdd(v000, v6);// v000是v1,v1 += ((v0 << 3) ^ (v0 >> 6) + v0) ^ (sum + key[(sum >> 11) & 3])
if ( !v5 )
{
v18 = 12;
v19 = 2846;
goto LABEL_298;
}
v16 = (*v000)-- == 1LL;
if ( v16 )
Py_Dealloc(v000);
v16 = (*(_QWORD *)v6)-- == 1LL;
if ( v16 )
Py_Dealloc(v6);
v88 = data->str_value;
v89 = *(__int64 (__fastcall **)(_QWORD *, __int64 *, _QWORD *))(v1111[1] + 152LL);
if ( v89 )
v90 = v89(v1111, v88, v5);
else
v90 = PyObject_SetAttr(v1111, v88, v5); // 设置v1.value的值
if ( v90 < 0 )
{
v18 = 12;
v19 = 2850;
goto LABEL_315;
}
v16 = (*v5)-- == 1LL;
if ( v16 )
Py_Dealloc(v5);
AttrStrNoError = v98;
++v105;
}
while ( v105 < 64 ); // 循环64次
v91 = data->str_value;
v92 = *(__int64 (__fastcall **)(_QWORD *, __int64 *))(v98[1] + 144LL);
if ( v92 )
v93 = v92(v98, v91);
else
v93 = PyObject_GetAttr(v98, v91); // v0.value
v5 = (_QWORD *)v93; // 赋值到v5
if ( !v93 )
{
v18 = 14;
v19 = 2862;
goto LABEL_72;
}
v94 = data->str_value;
v95 = *(__int64 (__fastcall **)(_QWORD *, __int64 *))(v1111[1] + 144LL);
if ( v95 )
v96 = v95(v1111, v94);
else
v96 = PyObject_GetAttr(v1111, v94); // v1.value
v6 = v96; // 赋值到v6
if ( !v96 )
{
v18 = 14;
v19 = 2864;
goto LABEL_316;
}
v97 = PyTuple_New(2LL); // 创建一个两个元素的元组
v37 = v97;
if ( !v97 )
{
v18 = 14;
v19 = 2866;
goto LABEL_312;
}
*(_QWORD *)(v97 + 24) = v5; // 把v0,v1保存到元组中用于返回
v36 = delta;
*(_QWORD *)(v97 + 32) = v6;
LABEL_73:
v16 = (*AttrStrNoError)-- == 1LL;
if ( v16 )
Py_Dealloc(AttrStrNoError);
LABEL_75:
if ( v1111 )
{
v16 = (*v1111)-- == 1LL;
if ( v16 )
Py_Dealloc(v1111);
}
if ( v36 )
{
v16 = (*v36)-- == 1;
if ( v16 )
Py_Dealloc(v36);
}
if ( v35 )
{
v16 = (*v35)-- == 1LL;
if ( v16 )
Py_Dealloc(v35);
}
return v37;
}

ez.check函数就是在比对密文。

大概逻辑,魔改xtea

1
2
3
4
5
6
7
8
9
v0 
v1
delta = 1415865428
sum = 0

v0 += ((v1<<3)^(v1>>6) + v1) ^ (sum + key[sum & 3])
sum += delta
v1 += ((v0 << 3) ^ (v0 >> 6) + v0) ^ (sum + key[(sum >> 11) & 3])
rounds 64

密文是下面这些,在_Pyx_InitConstants(_)函数中,这里被保存到了一个列表中,里面的值就是上面的整数常量。

image-20250127191838471

也可以用dir查看对象,直接打印密文。运行的时候记得要用相同的python版本运行这里是python3.11

1
2
3
4
import ez

print(dir(ez))
print(ez.data)

image-20250127192256014

最终解密脚本

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
#include<stdio.h>
#include<stdint.h>

void encrypt(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;

for (i = 0; i < num_rounds; i++) {
v0 += (((v1 << 3) ^ (v1 >> 6)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 3) ^ (v0 >> 6)) + v0) ^ (sum + key[(sum >> 11) & 3]);
}
v[0] = v0; v[1] = v1;
}

void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 1415865428, sum = delta * num_rounds;

for (i = 0; i < num_rounds; i++) {
v1 -= (((v0 << 3) ^ (v0 >> 6)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 3) ^ (v1 >> 6)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0; v[1] = v1;
}

int main() {
uint32_t v[6] = { 2248247555, 947843023, 345309213, 3805970057, 1592923520, 3785781401 };
uint32_t const k[4] = { 102, 108, 97, 103 };
unsigned int r = 64;
printf("\n");
for (int i = 0; i < 6; i+=2) {
decipher(r, &v[i], k);
}

for (int i = 0; i < 6; i++) {
for (int j = 0; j < 4; j++) {
printf("%c", (v[i] >> ((3 - j) * 8)) & 0xff);
}
}
return 0;
}
//flag{8dMPY8sj2caUUlqmxK}

rand0m

pyd逆向,先看python层。调用了rand0m函数加密并检查了flag{}内的内容。用help()和dir()函数也没看到有用的信息。

dia打开pyd文件发现是python3.12,编译一个相同版本的pyd文件用bindiff恢复符号。

恢复结构体

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
typedef struct _iint {
__int64* int_0;
__int64* int_1;
__int64* int_2;
__int64* int_3;
__int64* int_4;
__int64* int_5;
__int64* int_6;
__int64* str_wenhao;
__int64* str_asy;
__int64* str_check;
__int64* str___class_getitem__;
__int64* str_cline_in_traceback;
__int64* str_delta;
__int64* str_enc;
__int64* str_flag;
__int64* str_i;
__int64* str__is_continue;
__int64* str_main;
__int64* str_name;
__int64* str_rand0m;
__int64* str_rand0m_py;
__int64* str_range;
__int64* str_ret;
__int64* str_right;
__int64* str_seed;
__int64* str_sum;
__int64* str_test_;
__int64* str_tmp;
__int64* str_x;
__int64* int_0a;
__int64* int_1a;
__int64* int_2a;
__int64* int_4a;
__int64* int_5a;
__int64* int_8a;
__int64* int_11a;
__int64* int_16a;
__int64* int_23a;
__int64* int_65537a;
__int64* int_37360232a;
__int64* int_304643896a;
__int64* int_1244723021a;
__int64* int_2282784775a;
__int64* int_2563918650a;
__int64* int_2654435769a;
__int64* int_2918417411a;
__int64* int_3628702646a;
__int64* int_3773946743a;
__int64* int_4198170623a;
__int64* int_4294967293a;
__int64* int_50;
__int64* int_51;
__int64* int_52;
__int64* int_53;
__int64* int_54;
__int64* int_55;
__int64* int_56;
__int64* int_57;
__int64* int_58;
__int64* int_59;
__int64* int_60;
__int64* int_61;
__int64* int_62;
__int64* int_63;
} iint;

在字符串表找到”rand0m.check”交叉引用查看check函数,这里因为恢复了符号的关系,函数名有点问题,不过不影响。

发现有两处引用先看第一处,其实就是在初始化上下文信息并调用check函数,也就是_Pyx_VerifyCachedType_0()

image-20250128021530782

check函数的逻辑大概是

1
2
3
4
5
6
7
8
9
check:
data=[304643896,2563918650,1244723021,3773946743,37360232,2918417411,2282784775,3628702646]

i=0
result = rand0m(input[i * 8:(i+1)*8:]) # 对我们输入的字符串8个字符切片,由rand0m函数可知这是4字节的数据
compare(result[1],data[i]) #比较结果
compare(result[0],data[i+1])
i++
#循环多次知道字符串处理完毕

再看rand0m函数,用搜索字符串方式找到,同样会有一个是初始化函数。逻辑大概如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
rand0m:

v12 = int(input,16) #会把我们的输入从16进制转为10进制,说明我们的输入是16进制字符,一共4字节

v12 ^ 2654435769
v12 >> 5 >> 23
(v12 << 4) & 4198170623

((v12 << 4) & 4198170623) + (v12 >> 5 >> 23)
(((v12 ^ 2654435769) >> 11) ** 65537) % 4294967293

res[0] = (((v12 ^ 2654435769) >> 11) ** 65537) % 4294967293
res[1] = ((v12 << 4) & 4198170623) + (v12 >> 5 >> 23)
return res

从上面可以看到res的两个结果是由同一个值(我们的输入)计算出来的,其中涉及到一些位运算,这可以用z3求解器求解,而另一个涉及到了模和幂的运算是几乎不可能被反推的。但是z3求解器只能求解出其中一个解,而((v12 << 4) & 4198170623) + (v12 >> 5 >> 23)有很多的解。或许我们可以可以用res[0]的值来确定这个唯一解。即用z3求出来的一个结果传入rand0m.rand0m函数,拿res的值和正确的值比较,并不断添加条件,知道我们求出与原密文相同的解。

脚本如下

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
from z3 import*
import rand0m


flag =""
for i in range(0, 8, 2):
data = [304643896,2563918650,1244723021,3773946743,37360232,2918417411,2282784775,3628702646]

v12 = BitVec("input", 32) #创建一个向量未知量,用于位运算
s = Solver()
dt = ((v12 << 4) & 4198170623) + (v12 >> 28) # 运算逻辑

s.add(And(data[i] - 0x10 <= dt, dt <= data[i] + 0x10)) #位运算有误差,把满足的条件放大会更好找答案

while s.check() == sat: #如果有解
module = s.model()
result = module[v12].as_long() #获取结果为python整数,以便进行下面的操作
result_hex = hex(result)[2:] #转16进制字符串并去掉开头的0x
check = rand0m.rand0m(result_hex) #传入rand0m函数获取res值
if check[0] == data[i+1] and check[1] == data[i]: #验证res的两个值是否符合,注意这里比较的顺序
print(f"{result_hex}")
flag += result_hex
break
s.add(v12 != result) #如果不符合则添加条件排除当前值
print(f"flag{{{flag}}}") #输出flag
# flag{813a97f3d4b34f74802ba12678950880}