SCTF 2024 Re wp [复现]

BBOX

image-20250511205127753

strange.encode跟进去没发现什么,jeb打开看下

能看了

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
package com.example.bbandroid;

import android.support.v4.graphics.drawable.ۤۧۦ۠;
import android.support.v4.graphics.drawable.ۦ۠ۤۨ;
import androidx.activity.ۥۦۨۧ;
import androidx.appcompat.content.res.۠ۡ۟۠;
import androidx.appcompat.content.res.ۣۤۦۦ;
import androidx.appcompat.graphics.drawable.۟ۦ۟ۥۦ;
import androidx.appcompat.graphics.drawable.ۣۢۨ;
import androidx.appcompat.resources.ۥۣ۟۟;
import androidx.appcompat.widget.۟۠ۤۢۧ;
import androidx.arch.core.۟ۦۥ۠ۢ;
import androidx.arch.core.ۦۢۨۥ;
import androidx.cardview.ۣ۟ۢۤۧ;
import androidx.constraintlayout.core.motion.key.ۢۥۣ۠;
import androidx.constraintlayout.core.motion.key.ۢۧۨۢ;
import androidx.constraintlayout.core.motion.parse.ۣۢۢۨ;
import androidx.constraintlayout.core.motion.utils.ۣ۟۠ۨۥ;
import androidx.constraintlayout.core.motion.utils.۟ۡۦۢۤ;
import androidx.constraintlayout.core.motion.utils.ۡۨۢ;
import androidx.constraintlayout.core.state.ۦۣۧۦ;
import androidx.constraintlayout.core.state.ۨۤ۟;
import androidx.constraintlayout.core.widgets.analyzer.۟ۡۧ۠ۢ;
import androidx.constraintlayout.utils.widget.ۢۡۤۡ;
import androidx.coordinatorlayout.widget.۟ۧ۠ۧۥ;
import androidx.coordinatorlayout.۟ۦ۟ۢ۠;
import androidx.core.accessibilityservice.ۧۤۤۨ;
import androidx.core.animation.ۥۧۡۤ;
import androidx.core.app.unusedapprestrictions.ۣۣ۟ۤۨ;
import androidx.core.app.unusedapprestrictions.۟ۦۣۡۥ;
import androidx.core.app.unusedapprestrictions.ۣ۟ۧ۟ۡ;
import androidx.core.content.res.ۣۧۡ۟;
import androidx.core.graphics.drawable.ۣۣ۟ۤۦ;
import androidx.core.hardware.fingerprint.۟۟ۥۡۢ;
import androidx.core.hardware.fingerprint.ۡۥۨۤ;
import androidx.core.internal.ۤۢۤۤ;
import androidx.core.ktx.۟۠ۡۡۥ;
import androidx.core.net.ۦۡۤۡ;
import androidx.core.os.ۦۤۦۤ;
import androidx.core.telephony.mbms.ۤۧۤ۟;
import androidx.core.text.method.ۣۡۤ۟;
import androidx.core.text.۟ۥۢۤۧ;
import androidx.core.text.۟ۦۣۧۦ;
import androidx.core.text.۟ۨۥ۟;
import androidx.core.transition.ۥۡۥۢ;
import androidx.core.view.autofill.ۦۡۢۡ;
import androidx.cursoradapter.widget.۟ۤۥۢ;
import androidx.customview.view.ۡۦۡۨ;
import androidx.customview.ۣ۟ۢ۟ۧ;
import androidx.documentfile.provider.ۣ۟۟۟ۡ;
import androidx.documentfile.provider.۟۟۟ۧۨ;
import androidx.documentfile.ۨۨ۟ۥ;
import androidx.dynamicanimation.animation.۟ۤۥ۟ۥ;
import androidx.dynamicanimation.animation.۟ۥۨۤ۟;
import androidx.emoji2.text.flatbuffer.۟۟ۥۢۦ;
import androidx.emoji2.text.flatbuffer.ۡۡ۠۟;
import androidx.emoji2.۟۠۟ۦ;
import androidx.interpolator.ۧ۟ۤۧ;
import androidx.legacy.coreutils.۟ۥۤۦۤ;
import androidx.lifecycle.۟ۧۤۦ۠;
import androidx.loader.ۣۤۧۢ;
import androidx.localbroadcastmanager.ۣۧۢ۠;
import androidx.profileinstaller.ۢۨۦۤ;
import androidx.profileinstaller.ۦ۠ۢ;
import androidx.resourceinspection.annotation.ۤۡۥۥ;
import androidx.startup.ۣ۟ۧ۠ۧ;
import androidx.vectordrawable.۟ۡ۠ۤۨ;
import androidx.versionedparcelable.۟ۡ۟ۨ;
import androidx.viewbinding.۠ۨ۟ۥ;
import androidx.viewpager.۟۟ۤۥۨ;
import androidx.viewpager2.ۤۨۦ۟;
import com.example.bbandroid.databinding.ۡۡۡۧ;
import com.google.android.material.animation.ۥۣۣۢ;
import com.google.android.material.appbar.ۣ۟ۧ۠;
import com.google.android.material.badge.۟ۤۡۤۤ;
import com.google.android.material.bottomnavigation.ۣ۟۟ۡ۟;
import com.google.android.material.card.ۣۧۢۨ;
import com.google.android.material.carousel.ۨۨۦۥ;
import com.google.android.material.checkbox.۟ۢۡۤۨ;
import com.google.android.material.circularreveal.coordinatorlayout.ۨۤۦۢ;
import com.google.android.material.color.utilities.۟ۡ۟ۤۤ;
import com.google.android.material.color.ۣ۟۟ۤۦ;
import com.google.android.material.drawable.۠ۦۤۨ;
import com.google.android.material.motion.۟ۧۢۦۡ;
import com.google.android.material.progressindicator.ۨۡۦ;
import com.google.android.material.radiobutton.۟ۥۦۢۦ;
import com.google.android.material.radiobutton.ۤۦۧۧ;
import com.google.android.material.radiobutton.ۦۨۦ۠;
import com.google.android.material.resources.۟ۦ۟ۨۨ;
import com.google.android.material.resources.۟ۧۤۡۤ;
import com.google.android.material.resources.ۨ۟ۡ۠;
import com.google.android.material.search.ۨۥۣۦ;
import com.google.android.material.shadow.ۣ۟ۡۢ۟;
import com.google.android.material.snackbar.۟۠ۥۥ;
import com.google.android.material.stateful.ۥ۠ۢۦ;
import com.google.android.material.tabs.۟۠۟ۦۥ;
import com.google.android.material.theme.overlay.ۥۦۤۧ;
import com.google.android.material.tooltip.۟۟ۡۤۥ;
import com.google.android.material.tooltip.۟ۡۥۡ;
import com.google.android.material.transition.platform.۟۠۟ۧۡ;
import com.google.android.material.transition.ۡۧۥۣ;
import com.google.android.material.transition.ۤۤۢۧ;
import com.google.common.util.concurrent.ۨ۟ۨ۟;
import java.io.PrintStream;
import kotlin.collections.jdk8.۠ۦ۠ۧ;
import kotlin.collections.jdk8.ۣۢۥۨ;
import kotlin.collections.unsigned.ۥۢۧۤ;
import kotlin.coroutines.jvm.internal.ۣۨ۠ۦ;
import kotlin.enums.۟ۥۧۡ۠;
import kotlin.enums.ۤۧۢۤ;
import kotlin.experimental.۠۠ۥۨ;
import kotlin.internal.jdk7.۟۠ۦۦ;
import kotlin.internal.jdk7.۟ۡ۠ۢۡ;
import kotlin.internal.jdk7.ۣ۟۠ۦۢ;
import kotlin.internal.jdk7.ۢ۠ۦۧ;
import kotlin.io.۟ۥۥۥ۠;
import kotlin.jdk7.ۧۡ۟ۨ;
import kotlin.js.۟۟ۧۢۢ;
import kotlin.jvm.functions.ۣۧ۠ۤ;
import kotlin.jvm.internal.markers.ۡ۠ۤ۠;
import kotlin.jvm.jdk8.۟ۡۡ۠۟;
import kotlin.jvm.ۡۥ۠;
import kotlin.properties.ۥۥۨۦ;
import kotlin.sequences.۠ۤۤۤ;
import kotlin.streams.jdk8.ۣ۟ۢۡۦ;
import kotlin.system.۠۠ۥۦ;
import kotlin.text.jdk8.۟ۥ۟ۧ۠;
import kotlin.text.۟ۥ۠ۧۥ;
import kotlin.time.jdk8.ۣۡۡ۠;
import kotlin.time.jdk8.ۨ۠ۦۦ;
import kotlin.time.ۣۣ۟ۢۤ;
import kotlinx.coroutines.android.ۥۣ۠۟;
import kotlinx.coroutines.channels.۟۠ۨۤ۠;
import kotlinx.coroutines.channels.ۨ۠ۤ۟;
import kotlinx.coroutines.debug.ۣۣۣۡ;
import kotlinx.coroutines.scheduling.ۡ۟ۡ۟;
import kotlinx.coroutines.sync.ۦۤۧۥ;
import kotlinx.coroutines.sync.ۦۨۦۤ;
import np.protect.ۥۣۢۢ;

public class strange {
private static final char[] ALPHABET;
private static final int[] LOOKUP;
private static final short[] short;

// This method was "un-flattened"
static {
char[] arr_c;
strange.short = new short[]{0xB82, 0xB83, 0xB9C, 0xB9D, 0xB9E, 0xB9F, 0xB98, 0xBA8, 0xBA9, 0xBAA, 0xBAB, 2980, 0xBA5, 0xBA6, 0xBA7, 0xBA0, 0xB84, 0xB85, 2950, 0xB87, 0xB80, 3001, 3002, 3005, 3006, 3007, 3000, 3011, 3003, 0xBB4, 0xBB5, 0xBB6, 0xB8D, 0xB8E, 0xBAD, 2990, 0xBAF, 0xB8F, 0xB88, 0xB89, 0xB8A, 0xB8B, 0xB81, 0xB99, 2970, 3034, 3035, 3028, 3029, 3015, 0xB9B, 0xB94, 0xB95, 0xB96, 3036, 3037, 3038, 0xBDF, 3032, 3033, 0xBA1, 0xBA2, 0xBA3, 3004};
strange.ALPHABET = (char[])ۥۣۢۢ.n(0x9259, ((String)ۥۣۢۢ.n(0xFA8C, null, new Object[]{((short[])ۥۣۢۢ.n(70719)), ((int)0), ((int)(ۤۧۦ۠.۠۠ۦۥ ^ -750)), ((int)3052)})), new Object[0]);
int[] arr_v = new int[0x100];
strange.LOOKUP = arr_v;
do {
ۥۣۢۢ.n(92279, null, new Object[]{arr_v, ((int)(۟ۥۦۢۦ.۟ۧۢۨۢ ^ -668))});
arr_c = (char[])ۥۣۢۢ.n(4060);
int v = ۟ۧۢۦۡ.ۣ۟ۤ۟ۦ / ۨ۟ۨ۟.ۣۦۣ + 0x1AAB64;
if(0 >= arr_c.length) {
if(ۣۣۣۡ.ۦ۠ۨۦ >= 0) {
while(true) {
label_53:
goto label_53;
}
}

((int[])ۥۣۢۢ.n(87336))[61] = 0;
if(!((Boolean)ۥۣۢۢ.n(72724, null, new Object[]{((int)(۟ۦۣۡۥ.ۦۧۢ۟ ^ 0xFFFF940E))})).booleanValue()) {
if(۟ۥۢۤۧ.ۣۡۢۦ() > 0) {
v = ۤۢۤۤ.ۥۣۢ۟ % ۢۧۨۢ.ۤۤۨ۠ + 1755703;
return;
}

ۡۧۥۣ.ۥۦۧ۟ = 65;
while(true) {
label_73:
goto label_73;
}
}

throw new ArithmeticException("divide by zero");
}
}
while(ۦۡۢۡ.ۦ۠ۦ۟ <= 0);

while(true) {
int[] arr_v1 = (int[])ۥۣۢۢ.n(87336);
arr_v1[arr_c[0]] = 0;
}
}

public strange() {
Integer integer0 = null;
int v = ۧۤۤۨ.۟ۦۣۤۦ("\u06E5\u06DF");
label_9:
switch(v) {
case 0xDC9A: {
if(((int)(((Integer)ۥۣۢۢ.n(93572, null, new Object[0])))) > 0) {
goto label_92;
}

if(۟ۥ۠ۧۥ.۟ۦ۟۟۠() <= 0) {
v = ۣۡۤ۟.ۨۧ۠ۥ("\u06E5\u06DF");
goto label_9;
}

v = ۣۨ۠ۦ.ۤۢ۟ۢ - ۟۟ۡۤۥ.۟ۥۤۤۨ + 0x1AB339;
goto label_9;
}
case 0x1AA73F: {
ۥۣۢۢ.n(0x9101, ((PrintStream)ۥۣۢۢ.n(85270)), new Object[]{integer0});
if(ۧ۟ۤۧ.۟ۦۥۦۨ % (ۢ۠ۦۧ.۟ۥۧۤۤ * 6210) <= 0) {
v = ۣۣ۟ۢۤ.۟ۡۧۨۦ("ۧۡۢ");
goto label_9;
}

v = ۦۡۤۡ.ۣ۠ۤۡ("\u06E5\u06E8\u06E3");
goto label_9;
}
case 0x1AAF7B: {
Integer integer1 = (Integer)ۥۣۢۢ.n(21050, null, new Object[]{((String)ۥۣۢۢ.n(7196, null, new Object[]{((String)ۥۣۢۢ.n(46307))}))});
if(ۦۤۦۤ.۟ۤ۠ۢۢ + ۦۢۨۥ.ۣ۟ۧ۠۟ % 9043 >= 0) {
v = ۦۨۦۤ.ۢۤ۠ۤ("\u06E3\u06E8\u06E6");
integer0 = integer1;
goto label_9;
}

v = 0x1AA760 + (۟۠۟ۧۡ.۟ۦۣۡۨ | ۦۨۦۤ.ۥۣۣ۟);
integer0 = integer1;
goto label_9;
}
case 1750817: {
if(۟ۤۥۢ.ۣ۠ۥۦ % (ۡ۟ۡ۟.ۡۥ۟ۨ | 5202) > 0) {
v = ۢۡۤۡ.۟ۤۡۥۤ * ۟۠ۨۤ۠.ۦۧ۟ۨ + 0xBBB05;
goto label_9;
}

v = ۦۡۤۡ.ۣ۠ۤۡ("ۨۡۧ");
goto label_9;
}
case 0x1ABEA0: {
return;
}
case 1754440: {
label_92:
if(ۥ۠ۢۦ.ۣ۠ۥۥ() >= 0) {
v = ۟۟۟ۧۨ.۠ۥۨۤ("ۣۤۡ");
goto label_9;
}

v = ۟۟۟ۧۨ.۠ۥۨۤ("\u06E5\u06E8\u06E3");
}
default: {
goto label_9;
}
}
}

public static String encode(byte[] arr_b) {
char c6;
int v16;
char[] arr_c1;
int v18;
char c7;
boolean z = false;
int v = 0;
int v1 = 0;
int v2 = 0;
int v3 = 0;
int v4 = 0;
int v5 = 0;
int v6 = 0;
int v7 = 0;
int v8 = 0;
char[] arr_c = null;
char c = '\u0000';
char c1 = '\u0000';
char c2 = '\u0000';
char c3 = '\u0000';
char c4 = '\u0000';
char c5 = '\u0000';
int v9 = 0;
int v10 = 0;
int v11 = 0;
int v12 = 0;
int v13 = 0;
int v14 = ۢۨۦۤ.ۥ۟ۡۧ("\u06E1\u06E6\u06E6");
StringBuilder stringBuilder0 = null;
boolean z1 = false;
label_32:
switch(v14) {
case 0xDC24: {
v14 = ۣ۟۟۟ۡ.۟ۢۧۦۢ / ۠۠ۥۦ.ۤۧۢ۟ ^ 0xDC9B;
goto label_32;
}
case 56390: {
int v20 = (ۥۢۧۤ.۟ۦۤۢۦ ^ 0xFFFFFF40) + v9;
if(v20 >= arr_b.length) {
goto label_456;
}

int v21 = (۠ۤۤۤ.۟ۨۧۡ ^ -564) & arr_b[v20];
if(۟۟ۥۡۢ.ۧ۠ۦ۟ / (ۣ۟۠ۨۥ.ۥۨۦ۟ % 0xFFFFF888) <= 0) {
v5 = v21;
v14 = ۨۥۣۦ.ۨۧۤ("ۢۨ");
goto label_32;
}

v5 = v21;
v14 = ۠۠ۥۨ.۠ۡ۠۟("ۢۨۢ");
goto label_32;
}
case 0xDCDF: {
v6 = v4 + (ۨ۟ۡ۠.۠ۥ ^ 0x17F);
v14 = ۧۡ۟ۨ.۟ۢۤۡۤ - ۣ۟ۢۤۧ.ۨۡۧۤ ^ 0x1ABF23;
v7 = v3;
goto label_32;
}
case 0xDCFA: {
if(۟۠ۦۦ.ۧ۠ۢۦ - ۠ۦ۠ۧ.۟ۧۢۦۨ / 0xAB5 >= 0) {
ۦۢۨۥ.ۣ۟ۧ۠۟ = 66;
v14 = ۦ۠ۢ.ۣ۟ۤۥۦ("۠ۤۤ");
goto label_32;
}

v14 = ۟ۨۥ۟.۟ۤۡ۟۟ - ۢۥۣ۠.ۢۦۥۡ + 0x1AAD5B;
goto label_32;
}
case 0x1AA740: {
label_727:
if(۟ۦ۟ۨۨ.ۣ۟ۤ۠۠ <= 0) {
v14 = ۥۥۨۦ.۟۟۠ۨ۟("ۡۡۧ");
goto label_32;
}

v14 = ۟ۡۧ۠ۢ.۟ۢ۟۟ۦ / ۤۡۥۥ.۟ۤۤ۟ۢ + 1752490;
goto label_32;
}
case 0x1AAB02: {
throw new ArithmeticException("divide by zero");
}
case 0x1AAB60: {
StringBuilder stringBuilder5 = (StringBuilder)ۥۣۢۢ.n(0xA264, stringBuilder0, new Object[]{Character.valueOf(c5)});
int v25 = v9 + (۟ۥۦۢۦ.۟ۧۢۨۢ ^ 664);
if(ۣۣ۟ۤۨ.۟ۦۤۦۧ % (ۨۤ۟.ۥ۠ۢ - 0xA9F) <= 0) {
v14 = ۟۟ۥۢۦ.ۢۨ۠ۡ("\u06E6\u06E5\u06E6");
v9 = v25;
goto label_32;
}

v14 = ۦۨۦ۠.۟۟ۤۧۦ("\u06E6\u06E2\u06E5");
v9 = v25;
goto label_32;
}
case 0x1AABD7: {
if((۟ۦ۟ۥۦ.ۧۡۢۢ ^ (۟۠ۨۤ۠.ۦۧ۟ۨ | 0x340)) <= 0) {
v14 = ۣۨ۠ۦ.۟ۧ۟ۦۧ("\u06E1\u06E6\u06E6");
goto label_32;
}

v14 = ۟ۡ۠ۢۡ.۟۠۠ۨۥ("\u06E6\u06E7\u06E0");
v7 = v7;
goto label_32;
}
case 0x1AABD8: {
v11 = arr_b.length;
v14 = ۟۟۟ۧۨ.ۣۣۧ % ۥۣۣۢ.۟ۤ۠ۡۤ ^ 0xFFE53FC3;
v12 = arr_b.length;
v13 = 0;
goto label_32;
}
case 0x1AABA2:
case 0x1AABDB: {
if(ۣ۟۟ۡ۟.۟ۥۧۦۣ() >= 0) {
ۥۣ۠۟.ۣۦ۠ۥ = 11;
v14 = ۟۟ۥۡۢ.۟۟۟۠۟("\u06E6\u06E3\u06E8");
v10 = v10;
goto label_32;
}

v14 = ۣۡۡ۠.۟۟ۥۥۦ - ۣۧ۠ۤ.ۢۦۤ۟ + 0x1ABC76;
goto label_32;
}
case 0x1AAF3F: {
if(ۨ۟ۨ۟.ۣۦۣ / (ۣۣ۟ۤۦ.۟ۥۢۢۧ % 0xFFFFF8D9) != 0) {
v14 = ۨۨ۟ۥ.۟ۤ۠۟۟("ۤۡۨ");
goto label_32;
}

v14 = ۦۤۧۥ.ۡ۠ۡۢ("ۡ۠ۤ");
goto label_32;
}
case 0x1AAF61: {
boolean z2 = ((Boolean)ۥۣۢۢ.n(0xA587, new MainActivity(), new Object[0])).booleanValue();
boolean z3 = ((Boolean)ۥۣۢۢ.n(72724, null, new Object[]{((int)(ۨ۠ۤ۟.۟۠ۨۧۢ ^ 0xFFFF9745))})).booleanValue();
if(ۣۢۥۨ.۟ۢۢ۠۠ + (ۨۡۦ.۟ۤۥۤۤ ^ 0x26FF) <= 0) {
v14 = ۢ۠ۦۧ.ۣۡۡ۟("\u06E5\u06E7\u06E8");
z1 = z3;
z = z2;
goto label_32;
}

v14 = ۡۥۨۤ.ۡ۠ۡ۠ - ۣۤۦۦ.۟ۥۢۡۤ + 1750861;
z1 = z3;
z = z2;
goto label_32;
}
case 1749603: {
char c8 = arr_c[(۟ۥۥۥ۠.۟ۧ۟ۧ۠ ^ -998) & v7];
if(۟۟ۧۢۢ.ۦۡۦۥ() >= 0) {
ۢۡۤۡ.۟ۤۡۥۤ = 65;
v14 = ۤۦۧۧ.ۥۤۧۦ("\u06E3\u06E3\u06E6");
c4 = c8;
goto label_32;
}

v14 = ۡۡۡۧ.۟۟ۧۡۥ("ۤۢۢ");
c4 = c8;
goto label_32;
}
case 0x1AB2A8: {
v14 = ۟ۡۥۡ.۟ۢۧۧۡ - ۟ۧ۠ۧۥ.ۧ۠ۥۣ + 1756110;
c3 = c2;
goto label_32;
}
case 0x1AB35C: {
int v22 = v3 & v5 | v3 ^ v5;
if(ۤۧۤ۟.ۥۥۧ۟ - (ۦ۠ۤۨ.ۣ۟۠۠ۨ - 0x15F0) <= 0) {
v8 = v4;
v14 = ۟ۡ۠ۢۡ.۟۠۠ۨۥ("ۣۣۡ");
v7 = v22;
goto label_32;
}

v14 = ۦۡۤۡ.ۢ۟ۦۦ ^ ۣ۟ۧ۟ۡ.ۣۣۦۦ ^ 0xFFE554E6;
v7 = v22;
v8 = v4;
goto label_32;
}
case 1750568: {
int v19 = v13 + (۟۠ۡۡۥ.ۣۧۦۥ ^ 0x203);
if(ۣۢۢۨ.۟ۡ۠۟۠ + ۦ۠ۢ.ۨۡۨۤ * -2108 <= 0) {
v14 = ۣۡۤ۟.ۨۧ۠ۥ("ۢۨۢ");
v13 = v19;
goto label_32;
}

v14 = ۣۤۧۢ.۟۟ۢۢ - ۣۧ۠ۤ.ۢۦۤ۟ + 0xDE84;
v13 = v19;
goto label_32;
}
case 1750597: {
c7 = c;
goto label_632;
}
case 1750662: {
if((۟ۦ۟ۢ۠.ۥۣۨ۟ ^ (۟ۡۡ۠۟.ۦ۠۟ۥ ^ 3008)) <= 0) {
v14 = ۦۨۦ۠.۟۟ۤۧۦ("\u06E8\u06E6\u06E4");
v9 = v9;
goto label_32;
}

v14 = ۠ۡ۟۠.۟ۧۧۧ۠("\u06E1\u06E6\u06E6");
goto label_32;
}
case 0x1AB71F: {
if(!z1) {
v14 = ۦۨۦ۠.۟۟ۤۧۦ("\u06E5\u06E3\u06E2");
v9 = v9;
goto label_32;
}

v14 = ۥۣ۟۟.ۣۣۦۨ("ۣ۠ۡ");
goto label_32;
}
case 0x1AB9C5: {
c7 = '=';
if(v8 < 2) {
c1 = arr_c[v7 >> (۟ۥۧۡ۠.۟ۢۧۢۧ ^ 74) & (۠ۨ۟ۥ.ۣ۟ۥۣۨ ^ 0xFFFFFF40)];
v16 = v3;
c = '=';
v14 = ۦ۠ۤۨ.۟۟ۢۨ۟("\u06E7\u06E7\u06E5");
v3 = v16;
goto label_32;
}

label_632:
if(ۤۤۢۧ.ۣۧۨ۟ + ۣۧۢۨ.۟ۦۤۢۥ * -910 <= 0) {
v14 = ۣ۟ۢۤۧ.ۣ۟ۡۧۢ("ۡۤۤ");
c = c7;
goto label_32;
}

v14 = ۣ۟ۢۤۧ.ۣ۟ۡۧۢ("\u06E5\u06E7\u06E7");
c = c7;
goto label_32;
}
case 1751530: {
if(۟۠۟ۦۥ.ۢۡۥۦ >= 0) {
v14 = ۟۠۟ۧۡ.ۣۧۡۡ("\u06E7\u06E6");
v4 = v2;
goto label_32;
}

v4 = v2;
v14 = ۟۟ۥۡۢ.۟۟۟۠۟("ۢۨ");
v10 = v10;
goto label_32;
}
case 0x1ABA09: {
v2 = v10 + (۟۠ۤۢۧ.۠ۨۢ۠ ^ 403);
v14 = ۨۤۦۢ.ۣۣۨۧ("\u06E4\u06E0\u06E6");
v3 = v;
goto label_32;
}
case 0x1ABA0B: {
if(۟ۧۤۦ۠.۟۠ۥۣ۟() >= 0) {
۟ۨۥ۟.۟ۤۡ۟۟ = 21;
v14 = ۥۦۤۧ.۟ۥۧۦۢ("\u06E7\u06E5\u06E8");
v13 = 0;
goto label_32;
}

v14 = ۦۣۧۦ.ۡۨۤۢ / ۡۨۢ.۟ۢ۠۟ۤ + 0x1AC16C;
v13 = 0;
goto label_32;
}
case 0x1ABA24: {
if(ۣ۟ۧ۠.ۧۡ۠۟ <= 0) {
v14 = ۟ۡۦۢۤ.ۣ۟ۨۨ۟("\u06E4\u06E1\u06E6");
c5 = c4;
goto label_32;
}

v14 = ۟۟ۤۥۨ.ۥۤۢ۠ ^ ۨۤ۟.ۥ۠ۢ ^ 1747510;
c5 = c4;
goto label_32;
}
case 0x1ABA65: {
if(v9 >= arr_b.length) {
break;
}

int v26 = (arr_b[v9] & (۟ۢۡۤۨ.ۡ۠ۡۢ ^ 0xFFFFFF49)) << (ۤۨۦ۟.۟ۤۥۢۢ ^ 0xFFFFFCF0);
int v27 = v26 & (0xFF000000 ^ v26);
if((ۡۥ۠.ۦۧۧ | ۠ۦۤۨ.۟۟ۧۨۥ * 5237) >= 0) {
v = v27;
v14 = ۥۧۡۤ.۟ۢ۟ۢ("ۣۨۧ");
goto label_32;
}

v = v27;
v14 = ۣ۟ۢۡۦ.ۦۨ۠۠ % ۟۠ۡۡۥ.ۣۧۦۥ + 0x1ABE74;
goto label_32;
}
case 0x1ABA67: {
if(ۣۨ۠ۦ.ۤ۠ۨۦ() >= 0) {
۟ۥۤۦۤ.۟ۢۨ۟ۨ = 8;
v14 = ۟۠ۤۢۧ.۟ۧۡۦۥ("\u06E0\u06E6\u06E8");
v8 = v6;
goto label_32;
}

v8 = v6;
v14 = ۟۟ۤۥۨ.۟ۧ۠ۨ۠("\u06E5\u06E0\u06E5");
goto label_32;
}
case 0x1ABA82: {
label_456:
if(ۣ۟۠ۦۢ.۟۟۟ۤۦ < 0) {
v14 = ۨ۠ۦۦ.ۧۨۨۤ + ۡۦۡۨ.ۢۦۤۧ + 0xDD8B;
goto label_32;
}

v14 = ۟۟ۤۥۨ.۟ۧ۠ۨ۠("\u06E5\u06DF\u06E8");
goto label_32;
}
case 0x1ABDA9: {
return (String)ۥۣۢۢ.n(83074, stringBuilder0, new Object[0]);
}
case 1752490: {
arr_c1 = (char[])ۥۣۢۢ.n(4060);
StringBuilder stringBuilder2 = (StringBuilder)ۥۣۢۢ.n(0xA264, stringBuilder0, new Object[]{Character.valueOf(arr_c1[v7 >> (۟ۧۤۦ۠.۟ۤۧۤ۠ ^ 830) & (ۣۢۨ.۟ۤ۟۠ۡ ^ -1001)])});
StringBuilder stringBuilder3 = (StringBuilder)ۥۣۢۢ.n(0xA264, stringBuilder0, new Object[]{Character.valueOf(arr_c1[v7 >> (ۣۧۢ۠.ۨ۟ۥۤ ^ 0xFFFFFF27) & (ۥۢۧۤ.۟ۦۤۢۦ ^ 0xFFFFFF7D)])});
if(۟ۡ۟ۨ.ۣۤ۠ۢ >= 0) {
v18 = v1;
v14 = ۡ۠ۤ۠.ۧۥۣۦ("ۧ۟۠");
arr_c = arr_c1;
v1 = v18;
goto label_32;
}

arr_c = arr_c1;
v14 = ۟ۡ۟ۤۤ.ۨ۟ۥۦ("ۤ۟۠");
goto label_32;
}
case 0x1ABE04: {
StringBuilder stringBuilder1 = new StringBuilder();
v14 = ۣۤۧۢ.۟۟ۢۢ * ۟ۤۥ۟ۥ.۟ۡۤۤ۠ + 1794708;
stringBuilder0 = stringBuilder1;
goto label_32;
}
case 0x1ABE28: {
if((ۦۣۧۦ.ۡۨۤۢ | ۟ۥۨۤ۟.۠ۥۡۤ + 0x1C30) >= 0) {
v14 = ۥۦۨۧ.۟ۦۦۧ۟("ۣۨۤ");
goto label_32;
}

v5 = v5;
v14 = ۠۠ۥۨ.۠ۡ۠۟("ۧۨۧ");
goto label_32;
}
case 0x1ABE3F: {
int v17 = (ۤۦۧۧ.ۨۥۢۢ ^ 804) + v9;
if(v17 >= arr_b.length) {
goto label_547;
}

v18 = (arr_b[v17] & (۟ۡ۠ۤۨ.ۥۥۡۤ ^ 108)) << (۟۠۟ۦۥ.ۢۡۥۦ ^ 0xFFFFFF26);
if(۟ۦۥ۠ۢ.ۣۤۥۤ * (۟ۦۣۡۥ.ۦۧۢ۟ % -5686) <= 0) {
v1 = v18;
v14 = ۠ۤۤۤ.۟۟ۥۧۥ("\u06E4\u06E5\u06E3");
goto label_32;
}

arr_c1 = arr_c;
v14 = ۡ۠ۤ۠.ۧۥۣۦ("ۧ۟۠");
arr_c = arr_c1;
v1 = v18;
goto label_32;
}
case 1752709: {
v14 = ۦۨۦۤ.ۥۣۣ۟ / ۥۢۧۤ.۟ۦۤۢۦ + 0x1AB2A8;
c2 = '=';
goto label_32;
}
case 0xDC9A:
case 1752710: {
v14 = ۣ۟ۧ۠.ۧۡ۠۟ + ۣۢۥۨ.۟ۢۢ۠۠ + 0x1ABF31;
goto label_32;
}
case 0x1AC148: {
if(z) {
v14 = ۣ۟ۧ۠.ۧۡ۠۟ + ۣۢۥۨ.۟ۢۢ۠۠ + 0x1ABF31;
goto label_32;
}

int v23 = v11 + (۟ۤۡۤۤ.ۢۢۥۨ ^ 0xFFFFFF03);
if(۟ۧ۠ۧۥ.ۧ۠ۥۣ * (۟ۦ۟ۢ۠.ۥۣۨ۟ / 9880) != 0) {
v14 = ۣ۟ۡۢ۟.۟ۤۥۣۡ("ۧۨۧ");
v12 = v23;
goto label_32;
}

v14 = ۡۡ۠۟.۟ۡۧ۟ۡ("ۤۡۨ");
v12 = v23;
goto label_32;
}
case 0x1AC16C: {
if(v13 >= ((int)(((Integer)ۥۣۢۢ.n(31260, stringBuilder0, new Object[0]))))) {
goto label_727;
}

int v24 = ((Character)ۥۣۢۢ.n(0x8890, stringBuilder0, new Object[]{v13})).charValue();
ۥۣۢۢ.n(96695, stringBuilder0, new Object[]{v13, Character.valueOf(((char)(v24 & (v12 ^ -1) | (v24 ^ -1) & v12)))});
v14 = ۟ۧۤۡۤ.ۣۣ۟ۧۢ("\u06E3\u06E0\u06E5");
goto label_32;
}
case 0x1AC18C: {
break;
}
case 0x1AC1A9: {
v14 = ۟۟ۥۡۢ.۟۟۟۠۟("ۨۢ");
v10 = v8;
goto label_32;
}
case 0x1AC1C8: {
label_547:
if((ۤۡۥۥ.۟ۤۤ۟ۢ ^ ۣ۟۟ۤۦ.۟ۢۧۢ۟ * 7622) >= 0) {
v5 = v5;
v14 = ۠۠ۥۨ.۠ۡ۠۟("\u06E3\u06E6\u06E4");
goto label_32;
}

v14 = (۟۠ۥۥ.ۣۤۢ | ۡۡ۠۟.ۧ۠ۨۨ) + 0x1ABA13;
goto label_32;
}
case 0x1AC207: {
v14 = ۦۨۦ۠.۟۟ۤۧۦ("\u06E5\u06E3\u06E2");
v9 = v9;
goto label_32;
}
case 0x1AB35D:
case 0x1AC23F: {
if(۟ۥ۟ۧ۠.۟ۢۨۡۥ() >= 0) {
ۣ۟ۧ۠ۧ.ۨۦۣ۠ = 67;
v14 = ۣ۟ۢ۟ۧ.۟ۢۦۡۤ("۟ۨۤ");
goto label_32;
}

v14 = ۤۧۢۤ.۠۠۠ - ۟ۥۢۤۧ.۟ۥۣۦۤ + 1752101;
goto label_32;
}
case 0x1AC508: {
int v15 = v ^ v1 | v & v1;
if((۟۟۟ۧۨ.ۣۣۧ ^ ۣۧۡ۟.ۣۧۢۡ - 0xA6B) <= 0) {
v16 = v15;
v4 = v10;
v14 = ۦ۠ۤۨ.۟۟ۢۨ۟("\u06E7\u06E7\u06E5");
v3 = v16;
goto label_32;
}

v14 = ۥۦۨۧ.ۤۥۦۧ + ۦۨۦ۠.ۦ۠ۤۤ + 0x1AA90D;
v3 = v15;
v4 = v10;
goto label_32;
}
case 0x1AAEA5:
case 1754570: {
v14 = ۦۨۦ۠.۟۟ۤۧۦ("ۢۨ");
v9 = v9;
goto label_32;
}
case 0x1AC605: {
if(۟ۡ۟ۨ.۟۟۟۠ۧ() <= 0) {
v14 = ۟۠ۨۤ۠.ۣۥۢ("\u06E5\u06E0\u06E4");
c3 = c1;
goto label_32;
}

v14 = ۟ۦۣۧۦ.۟ۦۨۧۧ("\u06E5\u06E4\u06E7");
c3 = c1;
goto label_32;
}
case 0x1AC620: {
v14 = ۟۠ۤۢۧ.۟ۧۡۦۥ("\u06E4\u06E4\u06E5");
v9 = 0;
goto label_32;
}
case 0x1AC1C9:
case 0x1AC626: {
if(ۨۨۦۥ.ۦۣ۠ۡ() >= 0) {
v14 = ۥۣۣۢ.۟ۧ۠ۦۧ("\u06E4\u06E5\u06E1");
goto label_32;
}

v14 = ۟ۡ۟ۤۤ.ۣ۟۟ۡۧ * ۟۠۟ۦ.ۦ۠ۢۧ + 0xFEF37;
goto label_32;
}
case 0x1AC8EE: {
c6 = c5;
v14 = ۥۡۥۢ.ۡۨۧۥ("۠ۤۤ");
c5 = c6;
goto label_32;
}
case 0x1AC949: {
StringBuilder stringBuilder4 = (StringBuilder)ۥۣۢۢ.n(0xA264, stringBuilder0, new Object[]{Character.valueOf(c3)});
if(v8 < 1) {
if(۟ۥۤۦۤ.۟ۢۨ۟ۨ >= 0) {
c5 = c;
goto label_593;
}

v14 = ۟ۥۤۦۤ.ۨۦ("ۢ۠ۡ");
c5 = c;
goto label_32;
}

c6 = c;
v14 = ۥۡۥۢ.ۡۨۧۥ("۠ۤۤ");
c5 = c6;
goto label_32;
}
case 0x1AC94C: {
v10 = 0;
label_593:
v14 = ۡۡ۠۟.۟ۡۧ۟ۡ("ۧۨۡ");
v12 = v12;
}
default: {
goto label_32;
}
}

v14 = ۟ۥۢۤۧ.۟ۥۣۦۤ - ۟ۦۥ۠ۢ.ۣۤۥۤ + 1747730;
goto label_32;
}
}

做了混淆,控制流平坦化,还有什么变量都变了…

直接找so

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
const char *__fastcall Java_com_example_bbandroid_MainActivity_checkFlag(__int64 a1, __int64 a2, __int64 a3)
{
int v5; // w22
const char *src; // x0
const char *src_1; // x21
unsigned int seed; // w23
int n4; // w22
__int64 v10; // x19
__int64 v11; // x20
char *v12; // x22
char v13; // w0
int n32; // w9
signed int v15; // w8
unsigned __int64 n39; // x10
unsigned __int64 n0x26; // x11
int v18; // w12
int v19; // w13
char dest[256]; // [xsp+8h] [xbp-108h] BYREF
__int64 v21; // [xsp+108h] [xbp-8h]

v21 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
v5 = time(0LL);
src = (const char *)(*(__int64 (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)a1 + 1352LL))(a1, a3, 0LL);
if ( src )
{
src_1 = src;
seed = v5 / 1000000 / 100;
strncpy(dest, src, 0xFFuLL);
dest[255] = 0;
n4 = __strlen_chk(dest, 0x100uLL);
(*(void (__fastcall **)(__int64, __int64, const char *))(*(_QWORD *)a1 + 1360LL))(a1, a3, src_1);
srand(seed);
if ( n4 >= 4 )
{
v10 = 0LL;
v11 = (unsigned int)n4 >> 2;
do
{
v12 = &dest[4 * v10];
*v12 ^= rand();
v12[1] ^= rand();
v12[2] ^= rand();
v13 = rand();
n32 = 32;
v12[3] ^= v13;
v15 = *(_DWORD *)v12;
do
{
if ( v15 >= 0 )
v15 *= 2;
else
v15 = (2 * v15) ^ 0x85B6874F;
--n32;
}
while ( n32 );
*(_DWORD *)&dest[4 * v10++] = v15;
}
while ( v10 != v11 );
}
if ( dest[0] == 51 )
{
n39 = 0LL;
do
{
n0x26 = n39;
if ( n39 == 39 )
break;
v18 = (unsigned __int8)dest[n39 + 1];
v19 = byte_B14[++n39];
}
while ( v18 == v19 );
return (const char *)(n0x26 > 0x26);
}
else
{
return 0LL;
}
}
return src;
}

先frida调一下试试,看看能不能搞出来码表,frida_server 一开,点 check 就会闪退,有检测

GitHub - hzzheyang/strongR-frida-android: An anti detection version frida-server for android.

hulda是什么呢?是做了一些反检测frida后的项目,跟我们正常使用frida_server一样

1
2
3
./hs -l 0.0.0.0:9999
adb forward tcp:9999 tcp:9999(需要另外开一个终端)
frida -H 127.0.0.1:9999 -n bbandroid -l r0tracer.js

image-20250513202234325

然后可以用 r0tracer trace com.example.bbandroid.strange这个类

image-20250513202355492

image-20250513202412291

1
nopqrstDEFGHIJKLhijklUVQRST/WXYZabABCcdefgmuv6789+wxyz012345MNOP=

当然也可以jeb动调

如何动调可以看其中的方法二

Android逆向4-动态调试&Log插桩 | Matriy’s blog

方法二不行(好像要重启),那就只能手动改了

image-20250513205641786

image-20250513210427776

验证了一下是异或了输入长度

image-20250513211354555

动调没调到(还是不太熟练)

还可以用Objection,也能 Hook 到堆栈和函数返回值

1
2
objection -N -h 127.0.0.1 -p 9999 -g com.example.bbandroid explore
android hooking watch class_method com.example.bbandroid.strange.encode --dump-args --dump-backtrace --dump-return

我的机子不支持frida14.2.18这个得等新机到了在搞,模拟器不知道为啥frida不行

下面就是so层了

这段 Java_com_example_bbandroid_MainActivity_initSth 函数代码来自 Android NDK 层(native 层),是一个 JNI 函数,看起来主要做了一些libc.so 的内存与磁盘数据一致性校验,大致结构清晰,可以推断是某种反检测机制,以下是详细的分析:

1
2
3
4
getpid();
sub_10E8(filename); // 应该是 snprintf("/proc/%d/maps", getpid())
stream_1 = fopen(filename, "r"); // 打开进程 maps 文件
while ( !strstr(s, "libc.so") || !strstr(s, "r-xp") ) // 找到 libc.so 的代码段地址
1
2
3
4
5
fopen("/system/lib64/libc.so", "rb");
fread(ptr, 0x40); // ELF 头
fseek(stream_3, off, 0);
循环查找 `.text` 段标志 v24 == 1 && (v25 & 4)
记录该段在文件中的偏移 v26
1
2
3
4
fopen("/apex/com.android.runtime/lib64/bionic/libc.so", "rb");
读取 ELF 节区头,查找 `.text`
ptr_3 = malloc(size);
fread(ptr_3, size); // 读出磁盘中.text段
1
2
3
v15 = crc32(0LL, ptr_3, n) ^ crc32(0LL, 0LL, 0LL); // clean version hash
v16 = crc32(0LL, 0LL, 0LL);
result = (crc32(0LL, ptr_4, n) ^ v16) == v15; // 比对运行时内存中和磁盘中的crc

Java_com_example_bbandroid_MainActivity_checkFlag

从 Java 层获取用户输入字符串src);

复制到一个本地 dest 缓冲区(最多255字节);

根据时间派生一个伪随机种子(seed

dest 做块状异或混淆和 CRC-like 哈希运算

验证第一个字节是否为 51(即字符 '3'

逐字节和 byte_B14 里的内容对比验证是否正确

返回 true/false

可以得到

1
0x33,0xC0,0xC8,0xA3,0xF3,0xBF,0x1D,0x1A,0x3B,0x41,0xB7,0xC6,0xF1,0x5E,0x86,0x52,0x52,0xCF,0x6B,0x1E,0xC5,0xF9,0xCB,0xBF,0xED,0x7B,0x62,0xF1,0xF7,0x43,0x48,0x54,0xFB,0x85,0x4C,0xD9,0x35,0x30,0xF2,0x6E
1
2
3
v5 = time(0LL);
seed = v5 / 1000000 / 100;
srand(seed);

使用 time(0) 秒级时间戳,经过除以 100_000_000 得到一个较慢增长的 seed,意味着:每大约 1 天 seed 才会改变一次,或基本固定。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for each 4 bytes:
v12[0] ^= rand();
v12[1] ^= rand();
v12[2] ^= rand();
v12[3] ^= rand();

v15 = *(int*)v12;
for 32 rounds:
if v15 >= 0:
v15 *= 2;
else:
v15 = (v15 << 1) ^ 0x85B6874F;
*(int*)v12 = v15;

对每 4 字节的子块做:

  • 逐字节 XOR 一个伪随机数(从 rand());
  • 然后当成 int 做一个类似 CRC 的哈希运算,共 32 轮;
  • 这步可以理解为输入混淆 + 哈希保护。

image-20250514201646516

由于这里 1000000 / 100,我们可以得知seed 为 17

每字节 XOR 一个伪随机数(rand());

将 4 字节视为 int 做 32 轮 CRC-like 变换(如下):

1
2
3
4
5
6
for (int i = 0; i < 32; i++) {
if (v >= 0)
v *= 2;
else
v = (v << 1) ^ 0x85B6874F;
}

负数要 v = (v << 1) ^ 0x85B6874F;

意味着 MSB(最高位)为 1,那么如果你要反过来做,就是要在右移时恢复原来的 MSB = 1

➤ 正向流程中:

  • 假设 v 是 0xC0000000(负数),那么 v << 1 会移除 MSB
  • 然后 XOR 加密

➤ 逆向中:

  • 你右移后是 v >> 1
  • 但你不能丢掉 MSB 信息,否则加密就不可逆了!

不知道xor长度怎么办?爆破

image-20250514205544032

image-20250514205424385

ez_cython

image-20250514211612204

python反编译 - 在线工具

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
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.8

import cy

def str_hex(input_str):
return (lambda .0: [ ord(char) for char in .0 ])(input_str)

def main():
print('欢迎来到猜谜游戏!')
print("逐个输入字符进行猜测,直到 'end' 结束。")
guess_chars = []
char = input("请输入一个字符(输入 'end' 结束):")
if char == 'end':
pass
elif len(char) == 1:
guess_chars.append(char)
continue
print('请输入一个单独的字符。')
continue
guess_hex = str_hex(''.join(guess_chars))
if cy.sub14514(guess_hex):
print('真的好厉害!flag非你莫属')

print('不好意思,错了哦。')
retry = input('是否重新输入?(y/n):')
if retry.lower() != 'y':
pass

print('游戏结束')

if __name__ == '__main__':
main()

那就得看看cy这个库了

conda建一个3.8的环境,help(cy)

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
NAME
cy

CLASSES
builtins.object
QOOQOOQOOQOOOQ

class QOOQOOQOOQOOOQ(builtins.object)
| Methods defined here:
|
| __init__(self)
|
| get_key(self)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)

FUNCTIONS
sub14514(nmnmnnnmnmmnmmnn)

sub50520(T7T77T77T7T7TT, key)

sub50804(a, b, c, d, e, f)

DATA
__test__ = {}

FILE
e:\desktop\test\cy.cp38-win_amd64.pyd

发现有个类和几个方法,直接print(cy.QOOQOOQOOQOOOQ().get_key())

[83, 121, 67, 49, 48, 86, 101, 82, 102, 48, 82, 86, 101, 114]

看来还得IDA,看导入表可以猜测与tea相关(xor)

也可以

1
2
3
4
5
6
7
8
9
10
import pefile

def import_check(pyd_file):
pe = pefile.PE(pyd_file)
for entry in pe.DIRECTORY_ENTRY_IMPORT:
print(f"Module: {entry.dll.decode('utf-8')}")
for imp in entry.imports:
print(f" Function: {imp.name.decode('utf-8') if imp.name else None}")

import_check('cy.cp38-win_amd64.pyd')

image-20250515202748814

直接分析这俩(看了wp才知道BE30是设置key)

还发现了

image-20250515203044075

但是不知道顺序

回头看xor发现其中对xor和shr等api的交叉引用,可以分析出sub50804是xxtea的一个MX函数

image-20250515204244958

1
2
def shift(a, b, c, d, e, f):
return ((((a >> 3) ^ (b << 3)) + ((b >> 4) ^ (a << 2))) ^ ((b ^ c) + (d[(e & 2) ^ f] ^ a)))

可以确定是xxtea了,对比一下是可以发现有魔改的

1
MX (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z)))

可以对108B8交叉引用一个个找最终找到这个函数

1
__int64 __fastcall sub_180009420(__int64 a1, __int64 a2)

image-20250515210231149

和刚才的对照一下就可以得到密文

1
2
3
4
5
6
7
8
9
enc = [
4108944556, 3404732701, 1466956825, 788072761, 1482427973,
782926647, 1635740553, 4115935911, 2820454423, 3206473923,
1700989382, 2460803532, 2399057278, 968884411, 1298467094,
1786305447, 3953508515, 2466099443, 4105559714, 779131097,
288224004, 3322844775, 4122289132, 2089726849, 656452727,
3096682206, 2217255962, 680183044, 3394288893, 697481839,
1109578150, 2272036063
]

在sub14514中调用了off_1800108B8 + 32也就是get_key 然后作为参数传入sub50520 而xxtea算法只需要四个密钥,所以密钥是前四个字节

exp:

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

#define DELTA 0x9E3779B9
#define MX (z >> 3 ^ y << 3) + (y >> 4 ^ z << 2) ^ (sum ^ y) + (k[(p & 2) ^ e] ^ z)

void xxtea_encrypt(uint32_t *v, uint32_t len, uint32_t *k) {
uint32_t n = len - 1;
uint32_t y, z, sum = 0, e, p, q;
q = 4 + 60 / len;
while (q-- > 0) {
sum += DELTA;
e = sum >> 3 & 3;
for (p = 0; p < n; p++) {
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n] += MX;
}
}

void xxtea_decrypt(uint32_t *v, uint32_t len, uint32_t *k) {
uint32_t n = len;
uint32_t y = v[0], z, sum, e, p, q;
q = 4 + 60 / len;
sum = q * DELTA;
while (sum != 0) {
e = sum >> 3 & 3;
for (p = n-1; p > 0; p--) {
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
}
}

int main() {
uint32_t v[32] = { 4108944556, 3404732701, 1466956825, 788072761, 1482427973, 782926647, 1635740553, 4115935911, 2820454423, 3206473923, 1700989382, 2460803532, 2399057278, 968884411, 1298467094, 1786305447, 3953508515, 2466099443, 4105559714, 779131097, 288224004, 3322844775, 4122289132, 2089726849, 656452727, 3096682206, 2217255962, 680183044, 3394288893, 697481839, 1109578150, 2272036063};
uint32_t const k[4] = { 0x53, 0x79, 0x43, 0x31 };
xxtea_decrypt(v, 32, k);
printf("Decrypted data:\n");
for (int i = 0; i < 32; i++) {
printf("%c", v[i]);
}
return 0;
}
/*
Decrypted data:
SCTF{w0w_y0U_wE1_kNOw_of_cYtH0N}
*/

其他解法:

学习一下SCTF-cython-wp - Kvancy

既然源码是用python写的,而且这个sub_14514接受的参数是python里的list类,那么就可以考虑自己定义一个类似list的类,然后重写list的成员函数,从而在加密过程的时候如果调用了这个成员函数,那么就会进入到我们自己定义的函数中,如果我们自己在定义的时候打印调试信息显示这一步在干什么,我们是不是就能通过调试信息获取整个加密流程呢?

怎么重写呢?在C++里我们可以先父类继承,子类定义同名函数(参数列表也必须相同),从而实现重写函数,那么在python中也可以通过类似的方法实现重写,比如说定义一个自己的AList类继承自list

image-20250515214119211

每当Symbol对象执行了相应操作就会打印出来

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

class Symbol:
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
def __rshift__(self, other):
if isinstance(other, Symbol):
expression = Symbol(f"({self.name} >> {other.name})")
else:
expression = Symbol(f"({self.name} >> {other})")
return expression
def __lshift__(self, other):
if isinstance(other, Symbol):
expression = Symbol(f"({self.name} << {other.name})")
else:
expression = Symbol(f"({self.name} << {other})")
return expression
def __rxor__(self, other):
if isinstance(other, Symbol):
expression = Symbol(f"({self.name} ^ {other.name})")
else:
expression = Symbol(f"({self.name} ^ {other})")
return expression
def __xor__(self, other):
if isinstance(other, Symbol):
expression = Symbol(f"({self.name} ^ {other.name})")
else:
expression = Symbol(f"({self.name} ^ {other})")
return expression
def __add__(self, other):
if isinstance(other, Symbol):
expression = Symbol(f"({self.name} + {other.name})")
else:
expression = Symbol(f"({self.name} + {other})")
return expression
def __and__(self, other):
if isinstance(other, Symbol):
expression = Symbol(f"({self.name} & {other.name})")
else:
expression = Symbol(f"({self.name} & {other})")
return expression

class AList:
def __init__(self, nums):
self.nums = [Symbol(str(num)) for num in nums]
def __getitem__(self, key):
return self.nums[key]
def copy(self):
return AList(self.nums)
def __len__(self):
return len(self.nums)
def __setitem__(self, key, value):
print(f"new_{self.nums[key]} = {value}")
self.nums[key] = Symbol(f"new_{self.nums[key].name}")
def __eq__(self, other):
print(f"{self.nums} == {other}")
return self.nums == other

enc = AList([f"a[{i}]" for i in range(32)])
res = cy.sub14514(enc)
print(res)

uds

hint跟车有关,想起车机系统一般是arm架构的,直接IDA arm打开

image-20250516112846565

findcrypt

image-20250516113019098

tea加密

image-20250516113154103

向上追溯到sub_80043E8方法

case6还可以发现RC4

image-20250516114000180

手动翻汇编发现

image-20250516114947795

需要再D转化下

image-20250516115250862

sub_810004C的参数是dword_8004EC8,这时生成密文的函数

image-20250516115314779

直接让GPT写一下

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
#include <iostream>
#include <iomanip>

void sub_810004C(const char* a1, unsigned char* a2, int a3) {
const char* p = a1;
unsigned char* out = a2;
unsigned char* end = a2 + a3;

while (out < end) {
unsigned char b = *p++;
unsigned int copy_count = b & 0xF;
if (copy_count == 0)
copy_count = (unsigned char)(*p++);
unsigned int zero_count = b >> 4;
if (zero_count == 0)
zero_count = (unsigned char)(*p++);

while (--copy_count && out < end)
*out++ = (unsigned char)(*p++);

while (--zero_count && out < end)
*out++ = 0;
}
}

int main() {
char a1[40] = {
0x01, 0x13, 0x02, 0x96, 0x88, 0x00, 0x12, 0xB0, 0x14, 0xA6,
0x91, 0xFE, 0xB9, 0xD7, 0x41, 0xAF, 0x82, 0xCC, 0x4E, 0xE9,
0x47, 0x47, 0x28, 0x4F, 0xD1, 0x42, 0x10, 0x52, 0x01, 0x58,
0x90, 0xD0, 0x03, 0x00, 0x90, 0xD0, 0x03, 0x02, 0x18, 0x01
};

unsigned char output[256] = { 0 }; // 假设最大输出不超过 256 字节
int output_len = 256;

sub_810004C(a1, output, output_len);

std::cout << "Decompressed output (hex):\n";
for (int i = 0; i < output_len; ++i) {
std::cout << std::hex << std::setw(2) << std::setfill('0')
<< (int)output[i] << ' ';
if ((i + 1) % 16 == 0) std::cout << '\n';
}

return 0;
}

image-20250516120316299

key

image-20250516130959488

image-20250516132123530

注意,这里要复现的是加密代码,是tea加密完的key给RC4

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

void tea_encrypt(uint32_t* v, uint32_t* k) {
uint32_t sum = 0;
uint32_t v0 = v[0], v1 = v[1];
uint32_t delta = 0x9e3779b9;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];

for (int i = 0; i < 32; i++) {
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
}

v[0] = v0;
v[1] = v1;
}

int main() {
uint32_t enc[2] = { 0x11223344, 0x55667788 };
uint32_t key[4] = { 0x0123, 0x4567, 0x89AB, 0xCDEF };
tea_encrypt(enc, key);
printf("%x %x\n", enc[0], enc[1]);
}

604a8a6e 9dacb167

1
2
3
4
5
6
7
8
from Crypto.Cipher import ARC4
enc =[20,166, 145, 254, 185 ,215, 65 ,175 ,130 ,204 ,78 ,233 ,71 ,71 ,40 ,79, 209]

key = [0x60,0x4a,0x8a,0x6e,0x9d,0xac,0xb1,0x67]

rc4 = ARC4.new(bytes(key))
data = rc4.decrypt(bytes(enc))
print(data)

W0L000043MB541337

Logindemo

题目描述:李明的室友初学安卓写了一个登陆的逻辑,请根据har文件的流量中返回正确的请求的签名参数还原出正确的用户名和密码,flag为SCTF{用户名+密码}

jadx有一部分显示不出来

image-20250516191257920

用jeb试试

image-20250516193809738

anything -> transform -> getNothing -> xor -> generateSignature

xor主要是在发现了加载dex的sayhello方法,jeb没发现,jadx发现了这个异或方法

image-20250516195406161

1
this.btn_login.setOnClickListener((View v) -> new Thread(new com.example.sctf1.LoginActivity.1(this, method0, object0)).start());

设置了一个事件监听

而LoginActivity.1 implements Runnable

是这个线程是点击“登录”按钮后运行的主要逻辑,其中调用反射方法(核心点)(sayhello)

1
this.val$method.invoke(this.val$dexlib_obj, phone_number)
1
2
3
4
5
6
7
String sig = SignatureGenerator.generateSignature(secretKey + URL + JSON);
Request request = new Request.Builder()
.url("http://47.109.106.62:9090/login")
.post(RequestBody.create(...))
.addHeader("Signature", sig)
.build();

生成签名并发送网络请求

那么可以开始逆向了,看一下har文件的流量,刚好有下黄鸟抓包,看起来方便一点

image-20250516200809346

1
Zwl0AWgJaAdlagFyBWMCbwBjYgJxBWgEbwVkYgR6AWgEYAJmZgVyAmkBbAJlZAF2AW0EbghnZwFzCGMFYQBiZQF0CWoGYQdkYQZ2AWgDYAhmZQlxA2wIYAJjZQlyAWgGaAdgYAJ7BG0BawZvZAZ3B2sIawBgYgZ6CWgBbQhvYAN7CGwDaARkYgd2BGwCYAZjZgNyBmwIbwNhYAlzCWgJaAFnZwF2AmsIbwdkZwd1BmICawVgZgd2BG4IYAlkYAhwBm4EaQBvagN0CGIBaABhZABwAm8GbwJnZwdyBGkJbQhgawF3CGgFagdjYQV2AWkGaAFkZAZyBGkDaghnawdxAW4JagJhYgRwA2sIbARjagZ6AGgDaAhkZwB1BG0IagNlawZ2CGgFbgBiZwR7AW0AaAhjZAF6BGgJYQJkYQhxAmMFbANiZgN2AmIBbQdiYgh2AWoGawFjZgB2Am4IagdhYgh2AG4BaQlvZQFwAmMFaAViYwByBG4EbghmZwN2BmoDaAdmZQZwAGwBagNuZQB7CWsHbARiZwlzAW8AagVnZQFwAWgAbQVjYAd2AG8IbwRnZwV7BmgJaAJlagV3BWsBbQZvYgFzBmgHbwJgZABxBG4EagVkYgdzAWoFbARjYwFxAm0EaglmYwJ2A2sBaQVnZAV0CG4DbQRlYwNzCGoHYQVnYgV6BGIDaARnZAByAWkBYQJmaglxAGsCbAJiYwJ1BGgHaghlYwV1AmMGbwNmYgF1CG4JaQduYQJzAG8GagZnZQN3CW8AaQhuagNwBGkJaARiYAByCGgDYARvawNwA2oGaAJmawFxBWh0dHA6Ly80Ny4xMDkuMTA2LjYyOjkwOTB7Im5hbWUiOiJTQ1RGIiwicGFzc3dvcmQiOiI4ODg4ODg4OCJ9

Yg的才是对的,因为返回了OK

1
YgNxAGMDawJjZQR6B2IGYANiYQVxAG8JYQhkawZ3AW8JagluYAN2Am4GbQRmZAR6AWwBbQNlZANxCWsCaAlhZQRxAm4CbgRkZgl1AWIIawhmYAh3B2MBaAJmaghwAWoEbwliYgBwCWkIbQNuawlyAW0FYAhuYgB1Am8CawRuYAJxCG8CbgRgZAF3BWgJYQlhZwFzAGsJbwFlagV0CW0FawhgawNyCGkAbQNjYQh3Bm4FbwNkYAJ6A2IDaANmYwl2A2sEaQRlaglyAm0HaARmYQZ7AWsIbwZhYwB0B2sIYAlvYgN2AWsHYQJiZAByAGgDYANmYQB0BmwJYABhZwl1CGkEaQlmZQJzBm0IYQdjYwh6A20BbwVhZQl3CGoIaABmYAN1AW0IbQFvYAN0B2gFYAVhZAF1BW8HYQZvagZ6A20CaAhjZAl6BWkCYQhvZAN1AGgDaQJhYQZzCW8BYABjZAN0AW8BbQViZwVyA28JagJiagd1CGgDawhvYQJwB28GagNvYwd6AG0BYQFuawVyBGoBaQFkZAV1A24HbgdlYgd1AWwIYQNkagV6BW0DbglvZAl0A2kFaAhjawB3AmwAbwZgZwV3BGMEaQllYAhzAGsEYAFhYAJ6Bm4GaQdkagl6A20DawdkZgd3BW0JbgRgYQZyB2kJbANnZgdwA2gFaQFnYAh7BW4GbAdhYgd7Bm4DawJmawN0CWMDbgJgYwh0AmwGYQRiYQN2BmIGaAVkYwh2BmsDbAFhaglzB2kAbQBjZwJ1BGkCaghiZgByAWkJaAhhagZ3AG0JaghiYQVwAmMIaAFjYgVzBGh0dHA6Ly80Ny4xMDkuMTA2LjYyOjkwOTB7Im5hbWUiOiJTQ1RGIiwicGFzc3dvcmQiOiI4ODg4ODg4OCJ9

image-20250516201011947

之前是个xor

因为

1
2
3
4
5
6
7
String sig = SignatureGenerator.generateSignature(secretKey + URL + JSON);
Request request = new Request.Builder()
.url("http://47.109.106.62:9090/login")
.post(RequestBody.create(...))
.addHeader("Signature", sig)
.build();

所以Http前才是secret

1
2
3
4
5
6
7
8
import base64

signature = "YgNxAGMDawJjZQR6B2IGYANiYQVxAG8JYQhkawZ3AW8JagluYAN2Am4GbQRmZAR6AWwBbQNlZANxCWsCaAlhZQRxAm4CbgRkZgl1AWIIawhmYAh3B2MBaAJmaghwAWoEbwliYgBwCWkIbQNuawlyAW0FYAhuYgB1Am8CawRuYAJxCG8CbgRgZAF3BWgJYQlhZwFzAGsJbwFlagV0CW0FawhgawNyCGkAbQNjYQh3Bm4FbwNkYAJ6A2IDaANmYwl2A2sEaQRlaglyAm0HaARmYQZ7AWsIbwZhYwB0B2sIYAlvYgN2AWsHYQJiZAByAGgDYANmYQB0BmwJYABhZwl1CGkEaQlmZQJzBm0IYQdjYwh6A20BbwVhZQl3CGoIaABmYAN1AW0IbQFvYAN0B2gFYAVhZAF1BW8HYQZvagZ6A20CaAhjZAl6BWkCYQhvZAN1AGgDaQJhYQZzCW8BYABjZAN0AW8BbQViZwVyA28JagJiagd1CGgDawhvYQJwB28GagNvYwd6AG0BYQFuawVyBGoBaQFkZAV1A24HbgdlYgd1AWwIYQNkagV6BW0DbglvZAl0A2kFaAhjawB3AmwAbwZgZwV3BGMEaQllYAhzAGsEYAFhYAJ6Bm4GaQdkagl6A20DawdkZgd3BW0JbgRgYQZyB2kJbANnZgdwA2gFaQFnYAh7BW4GbAdhYgd7Bm4DawJmawN0CWMDbgJgYwh0AmwGYQRiYQN2BmIGaAVkYwh2BmsDbAFhaglzB2kAbQBjZwJ1BGkCaghiZgByAWkJaAhhagZ3AG0JaghiYQVwAmMIaAFjYgVzBGh0dHA6Ly80Ny4xMDkuMTA2LjYyOjkwOTB7Im5hbWUiOiJTQ1RGIiwicGFzc3dvcmQiOiI4ODg4ODg4OCJ9"

data = base64.b64decode(signature)
secret_key = data.split(b"http://")[0]
print(secret_key)

加上xor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import base64

def xor_encrypt_decrypt(input_str, key):
return ''.join(chr(ord(c) ^ ord(key[i % len(key)])) for i, c in enumerate(input_str))

signature = "YgNxAGMDawJjZQR6B2IGYANiYQVxAG8JYQhkawZ3AW8JagluYAN2Am4GbQRmZAR6AWwBbQNlZANxCWsCaAlhZQRxAm4CbgRkZgl1AWIIawhmYAh3B2MBaAJmaghwAWoEbwliYgBwCWkIbQNuawlyAW0FYAhuYgB1Am8CawRuYAJxCG8CbgRgZAF3BWgJYQlhZwFzAGsJbwFlagV0CW0FawhgawNyCGkAbQNjYQh3Bm4FbwNkYAJ6A2IDaANmYwl2A2sEaQRlaglyAm0HaARmYQZ7AWsIbwZhYwB0B2sIYAlvYgN2AWsHYQJiZAByAGgDYANmYQB0BmwJYABhZwl1CGkEaQlmZQJzBm0IYQdjYwh6A20BbwVhZQl3CGoIaABmYAN1AW0IbQFvYAN0B2gFYAVhZAF1BW8HYQZvagZ6A20CaAhjZAl6BWkCYQhvZAN1AGgDaQJhYQZzCW8BYABjZAN0AW8BbQViZwVyA28JagJiagd1CGgDawhvYQJwB28GagNvYwd6AG0BYQFuawVyBGoBaQFkZAV1A24HbgdlYgd1AWwIYQNkagV6BW0DbglvZAl0A2kFaAhjawB3AmwAbwZgZwV3BGMEaQllYAhzAGsEYAFhYAJ6Bm4GaQdkagl6A20DawdkZgd3BW0JbgRgYQZyB2kJbANnZgdwA2gFaQFnYAh7BW4GbAdhYgd7Bm4DawJmawN0CWMDbgJgYwh0AmwGYQRiYQN2BmIGaAVkYwh2BmsDbAFhaglzB2kAbQBjZwJ1BGkCaghiZgByAWkJaAhhagZ3AG0JaghiYQVwAmMIaAFjYgVzBGh0dHA6Ly80Ny4xMDkuMTA2LjYyOjkwOTB7Im5hbWUiOiJTQ1RGIiwicGFzc3dvcmQiOiI4ODg4ODg4OCJ9"

decoded = base64.b64decode(signature)
secret_key = decoded.split(b"http://")[0].decode(errors="ignore")

key = "S0C0Z0Y0W"
say_hello_result = xor_encrypt_decrypt(secret_key, key)

print(say_hello_result)

getnothing在so层

跟进这几个函数的变量

image-20250516203632158

发现

image-20250516203649075

好像是RSA,PQE都有

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
import base64
from Crypto.Util.number import inverse, long_to_bytes

def xor_encrypt_decrypt(input_str, key):
return ''.join(chr(ord(c) ^ ord(key[i % len(key)])) for i, c in enumerate(input_str))

signature = "YgNxAGMDawJjZQR6B2IGYANiYQVxAG8JYQhkawZ3AW8JagluYAN2Am4GbQRmZAR6AWwBbQNlZANxCWsCaAlhZQRxAm4CbgRkZgl1AWIIawhmYAh3B2MBaAJmaghwAWoEbwliYgBwCWkIbQNuawlyAW0FYAhuYgB1Am8CawRuYAJxCG8CbgRgZAF3BWgJYQlhZwFzAGsJbwFlagV0CW0FawhgawNyCGkAbQNjYQh3Bm4FbwNkYAJ6A2IDaANmYwl2A2sEaQRlaglyAm0HaARmYQZ7AWsIbwZhYwB0B2sIYAlvYgN2AWsHYQJiZAByAGgDYANmYQB0BmwJYABhZwl1CGkEaQlmZQJzBm0IYQdjYwh6A20BbwVhZQl3CGoIaABmYAN1AW0IbQFvYAN0B2gFYAVhZAF1BW8HYQZvagZ6A20CaAhjZAl6BWkCYQhvZAN1AGgDaQJhYQZzCW8BYABjZAN0AW8BbQViZwVyA28JagJiagd1CGgDawhvYQJwB28GagNvYwd6AG0BYQFuawVyBGoBaQFkZAV1A24HbgdlYgd1AWwIYQNkagV6BW0DbglvZAl0A2kFaAhjawB3AmwAbwZgZwV3BGMEaQllYAhzAGsEYAFhYAJ6Bm4GaQdkagl6A20DawdkZgd3BW0JbgRgYQZyB2kJbANnZgdwA2gFaQFnYAh7BW4GbAdhYgd7Bm4DawJmawN0CWMDbgJgYwh0AmwGYQRiYQN2BmIGaAVkYwh2BmsDbAFhaglzB2kAbQBjZwJ1BGkCaghiZgByAWkJaAhhagZ3AG0JaghiYQVwAmMIaAFjYgVzBGh0dHA6Ly80Ny4xMDkuMTA2LjYyOjkwOTB7Im5hbWUiOiJTQ1RGIiwicGFzc3dvcmQiOiI4ODg4ODg4OCJ9"

decoded = base64.b64decode(signature)
secret_key = decoded.split(b"http://")[0].decode(errors="ignore")

key = "S0C0Z0Y0W"
say_hello_result = xor_encrypt_decrypt(secret_key, key)

print(say_hello_result)

# 给定参数
p = 106697219132480173106064317148705638676529121742557567770857687729397446898790451577487723991083173010242416863238099716044775658681981821407922722052778958942891831033512463262741053961681512908218003840408526915629689432111480588966800949428079015682624591636010678691927285321708935076221951173426894836169
q = 144819424465842307806353672547344125290716753535239658417883828941232509622838692761917211806963011168822281666033695157426515864265527046213326145174398018859056439431422867957079149967592078894410082695714160599647180947207504108618794637872261572262805565517756922288320779308895819726074229154002310375209
e = 65537
n = p * q
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
c = int(say_hello_result)
m = str(pow(c, d, n))

enc = m.replace("00"," ").split(" ")[:-1]
for i in range(len(enc)):
print(chr(int(enc[i])),end='')

然后是下一层解密anything,是一个循环移位,要解密的话猜测,超过多少次,密文会恢复,因此可以直接复现

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
package zcy_msb;
public class GoodCard {
public static void main(String[] args) {
String tmp = "ywts7humj5h6g";
for (int i = 0; i < 100; i++) {
String flag = tmp;
tmp = anything(tmp);
System.out.println(tmp);
}
}
public static String anything(String str) {
char[] arr_c = str.toCharArray();
int to = arr_c.length - 1;
GoodCard.perfect(arr_c, 0, to, (to + 1) / 2);
return String.valueOf(arr_c);
}

public static void circle(char[] a, int from, int i, int n2) {
int k;
for(k = i * 2 % n2; k != i; k = k * 2 % n2) {
char temp = a[i + from];
a[i + from] = a[k + from];
a[k + from] = temp;
}
}

public static void perfect(char[] a, int from, int to, int n) {
if(from >= to) {
return;
}

if(from == to - 1) {
swap(a, from, to);
return;
}

int k = 0;
int p = n * 2 + 1;
int k_3;
for(k_3 = 1; k <= p / 3; k_3 *= 3) {
++k;
p /= 3;
}

int m = (k_3 - 1) / 2;
GoodCard.rightCircle(a, from + m, from + n + m - 1, m);
int i = 0;
int t;
for(t = 1; i < k; t *= 3) {
GoodCard.circle(a, from - 1, t, m * 2 + 1);
++i;
}

GoodCard.perfect(a, m * 2 + from, to, (to - (m * 2 + from) + 1) / 2);
}

public static void reverse(char[] a, int from, int to) {
while(from < to) {
swap(a, from, to);
++from;
--to;
}
}

public static void rightCircle(char[] a, int from, int to, int n) {
int m = n % (to - from + 1);
GoodCard.reverse(a, to - m + 1, to);
GoodCard.reverse(a, from, to - m);
GoodCard.reverse(a, from, to);
}
public static void swap(char[] a, int from, int to) {
char temp = a[from];
a[from] = a[to];
a[to] = temp;
}
}


image-20250516205912875

SCTF{wshm56yt7ujhg}