@@ -47,6 +47,7 @@ class StringDecrypter : IDisposable {
47
47
EfConstantsReader stringMethodConsts ;
48
48
bool isV32OrLater ;
49
49
bool isV50OrLater ;
50
+ bool isV51OrLater ;
50
51
int ? validStringDecrypterValue ;
51
52
DynamicDynocodeIterator dynocode ;
52
53
MethodDef realMethod ;
@@ -154,6 +155,12 @@ public void Find() {
154
155
stringMethod = method ;
155
156
realMethod = GetRealDecrypterMethod ( method ) ;
156
157
isV50OrLater = true ;
158
+ foreach ( var inst in stringMethod . Body . Instructions ) {
159
+ if ( inst . OpCode . Code == Code . Cgt_Un ) {
160
+ isV51OrLater = true ;
161
+ break ;
162
+ }
163
+ }
157
164
}
158
165
else stringMethod = method ;
159
166
@@ -318,10 +325,22 @@ bool FindConstants(ISimpleDeobfuscator simpleDeobfuscator) {
318
325
if ( decrypterType . Detected && ! decrypterType . Initialize ( ) )
319
326
return false ;
320
327
328
+ if ( ! isV50OrLater ) {
329
+ decrypterType . ShiftConsts = new List < int > { 24 , 16 , 8 , 0 , 16 , 8 , 0 , 24 } ;
330
+ }
331
+ else {
332
+ List < int > shiftConsts ;
333
+ if ( ! FindShiftInts ( decrypterType . Int64Method , out shiftConsts ) )
334
+ return false ;
335
+
336
+ decrypterType . ShiftConsts = shiftConsts ;
337
+ }
338
+
321
339
if ( ! FindInts ( index ) )
322
340
return false ;
323
341
}
324
342
343
+
325
344
InitializeFlags ( ) ;
326
345
Initialize ( ) ;
327
346
@@ -421,7 +440,14 @@ static int GetFlagsOffset(MethodDef method, int index, Local local) {
421
440
return - 1 ;
422
441
}
423
442
424
- static Local GetFlagsLocal ( MethodDef method , int index ) {
443
+ Local GetFlagsLocal ( MethodDef method , int index ) {
444
+ if ( isV51OrLater )
445
+ return GetFlagsLocalNew ( method , index ) ;
446
+ return GetFlagsLocalOld ( method , index ) ;
447
+ }
448
+
449
+ // <= 5.0
450
+ static Local GetFlagsLocalOld ( MethodDef method , int index ) {
425
451
var instrs = method . Body . Instructions ;
426
452
if ( index + 5 >= instrs . Count )
427
453
return null ;
@@ -441,6 +467,24 @@ static Local GetFlagsLocal(MethodDef method, int index) {
441
467
return stloc . GetLocal ( method . Body . Variables ) ;
442
468
}
443
469
470
+ // 5.1+
471
+ // Uses different OpCodes
472
+ static Local GetFlagsLocalNew ( MethodDef method , int index ) {
473
+ var instrs = method . Body . Instructions ;
474
+ if ( index + 5 >= instrs . Count )
475
+ return null ;
476
+ if ( instrs [ index ++ ] . OpCode . Code != Code . And )
477
+ return null ;
478
+ if ( instrs [ index ++ ] . OpCode . Code != Code . Ldc_I4_0 )
479
+ return null ;
480
+ if ( instrs [ index ++ ] . OpCode . Code != Code . Cgt_Un )
481
+ return null ;
482
+ var stloc = instrs [ index ++ ] ;
483
+ if ( ! stloc . IsStloc ( ) )
484
+ return null ;
485
+ return stloc . GetLocal ( method . Body . Variables ) ;
486
+ }
487
+
444
488
void Initialize ( ) {
445
489
reader = new BinaryReader ( encryptedResource . GetResourceStream ( ) ) ;
446
490
short len = ( short ) ( reader . ReadInt16 ( ) ^ s1 ) ;
@@ -592,6 +636,51 @@ EmbeddedResource FindResourceFromStringBuilder(MethodDef method) {
592
636
return DotNetUtils . GetResource ( module , sb . ToString ( ) ) as EmbeddedResource ;
593
637
}
594
638
639
+ bool FindShiftInts ( MethodDef method , out List < int > bytes ) {
640
+ var instrs = method . Body . Instructions ;
641
+ var constantsReader = new EfConstantsReader ( method ) ;
642
+ bytes = new List < int > ( 8 ) ;
643
+
644
+ for ( int i = 0 ; i < instrs . Count - 4 ; i ++ ) {
645
+ if ( bytes . Count >= 8 )
646
+ return true ;
647
+
648
+ var ldloc1 = instrs [ i ] ;
649
+ if ( ldloc1 . OpCode . Code != Code . Ldloc_1 )
650
+ continue ;
651
+
652
+ var ldlocs = instrs [ i + 1 ] ;
653
+ if ( ldlocs . OpCode . Code != Code . Ldloc_S )
654
+ continue ;
655
+
656
+ var maybe = instrs [ i + 2 ] ;
657
+ if ( maybe . OpCode . Code == Code . Conv_U1 ) {
658
+ var callvirt = instrs [ i + 3 ] ;
659
+ if ( callvirt . OpCode . Code != Code . Callvirt )
660
+ return false ;
661
+
662
+ bytes . Add ( 0 ) ;
663
+ continue ;
664
+ }
665
+ var shr = instrs [ i + 3 ] ;
666
+ if ( shr . OpCode . Code != Code . Shr )
667
+ return false ;
668
+
669
+ var convu1 = instrs [ i + 4 ] ;
670
+ if ( convu1 . OpCode . Code != Code . Conv_U1 )
671
+ return false ;
672
+
673
+ int constant ;
674
+ int index = i + 2 ;
675
+ if ( ! constantsReader . GetInt32 ( ref index , out constant ) )
676
+ return false ;
677
+
678
+ bytes . Add ( constant ) ;
679
+ }
680
+
681
+ return false ;
682
+ }
683
+
595
684
static MethodDef FindInt64Method ( MethodDef method ) {
596
685
foreach ( var instr in method . Body . Instructions ) {
597
686
if ( instr . OpCode . Code != Code . Call )
@@ -698,7 +787,7 @@ bool FindInts(int index) {
698
787
break ;
699
788
}
700
789
}
701
- done : ;
790
+ done :
702
791
703
792
foreach ( var val in fields . Values ) {
704
793
if ( val == null )
@@ -711,6 +800,13 @@ bool FindInts(int index) {
711
800
}
712
801
713
802
bool EmulateDynocode ( InstructionEmulator emu , ref int index ) {
803
+ if ( isV51OrLater )
804
+ return EmulateDynocodeNew ( emu , ref index ) ;
805
+ return EmulateDynocodeOld ( emu , ref index ) ;
806
+ }
807
+
808
+ // <= 5.0
809
+ bool EmulateDynocodeOld ( InstructionEmulator emu , ref int index ) {
714
810
var instrs = stringMethod . Body . Instructions ;
715
811
var instr = instrs [ index ] ;
716
812
@@ -770,6 +866,68 @@ bool EmulateDynocode(InstructionEmulator emu, ref int index) {
770
866
return true ;
771
867
}
772
868
869
+ // 5.1+
870
+ // the only changes are the indexes of ldloc and stfld
871
+ bool EmulateDynocodeNew ( InstructionEmulator emu , ref int index ) {
872
+ var instrs = stringMethod . Body . Instructions ;
873
+ var instr = instrs [ index ] ;
874
+
875
+ var ctor = instr . Operand as MethodDef ;
876
+ if ( ctor == null || ctor . MethodSig . GetParamCount ( ) != 1 || ctor . MethodSig . Params [ 0 ] . ElementType != ElementType . I4 )
877
+ return false ;
878
+
879
+ if ( index + 4 >= instrs . Count )
880
+ return false ;
881
+ var ldloc = instrs [ index + 2 ] ;
882
+ var stfld = instrs [ index + 3 ] ;
883
+ if ( ! ldloc . IsLdloc ( ) || stfld . OpCode . Code != Code . Stfld )
884
+ return false ;
885
+ var enumerableField = stfld . Operand as FieldDef ;
886
+ if ( enumerableField == null )
887
+ return false ;
888
+
889
+ var initValue = emu . GetLocal ( ldloc . GetLocal ( stringMethod . Body . Variables ) ) as Int32Value ;
890
+ if ( initValue == null || ! initValue . AllBitsValid ( ) )
891
+ return false ;
892
+
893
+ int leaveIndex = FindLeave ( instrs , index ) ;
894
+ if ( leaveIndex < 0 )
895
+ return false ;
896
+ var afterLoop = instrs [ leaveIndex ] . Operand as Instruction ;
897
+ if ( afterLoop == null )
898
+ return false ;
899
+ int newIndex = instrs . IndexOf ( afterLoop ) ;
900
+ var loopLocal = GetDCLoopLocal ( index , newIndex ) ;
901
+ if ( loopLocal == null )
902
+ return false ;
903
+ var initValue2 = emu . GetLocal ( loopLocal ) as Int32Value ;
904
+ if ( initValue2 == null || ! initValue2 . AllBitsValid ( ) )
905
+ return false ;
906
+
907
+ int loopStart = GetIndexOfCall ( instrs , index , leaveIndex , "System.Int32" , "()" ) ;
908
+ int loopEnd = GetIndexOfCall ( instrs , loopStart , leaveIndex , "System.Boolean" , "()" ) ;
909
+ if ( loopStart < 0 || loopEnd < 0 )
910
+ return false ;
911
+ loopStart ++ ;
912
+ loopEnd -- ;
913
+
914
+ dynocode . Initialize ( module ) ;
915
+ var ctorArg = emu . Pop ( ) as Int32Value ;
916
+ if ( ctorArg == null || ! ctorArg . AllBitsValid ( ) )
917
+ return false ;
918
+ dynocode . CreateEnumerable ( ctor , new object [ ] { ctorArg . Value } ) ;
919
+ dynocode . WriteEnumerableField ( enumerableField . MDToken . ToUInt32 ( ) , initValue . Value ) ;
920
+ dynocode . CreateEnumerator ( ) ;
921
+ foreach ( var val in dynocode ) {
922
+ emu . Push ( new Int32Value ( val ) ) ;
923
+ for ( int i = loopStart ; i < loopEnd ; i ++ )
924
+ emu . Emulate ( instrs [ i ] ) ;
925
+ }
926
+
927
+ index = newIndex - 1 ;
928
+ return true ;
929
+ }
930
+
773
931
static int GetIndexOfCall ( IList < Instruction > instrs , int startIndex , int endIndex , string returnType , string parameters ) {
774
932
if ( startIndex < 0 || endIndex < 0 )
775
933
return - 1 ;
0 commit comments