@@ -237,13 +237,69 @@ public byte[] Encrypt(byte[] data) {
237237 }
238238 }
239239
240- class DecrypterV2 : IDecrypter {
240+ private abstract class EmulatingDecrypterBase
241+ {
242+ protected MethodDef method ;
243+ protected List < Instruction > instructions ;
244+ protected List < Local > locals ;
245+ protected readonly InstructionEmulator instrEmulator = new ( ) ;
246+ protected Local emuLocal ;
247+
248+ /**
249+ * Locates the instructions that are responsible for producing the key stream for decrypting the resource.
250+ */
251+ protected bool FindStartEnd ( IList < Instruction > instrs , out int startIndex , out int endIndex , out Local tmpLocal ) {
252+ for ( int i = 0 ; i + 8 < instrs . Count ; i ++ ) {
253+ if ( instrs [ i ] . OpCode . Code != Code . Conv_R_Un )
254+ continue ;
255+ if ( instrs [ i + 1 ] . OpCode . Code != Code . Conv_R8 )
256+ continue ;
257+ if ( instrs [ i + 2 ] . OpCode . Code != Code . Conv_U4 )
258+ continue ;
259+ if ( instrs [ i + 3 ] . OpCode . Code != Code . Add )
260+ continue ;
261+ int newEndIndex = i + 3 ;
262+ int newStartIndex = - 1 ;
263+ for ( int j = newEndIndex ; j >= 0 ; j -- ) {
264+ // Search upwards for array access or br.
265+ if ( instrs [ j ] . OpCode . Code != Code . Ldelem_U1 && ( ! instrs [ j ] . IsBr ( ) || instrs [ j - 1 ] . OpCode . Code == Code . Bne_Un_S ) )
266+ continue ;
267+
268+ // Go down to next local load, where the actual decryption should begin.
269+ for ( int k = j + 1 ; k < newEndIndex ; k ++ ) {
270+ if ( instrs [ k ] . IsLdloc ( ) ) {
271+ newStartIndex = k ;
272+ break ;
273+ }
274+ }
275+ break ;
276+ }
277+ endIndex = newEndIndex ;
278+ startIndex = newStartIndex ;
279+ tmpLocal = CheckLocal ( instrs [ startIndex ] , true ) ;
280+ return true ;
281+ }
282+ endIndex = 0 ;
283+ startIndex = 0 ;
284+ tmpLocal = null ;
285+ return false ;
286+ }
287+
288+ /**
289+ * Gets the Local referenced by the instruction if it's either ldloc or stloc (determined by isLdloc).
290+ */
291+ protected Local CheckLocal ( Instruction instr , bool isLdloc ) {
292+ if ( isLdloc && ! instr . IsLdloc ( ) )
293+ return null ;
294+ if ( ! isLdloc && ! instr . IsStloc ( ) )
295+ return null ;
296+
297+ return instr . GetLocal ( locals ) ;
298+ }
299+ }
300+
301+ class DecrypterV2 : EmulatingDecrypterBase , IDecrypter {
241302 readonly byte [ ] key , iv ;
242- MethodDef method ;
243- List < Instruction > instructions ;
244- List < Local > locals ;
245- readonly InstructionEmulator instrEmulator = new InstructionEmulator ( ) ;
246- Local emuLocal ;
247303 Parameter emuArg ;
248304 MethodDef emuMethod ;
249305 bool isNewDecrypter ;
@@ -310,49 +366,6 @@ bool Find(IList<Instruction> instrs, out int startIndex, out int endIndex, out L
310366 return true ;
311367 }
312368
313- bool FindStartEnd ( IList < Instruction > instrs , out int startIndex , out int endIndex , out Local tmpLocal ) {
314- for ( int i = 0 ; i + 8 < instrs . Count ; i ++ ) {
315- if ( instrs [ i ] . OpCode . Code != Code . Conv_R_Un )
316- continue ;
317- if ( instrs [ i + 1 ] . OpCode . Code != Code . Conv_R8 )
318- continue ;
319- if ( instrs [ i + 2 ] . OpCode . Code != Code . Conv_U4 )
320- continue ;
321- if ( instrs [ i + 3 ] . OpCode . Code != Code . Add )
322- continue ;
323- int newEndIndex = i + 3 ;
324- int newStartIndex = - 1 ;
325- for ( int x = newEndIndex ; x > 0 ; x -- )
326- if ( instrs [ x ] . OpCode . FlowControl != FlowControl . Next ) {
327- newStartIndex = x + 1 ;
328- break ;
329- }
330- if ( newStartIndex < 0 )
331- continue ;
332-
333- var checkLocs = new List < Local > ( ) ;
334- int ckStartIndex = - 1 ;
335- for ( int y = newEndIndex ; y >= newStartIndex ; y -- ) {
336- var loc = CheckLocal ( instrs [ y ] , true ) ;
337- if ( loc == null )
338- continue ;
339- if ( ! checkLocs . Contains ( loc ) )
340- checkLocs . Add ( loc ) ;
341- if ( checkLocs . Count == 3 )
342- break ;
343- ckStartIndex = y ;
344- }
345- endIndex = newEndIndex ;
346- startIndex = Math . Max ( ckStartIndex , newStartIndex ) ;
347- tmpLocal = CheckLocal ( instrs [ startIndex ] , true ) ;
348- return true ;
349- }
350- endIndex = 0 ;
351- startIndex = 0 ;
352- tmpLocal = null ;
353- return false ;
354- }
355-
356369 bool FindStartEnd2 ( ref IList < Instruction > instrs , out int startIndex , out int endIndex , out Local tmpLocal , out Parameter tmpArg , ref MethodDef methodDef , ref List < Local > locals ) {
357370 foreach ( var instr in instrs ) {
358371 if ( instr . OpCode == OpCodes . Call ) {
@@ -436,15 +449,6 @@ bool FindEnd(IList<Instruction> instrs, int startIndex, out int endIndex) {
436449 return false ;
437450 }
438451
439- Local CheckLocal ( Instruction instr , bool isLdloc ) {
440- if ( isLdloc && ! instr . IsLdloc ( ) )
441- return null ;
442- else if ( ! isLdloc && ! instr . IsStloc ( ) )
443- return null ;
444-
445- return instr . GetLocal ( locals ) ;
446- }
447-
448452 public byte [ ] Decrypt ( EmbeddedResource resource ) {
449453 var encrypted = resource . CreateReader ( ) . ToArray ( ) ;
450454 var decrypted = new byte [ encrypted . Length ] ;
@@ -517,13 +521,7 @@ public byte[] Encrypt(byte[] data) {
517521 }
518522 }
519523
520- class DecrypterV3 : IDecrypter {
521- readonly MethodDef method ;
522- List < Instruction > instructions ;
523- readonly List < Local > locals ;
524- readonly InstructionEmulator instrEmulator = new InstructionEmulator ( ) ;
525- Local emuLocal ;
526-
524+ class DecrypterV3 : EmulatingDecrypterBase , IDecrypter {
527525 public DnrDecrypterType DecrypterType => DnrDecrypterType . V3 ;
528526
529527 public DecrypterV3 ( MethodDef method ) {
@@ -578,48 +576,6 @@ bool Find(IList<Instruction> instrs, out int startIndex, out int endIndex, out L
578576 return true ;
579577 }
580578
581- /**
582- * Locates the instructions that are responsible for producing the key stream for decrypting the resource.
583- */
584- bool FindStartEnd ( IList < Instruction > instrs , out int startIndex , out int endIndex , out Local tmpLocal ) {
585- for ( int i = 0 ; i + 8 < instrs . Count ; i ++ ) {
586- if ( instrs [ i ] . OpCode . Code != Code . Conv_R_Un )
587- continue ;
588- if ( instrs [ i + 1 ] . OpCode . Code != Code . Conv_R8 )
589- continue ;
590- if ( instrs [ i + 2 ] . OpCode . Code != Code . Conv_U4 )
591- continue ;
592- if ( instrs [ i + 3 ] . OpCode . Code != Code . Add )
593- continue ;
594- int newEndIndex = i + 3 ;
595-
596- int newStartIndex = - 1 ;
597- for ( int j = newEndIndex ; j >= 0 ; j -- ) {
598- // Search upwards for array access.
599- if ( instrs [ j ] . OpCode . Code != Code . Ldelem_U1 )
600- continue ;
601-
602- // Go down to next local load, where actual decryption should begin.
603- for ( int k = j + 1 ; k < newEndIndex ; k ++ ) {
604- if ( instrs [ k ] . IsLdloc ( ) ) {
605- newStartIndex = k ;
606- break ;
607- }
608- }
609- break ;
610- }
611-
612- endIndex = newEndIndex ;
613- startIndex = newStartIndex ;
614- tmpLocal = CheckLocal ( instrs [ startIndex ] , true ) ;
615- return true ;
616- }
617- endIndex = 0 ;
618- startIndex = 0 ;
619- tmpLocal = null ;
620- return false ;
621- }
622-
623579 bool FindStart ( IList < Instruction > instrs , out int startIndex , out Local tmpLocal ) {
624580 for ( int i = 0 ; i + 8 < instrs . Count ; i ++ ) {
625581 if ( instrs [ i ] . OpCode . Code != Code . Conv_U )
@@ -675,18 +631,6 @@ bool FindEnd(IList<Instruction> instrs, int startIndex, out int endIndex) {
675631 return false ;
676632 }
677633
678- /**
679- * Gets the Local referenced by the instruction if it's either ldloc or stloc (determined by isLdloc).
680- */
681- Local CheckLocal ( Instruction instr , bool isLdloc ) {
682- if ( isLdloc && ! instr . IsLdloc ( ) )
683- return null ;
684- if ( ! isLdloc && ! instr . IsStloc ( ) )
685- return null ;
686-
687- return instr . GetLocal ( locals ) ;
688- }
689-
690634 public byte [ ] Decrypt ( EmbeddedResource resource ) {
691635 var encrypted = resource . CreateReader ( ) . ToArray ( ) ;
692636 var decrypted = new byte [ encrypted . Length ] ;
@@ -766,14 +710,10 @@ public byte[] Encrypt(byte[] data) {
766710 }
767711 }
768712
769- class DecrypterV4 : IDecrypter {
713+ class DecrypterV4 : EmulatingDecrypterBase , IDecrypter {
770714 readonly byte [ ] key , iv ;
771715 MethodDef decryptMethod ;
772716 MethodDef emuMethod ;
773- List < Instruction > instructions ;
774- List < Local > locals ;
775- readonly InstructionEmulator instrEmulator = new InstructionEmulator ( ) ;
776- Local emuLocal ;
777717
778718 public DnrDecrypterType DecrypterType => DnrDecrypterType . V4 ;
779719
@@ -908,43 +848,6 @@ bool Find(IList<Instruction> instrs, out int startIndex, out int endIndex, out L
908848 return true ;
909849 }
910850
911- bool FindStartEnd ( IList < Instruction > instrs , out int startIndex , out int endIndex , out Local tmpLocal ) {
912- for ( int i = 0 ; i + 8 < instrs . Count ; i ++ ) {
913- if ( instrs [ i ] . OpCode . Code != Code . Conv_R_Un )
914- continue ;
915- if ( instrs [ i + 1 ] . OpCode . Code != Code . Conv_R8 )
916- continue ;
917- if ( instrs [ i + 2 ] . OpCode . Code != Code . Conv_U4 )
918- continue ;
919- if ( instrs [ i + 3 ] . OpCode . Code != Code . Add )
920- continue ;
921- int newEndIndex = i + 3 ;
922- int newStartIndex = - 1 ;
923- for ( int j = newEndIndex ; j >= 0 ; j -- ) {
924- // Search upwards for array access.
925- if ( instrs [ j ] . OpCode . Code != Code . Ldelem_U1 )
926- continue ;
927-
928- // Go down to next local load, where actual decryption should begin.
929- for ( int k = j + 1 ; k < newEndIndex ; k ++ ) {
930- if ( instrs [ k ] . IsLdloc ( ) ) {
931- newStartIndex = k ;
932- break ;
933- }
934- }
935- break ;
936- }
937- endIndex = newEndIndex ;
938- startIndex = newStartIndex ;
939- tmpLocal = CheckLocal ( instrs [ startIndex ] , true ) ;
940- return true ;
941- }
942- endIndex = 0 ;
943- startIndex = 0 ;
944- tmpLocal = null ;
945- return false ;
946- }
947-
948851 bool FindStart ( IList < Instruction > instrs , out int startIndex , out Local tmpLocal ) {
949852 for ( int i = 0 ; i + 8 < instrs . Count ; i ++ ) {
950853 if ( instrs [ i ] . OpCode . Code != Code . Conv_U )
@@ -1000,15 +903,6 @@ bool FindEnd(IList<Instruction> instrs, int startIndex, out int endIndex) {
1000903 return false ;
1001904 }
1002905
1003- Local CheckLocal ( Instruction instr , bool isLdloc ) {
1004- if ( isLdloc && ! instr . IsLdloc ( ) )
1005- return null ;
1006- else if ( ! isLdloc && ! instr . IsStloc ( ) )
1007- return null ;
1008-
1009- return instr . GetLocal ( locals ) ;
1010- }
1011-
1012906 public byte [ ] Decrypt ( EmbeddedResource resource ) {
1013907 var encrypted = resource . CreateReader ( ) . ToArray ( ) ;
1014908 var decrypted = new byte [ encrypted . Length ] ;
0 commit comments