@@ -147,9 +147,9 @@ class Decrypter3 : IDecrypter {
147147 ModuleDefMD module ;
148148 Inflater inflater ;
149149
150- public Decrypter3 ( ModuleDefMD module , MethodDef decryptMethod ) {
150+ public Decrypter3 ( ModuleDefMD module , MethodDef decryptMethod , ISimpleDeobfuscator deobfuscator ) {
151151 this . module = module ;
152- inflater = InflaterCreator . Create ( decryptMethod , true ) ;
152+ inflater = InflaterCreator . Create ( decryptMethod , deobfuscator , true ) ;
153153 }
154154
155155 public byte [ ] Decrypt ( byte [ ] encryptedData ) {
@@ -199,6 +199,80 @@ bool GetKeyIv(byte[] headerData, out byte[] key, out byte[] iv) {
199199 }
200200 }
201201
202+ // v10/v11
203+ class Decrypter4 : IDecrypter {
204+ ModuleDefMD module ;
205+ Inflater inflater ;
206+
207+ public Decrypter4 ( ModuleDefMD module , MethodDef decryptMethod , ISimpleDeobfuscator deobfuscator ) {
208+ this . module = module ;
209+ inflater = InflaterCreator . Create ( decryptMethod , deobfuscator , true ) ;
210+ }
211+
212+ public byte [ ] Decrypt ( byte [ ] encryptedData ) {
213+ int index = 0 ;
214+ ParseHeader ( GetHeaderData ( encryptedData , ref index , out var iv ) ,
215+ out var key ,
216+ out var flag ,
217+ out var cipherType ) ;
218+ bool isEncrypted = ( flag & 2 ) != 0 ;
219+ bool isCompressed = ( flag & 1 ) != 0 ;
220+
221+ byte [ ] data = new byte [ encryptedData . Length - index ] ;
222+ Array . Copy ( encryptedData , index , data , 0 , encryptedData . Length - index ) ;
223+
224+ if ( isEncrypted ) {
225+ if ( cipherType == 1 )
226+ data = DeobUtils . DesDecrypt ( data , 0 , data . Length , key , iv ) ;
227+ else if ( cipherType is 2 or 4 )
228+ data = DeobUtils . AesDecrypt ( data , key , iv ) ;
229+ else if ( cipherType == 3 )
230+ data = DeobUtils . Des3Decrypt ( data , key , iv ) ;
231+ else
232+ throw new Exception ( $ "Unsupported cipher type { cipherType } ") ;
233+ }
234+
235+ if ( isCompressed ) {
236+ data = DeobUtils . Inflate ( data , inflater ) ;
237+ }
238+
239+ return data ;
240+ }
241+
242+ byte [ ] GetHeaderData ( byte [ ] encryptedData , ref int index , out byte [ ] iv ) {
243+ var headerData = new byte [ BitConverter . ToUInt16 ( encryptedData , index ) ] ;
244+ Array . Copy ( encryptedData , index + 2 , headerData , 0 , headerData . Length ) ;
245+ index += headerData . Length + 2 ;
246+
247+ iv = new byte [ encryptedData [ index ++ ] ] ;
248+ Array . Copy ( encryptedData , index , iv , 0 , iv . Length ) ;
249+ index += iv . Length ;
250+ for ( int i = 0 ; i < headerData . Length ; i ++ )
251+ headerData [ i ] ^= iv [ i % iv . Length ] ;
252+
253+ return headerData ;
254+ }
255+
256+ void ParseHeader ( byte [ ] headerData , out byte [ ] key , out byte flag , out byte cipherType ) {
257+ var reader = new BinaryReader ( new MemoryStream ( headerData ) ) ;
258+
259+ /*var license =*/ reader . ReadString ( ) ;
260+ flag = reader . ReadByte ( ) ;
261+ cipherType = reader . ReadByte ( ) ;
262+ byte pubKeyOffset = reader . ReadByte ( ) ;
263+
264+ key = reader . ReadBytes ( reader . ReadByte ( ) ) ;
265+ if ( pubKeyOffset < 64 ) {
266+ if ( reader . BaseStream . Position < reader . BaseStream . Length )
267+ throw new Exception ( "Expected end of header" ) ;
268+ }
269+ else {
270+ Array . Copy ( module . Assembly . PublicKey . Data , pubKeyOffset + 12 , key , 0 , key . Length ) ;
271+ //key[5] |= 0x80;
272+ }
273+ }
274+ }
275+
202276 public MethodDef DecryptMethod {
203277 set {
204278 if ( value == null )
@@ -222,7 +296,8 @@ public static MethodDef FindDecrypterMethod(MethodDef method) {
222296 var calledMethod = instr . Operand as MethodDef ;
223297 if ( calledMethod == null || ! calledMethod . IsStatic || calledMethod . Body == null )
224298 continue ;
225- if ( ! DotNetUtils . IsMethod ( calledMethod , "System.IO.MemoryStream" , "(System.IO.Stream)" ) )
299+ if ( ! DotNetUtils . IsMethod ( calledMethod , "System.IO.MemoryStream" , "(System.IO.Stream)" )
300+ && ! DotNetUtils . IsMethod ( calledMethod , "System.IO.Stream" , "(System.IO.Stream)" ) )
226301 continue ;
227302
228303 return calledMethod ;
@@ -238,8 +313,10 @@ public byte[] Decrypt(byte[] encryptedData) {
238313 }
239314
240315 IDecrypter CreateDecrypter ( byte [ ] encryptedData ) {
316+ if ( decryptMethod != null && DeobUtils . HasInteger ( decryptMethod , 64 ) )
317+ return new Decrypter4 ( module , decryptMethod , simpleDeobfuscator ) ;
241318 if ( decryptMethod != null && DeobUtils . HasInteger ( decryptMethod , 6 ) )
242- return new Decrypter3 ( module , decryptMethod ) ;
319+ return new Decrypter3 ( module , decryptMethod , simpleDeobfuscator ) ;
243320 if ( IsV30 ( encryptedData ) )
244321 return new Decrypter1 ( module ) ;
245322 return new Decrypter2 ( module ) ;
0 commit comments