首页
论坛
课程
招聘
静态分析某APP的AES加密算法(内附秘籍)
2021-5-12 14:44 12109

静态分析某APP的AES加密算法(内附秘籍)

2021-5-12 14:44
12109

定位算法

某位好胸弟已经把算法位置已经找到,便于大家分析,我直接把ida中反编译的代码贴出来吧,代码不多也就八百多行。

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
int __fastcall innoSecure(const char *a1, const char *a2, int a3, int a4, _DWORD *decode, _DWORD *a6, int a7)
{
  int v10; // r5
  int v11; // r6
  char *v12; // r4
  int v13; // r0
  int v14; // r1
  int v15; // r2
  unsigned int v16; // r4
  int v17; // r6
  int v18; // r5
  unsigned int v19; // r5
  unsigned int v20; // r0
  size_t v21; // r0
  signed int v22; // r0
  int i; // r1
  __int64 *v24; // r2
  int v25; // r3
  bool v26; // cf
  int v27; // r5
  int v28; // r0
  char *v29; // r0
  char *v30; // r1
  char v31; // t1
  int v32; // r4
  int v33; // r0
  int v34; // r1
  int v35; // r2
  unsigned __int8 *v36; // r3
  unsigned int v37; // t1
  char v38; // lr
  int v39; // r5
  char v40; // r2
  int v41; // r4
  int v42; // r6
  int v43; // r0
  char v44; // r3
  int j; // r6
  char v46; // r0
  size_t v47; // r0
  void *v48; // r4
  int v49; // r5
  size_t v50; // r0
  void *v51; // r9
  int v52; // r0
  int v53; // r0
  int v54; // r1
  int v55; // r2
  unsigned int v56; // r6
  int v57; // r4
  int v58; // r6
  int v59; // r3
  int k; // r0
  unsigned int v61; // r2
  int v62; // r3
  int v63; // r6
  unsigned int v64; // r5
  char v65; // r2
  int v66; // r6
  int v67; // r5
  int v68; // r4
  unsigned int v69; // r1
  char *v70; // r1
  int v71; // r6
  size_t v72; // r0
  size_t v73; // r4
  size_t i2; // r2
  char v75; // r3
  int i3; // r0
  int i4; // r0
  char *v78; // r1
  char v79; // r3
  char v80; // r2
  unsigned int v81; // r11
  int i7; // r0
  int i6; // r0
  int i5; // r0
  char v85; // lr
  char v86; // r3
  char v87; // r2
  char v88; // r1
  char v89; // r12
  char v90; // r10
  char v91; // r1
  int v92; // r2
  size_t v93; // r0
  char *v94; // r4
  size_t v95; // r0
  size_t v96; // r1
  size_t v97; // r0
  size_t v98; // r0
  void *v99; // r0
  size_t v100; // r5
  unsigned int v101; // r6
  char v102; // r0
  size_t l; // r1
  char v104; // r2
  int v105; // r1
  int v106; // r4
  int v107; // r0
  int m; // r0
  char *v109; // r1
  char v110; // r3
  char v111; // r2
  int v112; // r4
  int ii; // r0
  int n; // r0
  int v115; // r0
  char v116; // lr
  char v117; // r3
  char v118; // r4
  char v119; // r2
  char v120; // r12
  char v121; // r1
  int jj; // r0
  int kk; // r0
  char *v124; // r1
  char v125; // r3
  char v126; // r2
  unsigned int v127; // r8
  int nn; // r0
  int mm; // r0
  int ll; // r0
  char v131; // lr
  char v132; // r3
  char v133; // r4
  char v134; // r2
  char v135; // r1
  int i1; // r0
  char *v137; // r4
  size_t v138; // r0
  char *v139; // r4
  size_t v140; // r0
  size_t v141; // r1
  size_t v142; // r0
  unsigned int v144; // [sp+38h] [bp-508h]
  char *v145; // [sp+44h] [bp-4FCh]
  int v146; // [sp+48h] [bp-4F8h]
  int v147; // [sp+4Ch] [bp-4F4h]
  char *ptr; // [sp+50h] [bp-4F0h]
  unsigned int v149; // [sp+5Ch] [bp-4E4h]
  char v150; // [sp+5Ch] [bp-4E4h]
  char v151; // [sp+62h] [bp-4DEh] BYREF
  char v152; // [sp+63h] [bp-4DDh] BYREF
  __int64 v153; // [sp+64h] [bp-4DCh] BYREF
  int v154; // [sp+6Ch] [bp-4D4h] BYREF
  char v155[40]; // [sp+70h] [bp-4D0h] BYREF
  int v156; // [sp+98h] [bp-4A8h] BYREF
  int v157; // [sp+9Ch] [bp-4A4h]
  int v158; // [sp+A0h] [bp-4A0h]
  int v159; // [sp+A4h] [bp-49Ch]
  int v160; // [sp+A8h] [bp-498h]
  int v161; // [sp+ACh] [bp-494h]
  char v162[16]; // [sp+F0h] [bp-450h] BYREF
  char v163[32]; // [sp+100h] [bp-440h] BYREF
  int v164; // [sp+120h] [bp-420h]
  int v165; // [sp+124h] [bp-41Ch]
  int v166; // [sp+128h] [bp-418h]
  int v167; // [sp+12Ch] [bp-414h]
  int v168; // [sp+130h] [bp-410h] BYREF
  int v169; // [sp+134h] [bp-40Ch]
  int v170; // [sp+138h] [bp-408h]
  int v171; // [sp+13Ch] [bp-404h]
  _DWORD v172[4]; // [sp+140h] [bp-400h] BYREF
  int v173; // [sp+150h] [bp-3F0h]
  int v174; // [sp+154h] [bp-3ECh]
  int v175; // [sp+158h] [bp-3E8h]
  int v176; // [sp+15Ch] [bp-3E4h]
  char v177[32]; // [sp+160h] [bp-3E0h] BYREF
  _DWORD v178[3]; // [sp+180h] [bp-3C0h] BYREF
  int v179; // [sp+18Ch] [bp-3B4h] BYREF
  _BYTE v180[15]; // [sp+1A0h] [bp-3A0h] BYREF
  char v181[81]; // [sp+1AFh] [bp-391h]
  int v182; // [sp+200h] [bp-340h] BYREF
  char v183[52]; // [sp+247h] [bp-2F9h] BYREF
  _BYTE v184[16]; // [sp+27Bh] [bp-2C5h] BYREF
  _DWORD v185[4]; // [sp+290h] [bp-2B0h] BYREF
  _DWORD v186[4]; // [sp+2A0h] [bp-2A0h]
  char v187[36]; // [sp+2B0h] [bp-290h] BYREF
  _DWORD v188[22]; // [sp+2D4h] [bp-26Ch] BYREF
  char v189[16]; // [sp+32Dh] [bp-213h] BYREF
  char v190[81]; // [sp+33Dh] [bp-203h] BYREF
  char v191[48]; // [sp+3B0h] [bp-190h] BYREF
  char v192[16]; // [sp+3E0h] [bp-160h]
  char v193[304]; // [sp+3F0h] [bp-150h] BYREF
  int v194; // [sp+520h] [bp-20h]
 
  memset(v193, 0, 0x12Cu);
  v10 = a3 + 49;
  v11 = 0;
  v12 = v193;
  do
  {
    qmemcpy(v12, (const void *)(v10 + v11), 0x1Eu);
    v11 += 36;
    v12 += 30;
  }
  while ( v11 != 360 );
  v13 = 0;
  v14 = 1;
  v15 = 278;
  v16 = 0;
  do
  {
    if ( v16 % 3 )
    {
      v17 = v15;
      v192[2 * v16] = ~v193[v15 - 2];
      v18 = v14;
      if ( v16 % 3 != 1 )
      {
        v17 = 3 * v16 + 277;
        v18 = v14;
      }
    }
    else
    {
      v18 = v13 | 1;
      v192[2 * v16] = ~v193[v15 - 1];
      v17 = 3 * v16 + 278;
    }
    ++v16;
    v15 += 3;
    v14 += 2;
    v13 += 2;
    v192[v18] = ~v193[v17];
  }
  while ( v16 != 8 );
  strcpy(&v190[65], "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x");
  v19 = 0;
  sprintf(
    &v191[15],
    &v190[65],
    (unsigned __int8)v192[0],
    (unsigned __int8)v192[1],
    (unsigned __int8)v192[2],
    (unsigned __int8)v192[3],
    (unsigned __int8)v192[4],
    (unsigned __int8)v192[5],
    (unsigned __int8)v192[6],
    (unsigned __int8)v192[7],
    (unsigned __int8)v192[8],
    (unsigned __int8)v192[9],
    (unsigned __int8)v192[10],
    (unsigned __int8)v192[11],
    (unsigned __int8)v192[12],
    (unsigned __int8)v192[13],
    (unsigned __int8)v192[14],
    (unsigned __int8)v192[15]);
  do
  {
    if ( v191[v19 + 15] != *(_BYTE *)(a7 + v19) )
      return _stack_chk_guard - v194;
    ++v19;
  }
  while ( v19 <= 0x1F );
  v20 = 0;
  v154 = 0;
  do
  {
    if ( !v193[v20 + 48] )
      break;
    *((_BYTE *)&v154 + v20) = ~v193[v20 + 48];
    ++v20;
  }
  while ( v20 < 3 );
  strcpy(v190, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X");
  v188[0] = 0;
  v188[1] = 0;
  v188[2] = 0x67452301;
  v188[4] = 0x98BADCFE;
  v188[3] = 0xEFCDAB89;
  v188[5] = 0x10325476;
  v21 = strlen(a2);
  j_innosecure_x22(v188, a2, v21);              // MD5加密
  j_innosecure_x23(v188, v189);
  v22 = strlen(a2);
  v153 = 0LL;
  if ( v22 < 1 )
  {
LABEL_32:
    sprintf(
      v187,
      v190,
      (unsigned __int8)v189[0],
      (unsigned __int8)v189[1],
      (unsigned __int8)v189[2],
      (unsigned __int8)v189[3],
      (unsigned __int8)v189[4],
      (unsigned __int8)v189[5],
      (unsigned __int8)v189[6],
      (unsigned __int8)v189[7],
      (unsigned __int8)v189[8],
      (unsigned __int8)v189[9],
      (unsigned __int8)v189[10],
      (unsigned __int8)v189[11],
      (unsigned __int8)v189[12],
      (unsigned __int8)v189[13],
      (unsigned __int8)v189[14],
      (unsigned __int8)v189[15]);
    goto LABEL_33;
  }
  for ( i = 0; i != v22; ++i )
  {
    v25 = (unsigned __int8)a2[i];
    if ( (unsigned __int8)(v25 - 48) >= 0xAu )
    {
      v24 = (__int64 *)((char *)&v153 + 4);
      v26 = (unsigned int)(v25 - 65) >= 6;
      if ( (unsigned int)(v25 - 65) >= 6 )
        v26 = (unsigned int)(v25 - 97) >= 6;
      if ( v26 )
      {
        if ( v25 != 45 )
          continue;
        v24 = &v153;
      }
    }
    else
    {
      v24 = (__int64 *)((char *)&v153 + 4);
    }
    ++*(_DWORD *)v24;
  }
  if ( v22 != 36 || v153 != 0x2000000004LL )
    goto LABEL_32;
  v27 = 0;
  v178[2] = 0;
  v179 = 0;
  v178[0] = 0;
  v178[1] = 0;
  v28 = strlen(a2);
  j_innosecure_x29(v28, (int)a2, 1, 0, 0, (int)v178);
  memset(v187, 0, 0x21u);
  v29 = (char *)&v179 + 3;
  do
  {
    v187[2 * v27] = v189[v27];
    v30 = &v187[2 * v27];
    v31 = *v29--;
    ++v27;
    v30[1] = v31;
  }
  while ( v27 != 16 );
LABEL_33:
  v32 = 0;
  v186[2] = 0;
  v186[3] = 0;
  v186[0] = 0;
  v186[1] = 0;
  do
    *((_BYTE *)v186 + v32++) = arc4random();
  while ( v32 != 16 );
  v33 = 0;
  v185[2] = 0;
  v185[3] = 0;
  v185[0] = 0;
  v185[1] = 0;
  do
  {
    *((_BYTE *)v185 + v33) = ~(*((_BYTE *)v186 + v33) ^ v189[v33]);
    ++v33;
  }
  while ( v33 != 16 );
  memset(&v183[49], 0, 0x13u);
  LOWORD(v34) = 0;
  v35 = 15;
  v36 = (unsigned __int8 *)v185;
  do
  {
    v37 = *v36++;
    v34 = (unsigned __int16)v34 | (((v37 >> 3) & 1) << v35--);
  }
  while ( v35 != -1 );
  v38 = 0;
  v39 = 16;
  v40 = 0;
  v41 = 0;
  do
  {
    v42 = v39 - 1;
    v43 = ((unsigned __int8)((unsigned __int16)v34 >> v39) ^ (unsigned __int8)((unsigned __int16)v34 >> (v39 - 1))) & 1;
    if ( v41 > 7 )
      v40 |= v43 << v42;
    else
      v38 |= v43 << (v39 - 9);
    ++v41;
    --v39;
  }
  while ( v42 );
  v44 = 0;
  for ( j = 0; j != 16; ++j )
  {
    v46 = *((_BYTE *)v185 + j);
    v44 += v46;
  }
  v183[50] = -v44;
  v183[49] = v38;
  v183[51] = v40;
  qmemcpy(v184, v185, sizeof(v184));
  v47 = strlen(a2);
  v48 = malloc(v47 + 256);
  memset(v48, 0, strlen(a2) + 256);
  v49 = 0;
  strcpy(v183, "param%c%s%cversion%c%s%cplatform%candroid%cec%c1");
  sprintf((char *)v48, v183, 31, a2, 30, 31, &v154, 30, 31, 30, 31);
  v50 = strlen((const char *)v48);
  v51 = malloc(2 * v50);
  memset(v51, 0, 2 * strlen((const char *)v48));
  v52 = strlen((const char *)v48);
  j_innosecure_x1((int)v48, (int)v51, v52);     // base64
  free(v48);
  memset(v177, 0, sizeof(v177));
  v53 = -16;
  v54 = 0;
  v55 = 0;
  do
  {
    v56 = (v53 + 16) % 3u;
    if ( v56 )
    {
      v57 = 3 * v54;
      v177[v55] = v193[v49];
      if ( v56 == 1 )
        v58 = v57 + 2;
      else
        v58 = v57 + 1;
      v59 = v55 + 1;
    }
    else
    {
      v58 = v49 + 2;
      v177[v55] = v193[v49 + 1];
      v59 = v55 | 1;
    }
    v49 += 3;
    ++v53;
    ++v54;
    v55 += 2;
    v177[v59] = v193[v58];
  }
  while ( v53 );
  v152 = 1;
  for ( k = 0; k != 32; ++k )
  {
    v61 = (unsigned __int8)v187[k];
    if ( innoSecureParityTable256[v61] == 1 )
    {
      LOBYTE(v62) = 0;
      v63 = 8;
      do
      {
        v64 = v61 >> v63--;
        v62 = (unsigned __int8)v62 | ((((unsigned __int8)v64 ^ (unsigned __int8)(v61 >> v63)) & 1) << v63);
      }
      while ( v63 );
      v65 = v177[k] ^ v62;
    }
    else
    {
      v66 = 0;
      v67 = 7;
      LOBYTE(v68) = 0;
      do
      {
        v69 = (((unsigned __int8)v177[k] ^ 0xFFu) >> v67--) & 1;
        v68 = (unsigned __int8)v68 | (v69 << v66++);
      }
      while ( v67 != -1 );
      v65 = v61 ^ v68;
    }
    v70 = (char *)v178 + k;                     // v178 : sp+0x180
    v70[0x40] = v65;                            // v178 的地址+0x40 也为密钥地址
    v70[0x80] = v65;                            // sp+0x180+0x80=sp+0x200    v182  也为密钥地址
  }
  v71 = 7;
  do
  {
    j_innosecure_x13((int)&v182, (int)&v152);   // v182 为密钥   sp+0x200
    --v71;
  }
  while ( (_BYTE)v71 );
  v72 = strlen(a1);
  v73 = v72;
  if ( v72 > 0xF )
  {
    v100 = v72 + 16;
    v101 = (v72 + 16) & 0xFFFFFFF0;
    ptr = (char *)malloc(v101);
    memset(ptr, 0, (v73 + 16) & 0xFFFFFFF0);
    if ( v101 )
    {
      v102 = v101 - v73;
      if ( (v73 & 0xF) == 0 )                   // 判断v73是否为0xf的倍数
        v102 = 0x10;
      for ( l = 0; l != v101; ++l )             // 填充方式
      {
        v104 = v102;
        if ( l < v73 )                          // 如果l>明文长度将填充0x10
          v104 = a1[l];                         // 在此处将a1的明文数据拷贝到&ptr的指针处
        ptr[l] = v104;
      }
    }
    v144 = (v73 + 16) & 0xFFFFFFF0;
    v145 = (char *)malloc(v144);
    memset(v145, 0, v144);
    if ( v100 >> 4 )                            // 判断明文长度
    {
      v105 = 0;
      do
      {
        v106 = v105;
        qmemcpy(v155, &ptr[16 * v105], 0x10u);  // &ptr 为明文所在地址
        v146 = 16 * v106;
        v147 = v106;
        v107 = 15;
        if ( v106 )
        {
          do
          {
            v155[v107] ^= *((_BYTE *)&v173 + v107);// 与iv异或
            --v107;
          }
          while ( v107 != -1 );
          for ( m = 0; m != -16; --m )
          {
            v109 = (char *)v178 + m;
            v110 = v155[m + 15];
            v111 = *((_BYTE *)&v178[19] + m + 3);// 轮密钥加,与密钥进行异或
            v109[47] = v111;
            v155[m + 15] = v111 ^ v110;
            v109[63] = v109[95];
          }
          v112 = 1;
          LOBYTE(v168) = 1;
          while ( 1 )
          {
            v115 = 15;
            v149 = v112;
            do
            {
              v155[v115] = RijnDael_AES_LONG_8113[(unsigned __int8)v155[v115]];// 字节替换
              --v115;
            }
            while ( v115 != -1 );
            v116 = v155[2];                     // 行位移
            v117 = v155[5];
            v118 = v155[13];
            v119 = v155[9];
            v120 = v155[3];
            v155[13] = v155[1];
            v155[9] = v118;
            v155[5] = v119;
            v155[1] = v117;
            v155[2] = v155[10];
            v155[10] = v116;
            v155[3] = v155[15];
            v155[15] = v155[11];
            v155[11] = v155[7];
            v155[7] = v120;
            v121 = v155[14];
            v155[14] = v155[6];
            v155[6] = v121;
            if ( v149 > 13 )                    // 加密处理轮数14
              break;
            j_innosecure_x11((int)v155);        // 列混合
            if ( v149 << 31 )
            {
              for ( n = 0; n != -16; --n )
                v155[n + 15] ^= v181[n + 16];   // 子密钥
            }
            else
            {
              j_innosecure_x13((int)v180, (int)&v168);
              for ( ii = 0; ii != -16; --ii )
                v155[ii + 15] ^= v181[ii];
            }
            v112 = v149 + 1;
          }
          j_innosecure_x13((int)v180, (int)&v168);
          for ( jj = 0; jj != -16; --jj )
            v155[jj + 15] ^= v181[jj];
        }
        else
        {
          do
          {
            v155[v107] ^= *((_BYTE *)v186 + v107);// 与iv异或
            --v107;
          }
          while ( v107 != -1 );
          for ( kk = 0; kk != -16; --kk )
          {
            v124 = (char *)v178 + kk;
            v125 = v155[kk + 15];
            v126 = *((_BYTE *)&v178[0x13] + kk + 3);
            v124[47] = v126;
            v155[kk + 15] = v126 ^ v125;
            v124[63] = v124[95];
          }
          v127 = 1;
          LOBYTE(v168) = 1;
          while ( 1 )
          {
            for ( ll = 15; ll != -1; --ll )
              v155[ll] = RijnDael_AES_LONG_8113[(unsigned __int8)v155[ll]];
            v150 = v155[3];
            v131 = v155[2];
            v132 = v155[5];
            v133 = v155[13];
            v134 = v155[9];
            v155[13] = v155[1];
            v155[9] = v133;
            v155[5] = v134;
            v155[1] = v132;
            v155[2] = v155[10];
            v155[10] = v131;
            v155[3] = v155[15];
            v155[15] = v155[11];
            v155[11] = v155[7];
            v155[7] = v150;
            v135 = v155[14];
            v155[14] = v155[6];
            v155[6] = v135;
            if ( v127 > 0xD )
              break;
            j_innosecure_x11((int)v155);
            if ( v127 << 31 )
            {
              for ( mm = 0; mm != -16; --mm )
                v155[mm + 15] ^= v181[mm + 16];
            }
            else
            {
              j_innosecure_x13((int)v180, (int)&v168);
              for ( nn = 0; nn != -16; --nn )
                v155[nn + 15] ^= v181[nn];
            }
            ++v127;
          }
          j_innosecure_x13((int)v180, (int)&v168);
          for ( i1 = 0; i1 != -16; --i1 )
            v155[i1 + 15] ^= v181[i1];
        }
        qmemcpy(&v145[v146], v155, 0x10u);
        v173 = *(_DWORD *)v155;
        v174 = *(_DWORD *)&v155[4];
        v175 = *(_DWORD *)&v155[8];
        v176 = *(_DWORD *)&v155[12];
        v105 = v147 + 1;
      }
      while ( v147 + 1 != v100 >> 4 );
    }
    v137 = (char *)malloc(v144 + 32);
    qmemcpy(v137, v145, v144);
    qmemcpy(&v137[v144], v187, 0x20u);
    v156 = 0;
    v157 = 0;
    v158 = 1732584193;
    v160 = -1732584194;
    v159 = -271733879;
    v161 = 271733878;
    j_innosecure_x22(&v156, v137, v144 + 32);
    j_innosecure_x23(&v156, v172);
    sprintf(
      v163,
      v190,
      LOBYTE(v172[0]),
      BYTE1(v172[0]),
      BYTE2(v172[0]),
      HIBYTE(v172[0]),
      LOBYTE(v172[1]),
      BYTE1(v172[1]),
      BYTE2(v172[1]),
      HIBYTE(v172[1]),
      LOBYTE(v172[2]),
      BYTE1(v172[2]),
      BYTE2(v172[2]),
      HIBYTE(v172[2]),
      LOBYTE(v172[3]),
      BYTE1(v172[3]),
      BYTE2(v172[3]),
      HIBYTE(v172[3]));
    free(v137);
    v138 = strlen((const char *)v51);
    v139 = (char *)malloc(v138 + v144 + 53);
    v140 = strlen((const char *)v51) + v144 + 53;
    v141 = v140 - 32;
    if ( v140 < 0x21 )
      v141 = 0;
    memset(v139 + 32, 0, v141);
    qmemcpy(v139, v163, 0x20u);
    v139[32] = 46;
    qmemcpy(v139 + 33, v51, strlen((const char *)v51));
    v139[strlen((const char *)v51) + 33] = 46;
    v142 = strlen((const char *)v51);
    qmemcpy(&v139[v142 + 34], &v183[49], 0x13u);
    qmemcpy(&v139[strlen((const char *)v51) + 53], v145, v144);
    *decode = v139;
    *a6 = strlen((const char *)v51) + v144 + 53;
    free(v51);
    free(v145);
    v99 = ptr;
  }
  else
  {
    for ( i2 = 0; i2 != 16; ++i2 )
    {
      v75 = 16 - v72;
      if ( i2 < v72 )
        v75 = a1[i2];
      *((_BYTE *)&v173 + i2) = v75;
    }
    v168 = v173;
    v169 = v174;
    v170 = v175;
    v171 = v176;
    for ( i3 = 15; i3 != -1; --i3 )
      *((_BYTE *)&v168 + i3) ^= *((_BYTE *)v186 + i3);
    for ( i4 = 0; i4 != -16; --i4 )
    {
      v78 = (char *)v178 + i4;
      v79 = *((_BYTE *)&v171 + i4 + 3);
      v80 = *((_BYTE *)&v178[19] + i4 + 3);
      v78[47] = v80;
      *((_BYTE *)&v171 + i4 + 3) = v80 ^ v79;
      v78[63] = v78[95];
    }
    v81 = 1;
    v151 = 1;
    while ( 1 )
    {
      for ( i5 = 15; i5 != -1; --i5 )
        *((_BYTE *)&v168 + i5) = RijnDael_AES_LONG_8113[*((unsigned __int8 *)&v168 + i5)];
      v85 = BYTE2(v168);
      v86 = BYTE1(v169);
      v87 = BYTE1(v171);
      v88 = BYTE1(v170);
      v89 = HIBYTE(v168);
      BYTE1(v171) = BYTE1(v168);
      BYTE1(v170) = v87;
      BYTE1(v169) = v88;
      BYTE1(v168) = v86;
      BYTE2(v168) = BYTE2(v170);
      BYTE2(v170) = v85;
      HIBYTE(v168) = HIBYTE(v171);
      v90 = HIBYTE(v170);
      HIBYTE(v171) = HIBYTE(v170);
      HIBYTE(v170) = HIBYTE(v169);
      HIBYTE(v169) = v89;
      v91 = BYTE2(v171);
      BYTE2(v171) = BYTE2(v169);
      BYTE2(v169) = v91;
      if ( v81 > 0xD )
        break;
      j_innosecure_x11((int)&v168);
      if ( v81 << 31 )
      {
        for ( i6 = 0; i6 != -16; --i6 )
          *((_BYTE *)&v171 + i6 + 3) ^= v181[i6 + 16];
      }
      else
      {
        j_innosecure_x13((int)v180, (int)&v151);
        for ( i7 = 0; i7 != -16; --i7 )
          *((_BYTE *)&v171 + i7 + 3) ^= v181[i7];
      }
      ++v81;
    }
    j_innosecure_x13((int)v180, (int)&v151);
    v92 = 0;
    HIBYTE(v171) = v181[0] ^ v90;
    do
    {
      *((_BYTE *)&v171 + v92 + 2) ^= v180[v92 + 14];
      --v92;
    }
    while ( v92 != -15 );
    v172[0] = v168;
    v172[1] = v169;
    v172[2] = v170;
    v172[3] = v171;
    *(_DWORD *)v163 = v168;
    *(_DWORD *)&v163[4] = v169;
    *(_DWORD *)&v163[8] = v170;
    *(_DWORD *)&v163[12] = v171;
    *(_DWORD *)&v163[16] = *(_DWORD *)v187;
    *(_DWORD *)&v163[20] = *(_DWORD *)&v187[4];
    *(_DWORD *)&v163[24] = *(_DWORD *)&v187[8];
    *(_DWORD *)&v163[28] = *(_DWORD *)&v187[12];
    v164 = *(_DWORD *)&v187[16];
    v165 = *(_DWORD *)&v187[20];
    v166 = *(_DWORD *)&v187[24];
    v167 = *(_DWORD *)&v187[28];
    v156 = 0;
    v157 = 0;
    v158 = 0x67452301;
    v160 = 0x98BADCFE;
    v159 = 4023233417;
    v161 = 0x10325476;
    j_innosecure_x22(&v156, v163, 48);
    j_innosecure_x23(&v156, v162);
    sprintf(
      v155,
      v190,
      (unsigned __int8)v162[0],
      (unsigned __int8)v162[1],
      (unsigned __int8)v162[2],
      (unsigned __int8)v162[3],
      (unsigned __int8)v162[4],
      (unsigned __int8)v162[5],
      (unsigned __int8)v162[6],
      (unsigned __int8)v162[7],
      (unsigned __int8)v162[8],
      (unsigned __int8)v162[9],
      (unsigned __int8)v162[10],
      (unsigned __int8)v162[11],
      (unsigned __int8)v162[12],
      (unsigned __int8)v162[13],
      (unsigned __int8)v162[14],
      (unsigned __int8)v162[15]);
    v93 = strlen((const char *)v51);
    v94 = (char *)malloc(v93 + 69);
    v95 = strlen((const char *)v51);
    v96 = v95 + 37;
    if ( v95 + 69 < 0x21 )
      v96 = 0;
    memset(v94 + 32, 0, v96);
    qmemcpy(v94, v155, 0x20u);
    v94[32] = 46;
    qmemcpy(v94 + 33, v51, strlen((const char *)v51));
    v94[strlen((const char *)v51) + 33] = 46;
    v97 = strlen((const char *)v51);
    qmemcpy(&v94[v97 + 34], &v183[49], 0x13u);
    v98 = strlen((const char *)v51);
    qmemcpy(&v94[v98 + 53], v172, 0x10u);
    *decode = v94;
    *a6 = strlen((const char *)v51) + 69;
    v99 = v51;
  }
  free(v99);
  return _stack_chk_guard - v194;
}

静态分析

代码中有MD5,base64等比较简单的算法,这里不再分析。本文主要结束如何静态找出AES算法的关键信息。关键信息如下: 明文,密文,IV,密钥,填充方式,加密模式,数据块大小。
1.根据IDA插件FindCrpt找出sbox,根据sbox定位AES算法。首先浏览一遍代码。根据AES加密的流程,密钥扩展和明文都需要根据sbox的数据进行替换。而两者比较明显的区别:
(1)密钥扩展函数里字节替换后会进行异或操作。
(2)明文经过字节替换后会进行行移位操作。
图片描述
根据此特征查看此处字节替换操作
图片描述
很明显字节替换后,进行了行移位。可以判断 &v155 是要加密的内存地址

1
j_innosecure_x11((int)v155);

进入此函数
图片描述
注意列混合的特征:某两个字节异或后会判断字节的最高bit位,如果最高bit位为1,则与0x1B异或。
图片描述
根据此特征即可判断 j_innosecure_x11((int)v155) 为列混合。
接下来看下AES 解密流程,下图是AES128位的流程:
图片描述
既然明文的字节替换,行移位,列混合都已找到,根据流程,这几个函数一定在一个循环之中,只要知道循环的次数,就可以知道加密的轮数。
AES128位 加密轮数为10
AES256位 加密轮数位14
根据此处判断
图片描述
加密轮数位14,说明改AES算法的密钥大小为256位,即32字节。
现在已知AES的字节替换,行移位,列混合,那后面的自然是轮密钥加过程了,如图:
图片描述
继续看下此过程,此处有个判断很关键if(v149<<31),当v149 即轮数为单数时,会执行 j_innosecure_x13((int)v180, (int)&v168),然后执行轮密钥加过程。
进入此函数,如图
图片描述
好家伙,又有字节替换过程,且替换后直接异或操作,此处应该就是密钥扩展的一部分了。看下代码,将result数组看成4x4矩阵。

1
2
3
4
5
result[1] ^= RijnDael_AES_LONG_8113[(unsigned __int8)result[30]];
 v6 = RijnDael_AES_LONG_8113[(unsigned __int8)result[29]];
 v7 = RijnDael_AES_LONG_8113[(unsigned __int8)result[28]];
 result[2] = RijnDael_AES_LONG_8113[(unsigned __int8)result[31]] ^ v3;
 result[3] = v4 ^ v7;

此处代码将矩阵最后一列循环移位一字节,然后再与第一列进行异或操作。
现在可以判断出该算法并不是一开始就将密钥进行完全扩展,而是每一轮扩展一次。
因为密钥块大小为256位,此函数每一次扩展32字节(roundkey[32]),轮密钥加过程中每一轮只与扩展密钥的16字节异或,所以第一轮与roundkey[0-15],第二轮与roundkey[16-32]异或,第三轮继续扩展密钥.....如图:
图片描述
接着继续分析:
在AES算法中,执行10或14轮加密前,明文会直接执行轮密钥加过程,根据AES密钥扩展函数,扩展密钥的前16字节或32字节即为密钥。所以循环加密之前的那次轮密钥加过程即为明文与密钥进行异或,如图:
图片描述
此图中在轮密钥加之前又有一次异或,可以判断此处是明文与IV异或。
分析到现在 AES的明文,密文,IV,密钥,密钥大小已经出来了,现在还差填充方式和加密模式。
继续分析,AES加密会将明文分割成16个字节,然后进行上图10轮或14轮的加密,所以在10轮或14轮循环加密之外必定有个分割明文的循环,如图
图片描述
继续往上分析
图片描述
分析此函数可知:
填充规则为PKCS7Padding,根据函数加密逻辑同时也可以判断加密模式为CBC,所以此AES的加密模式CBC,256位
密钥:
图片描述

 

iv:
图片描述

 

明文:
图片描述

总结:(秘籍)

1.根据sbox,找到字节替换过程,如果字节替换后是异或操作,那此处即为扩展密钥的某部分。如果出现行移位操作,列混合操作即为明文的字节替换操作。
2.列混合操作的明显特征是,先异或,再判断字节最高bit位是否为1,如果为1再与0x1b进行异或,若函数内出现判断最高位和0x1b操作即为列混合操。
3.根据字节替换,行移位,列混合即可定位轮密钥加,这些操作一定在一个循环中,找到循环条件,知道循环次数,即可判断加密轮数,根据轮数即可判断密钥大小。
4.根据字节替换,行移位,列混合,轮密钥加循环,可以找到明文与iv异或和明文轮密钥加的过程(即明文与密钥进行异或)
图片描述
如果明文没有与iv异或直接轮密钥加,即为ECB模式,若与iv异或那肯定不是ECB模式。
5.若明文大小大于16字节,在字节替换,行移位,列混合,轮密钥加循环外肯定有一个循环,用于分割明文,循环加密。一般为memcpy(a1,a2,0x10),
注意0x16 很关键,应该时刻关注0x16这个常数。通过这些特征找到明文地址,在分割明文循环之前,一定有填充函数,根据明文地址即可找到。如果填充0x16即为PKCS7Padding,如果填充为0即为ZeroPadding
6.对AES算法熟悉后,看循环次数,判断条件,memcpy(a1,a2,0x10)等下这些函数即可判断位置

 

附件为idb文件,里面有分析过程


恭喜ID[飞翔的猫咪]获看雪安卓应用安全能力认证高级安全工程师!!

最后于 2021-5-13 13:38 被Mr.YX编辑 ,原因: 修改文字
上传的附件:
收藏
点赞7
打赏
分享
最新回复 (8)
雪    币: 1
活跃值: 活跃值 (184)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bluegatar 活跃值 2021-5-12 19:05
2
0
掃噶,800多行要看一下
雪    币: 22
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
万里星河 活跃值 2021-5-13 02:37
3
0
大佬 请收下我的膝盖
顺便有二个基础问题不明白 首先就是看论坛帖子 总会提到 findEncrypt和findHash这两个插件 具体是干啥的呀 要怎么安装呀 其次是这里的sbox是指啥呀
雪    币: 11074
活跃值: 活跃值 (3156)
能力值: (RANK:200 )
在线值:
发帖
回帖
粉丝
LowRebSwrd 活跃值 4 2021-5-13 10:22
4
0
不错
雪    币: 2480
活跃值: 活跃值 (1778)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
TUGOhost 活跃值 2021-5-13 17:17
5
0
看不懂,先支持一波
雪    币: 12
活跃值: 活跃值 (223)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gannicusliu 活跃值 2021-5-19 15:09
6
0
大佬 请收下我的膝盖
雪    币: 80
活跃值: 活跃值 (76)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wate 活跃值 2021-5-19 16:05
7
0

https://blog.csdn.net/userpass_word/article/details/80484467

最后于 2021-5-19 16:06 被wate编辑 ,原因:
雪    币: 80
活跃值: 活跃值 (76)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wate 活跃值 2021-5-19 16:06
8
0
万里星河 大佬 请收下我的膝盖[em_4] 顺便有二个基础问题不明白 首先就是看论坛帖子 总会提到 findEncrypt和findHash这两个插件 具体是干啥的呀 要怎么安装呀 其次是这里的sbox是指啥 ...
https://blog.csdn.net/userpass_word/article/details/80484467
雪    币: 15
活跃值: 活跃值 (472)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jfztaq 活跃值 2021-12-9 06:00
9
0
AES_LONG_8813就是sbox?
游客
登录 | 注册 方可回帖
返回