@@ -20,6 +20,7 @@ You should have received a copy of the GNU General Public License
2020using System ;
2121using System . Collections . Generic ;
2222using System . IO ;
23+ using System . Linq ;
2324using dnlib . IO ;
2425using dnlib . DotNet ;
2526using dnlib . DotNet . MD ;
@@ -126,15 +127,23 @@ public bool Decrypt(MyPEImage peImage, ISimpleDeobfuscator simpleDeobfuscator, r
126127
127128 var methodsDataReader = ByteArrayDataReaderFactory . CreateReader ( methodsData ) ;
128129
129- int tmp = methodsDataReader . ReadInt32 ( ) ;
130- if ( ( tmp & 0xFF000000 ) == 0x06000000 )
131- methodsDataReader . ReadInt32 ( ) ;
132- else
133- methodsDataReader . Position -= 4 ;
130+ int tmp ;
131+ if ( FindBinaryReaderMethod ( simpleDeobfuscator , out var popCallsCount ) && popCallsCount > 3 )
132+ for ( var i = 0 ; i < popCallsCount ; i ++ )
133+ methodsDataReader . ReadInt32 ( ) ;
134+ else {
135+ tmp = methodsDataReader . ReadInt32 ( ) ;
136+ if ( ( tmp & 0xFF000000 ) == 0x06000000 )
137+ methodsDataReader . ReadInt32 ( ) ;
138+ else
139+ methodsDataReader . Position -= 4 ;
140+ }
134141
135142 int patchCount = methodsDataReader . ReadInt32 ( ) ;
136- int mode = methodsDataReader . ReadInt32 ( ) ;
143+ if ( patchCount > methodsDataReader . BytesLeft / 8 )
144+ patchCount = methodsDataReader . ReadInt32 ( ) ;
137145
146+ int mode = methodsDataReader . ReadInt32 ( ) ;
138147 tmp = methodsDataReader . ReadInt32 ( ) ;
139148 methodsDataReader . Position -= 4 ;
140149 if ( ( tmp & 0xFF000000 ) == 0x06000000 ) {
@@ -253,6 +262,53 @@ public bool Decrypt(MyPEImage peImage, ISimpleDeobfuscator simpleDeobfuscator, r
253262 return true ;
254263 }
255264
265+ // Adapted from SychicBoy's NETReactorSlayer
266+ private bool FindBinaryReaderMethod ( ISimpleDeobfuscator simpleDeobfuscator , out int popCallsCount ) {
267+ popCallsCount = 0 ;
268+ var decrypterMethod = encryptedResource . Method ;
269+ var calls = decrypterMethod . Body . Instructions
270+ . Where ( x => x . OpCode == OpCodes . Callvirt && x . Operand is MethodDef md && md . MethodSig . RetType . FullName == "System.Int32" )
271+ . Select ( x => x . Operand )
272+ . Cast < MethodDef > ( ) ;
273+ foreach ( var method in calls )
274+ try {
275+ simpleDeobfuscator . Deobfuscate ( method ) ;
276+ if ( method . Body . Instructions . Count != 4 )
277+ continue ;
278+
279+ if ( ! method . Body . Instructions [ 0 ] . IsLdarg ( )
280+ || method . Body . Instructions [ 1 ] . OpCode != OpCodes . Ldfld
281+ || method . Body . Instructions [ 2 ] . OpCode . Code is not ( Code . Callvirt or Code . Call )
282+ || method . Body . Instructions [ 3 ] . OpCode != OpCodes . Ret )
283+ continue ;
284+
285+ if ( ! method . Body . Instructions [ 2 ] . Operand . ToString ( ) ! . Contains ( "System.Int32" ) )
286+ continue ;
287+
288+ for ( var i = 0 ; i < decrypterMethod . Body . Instructions . Count ; i ++ )
289+ try {
290+ if ( ! decrypterMethod . Body . Instructions [ i ] . IsLdloc ( )
291+ || decrypterMethod . Body . Instructions [ i + 1 ] . OpCode != OpCodes . Callvirt
292+ || decrypterMethod . Body . Instructions [ i + 1 ] . Operand is not MethodDef calledMethod
293+ || decrypterMethod . Body . Instructions [ i + 2 ] . OpCode != OpCodes . Pop )
294+ continue ;
295+
296+ if ( MethodEqualityComparer . CompareDeclaringTypes . Equals ( calledMethod , method ) )
297+ popCallsCount ++ ;
298+ }
299+ catch {
300+ // ignored
301+ }
302+
303+ return true ;
304+ }
305+ catch {
306+ // ignored
307+ }
308+
309+ return false ;
310+ }
311+
256312 public static bool IsNewer45Decryption ( MethodDef method ) {
257313 if ( method == null || method . Body == null )
258314 return false ;
0 commit comments