1+ //css_co /unsafe
2+ //css_ref dnlib.dll
3+ using System ;
4+ using dnlib . DotNet ;
5+ using dnlib . DotNet . Emit ;
6+ using dnlib . DotNet . Writer ;
7+ using System . Diagnostics ;
8+ using System . Collections . Generic ;
9+ using System . Linq ;
10+ using System . Reflection ;
11+ using System . Windows . Forms ;
12+ using System . IO ;
13+ using System . Threading ;
14+ using System . Runtime . CompilerServices ;
15+ using System . Runtime . InteropServices ;
16+
17+ class Script
18+ {
19+ public static AssemblyWriter assemblyWriter ;
20+ public static Assembly assembly ;
21+ public static MethodDef currentMethod ;
22+ public static List < TypeDef > junkType = new List < TypeDef > ( ) ;
23+
24+ [ STAThread ]
25+ static public void Main ( string [ ] args )
26+ {
27+ try
28+ {
29+ Console . BackgroundColor = ConsoleColor . White ;
30+ Console . ForegroundColor = ConsoleColor . Black ;
31+ Console . WriteLine ( "*********************************" ) ;
32+ Console . WriteLine ( "*** ***" ) ;
33+ Console . WriteLine ( "*** ILProtector Unpacker ***" ) ;
34+ Console . WriteLine ( "*** Coded By RexProg ***" ) ;
35+ Console . WriteLine ( "*** ***" ) ;
36+ Console . WriteLine ( "*********************************" ) ;
37+ Console . ForegroundColor = ConsoleColor . Blue ;
38+ Console . WriteLine ( "[?] Enter Your Program Path : " ) ;
39+ Console . ForegroundColor = ConsoleColor . Red ;
40+
41+ var path = Console . ReadLine ( ) ;
42+
43+ if ( path == string . Empty )
44+ return ;
45+ if ( path . StartsWith ( "\" " ) && path [ path . Length - 1 ] == '"' )
46+ path = path . Substring ( 1 , path . Length - 2 ) ;
47+
48+ if ( ! File . Exists ( path ) )
49+ {
50+ Console . ForegroundColor = ConsoleColor . Blue ;
51+ Console . WriteLine ( "[!] File not found" ) ;
52+ Console . WriteLine ( "[!] Press key to exit..." ) ;
53+ Console . Read ( ) ;
54+ return ;
55+ }
56+ Console . ForegroundColor = ConsoleColor . DarkRed ;
57+
58+ assemblyWriter = new AssemblyWriter ( path ) ;
59+ assembly = Assembly . LoadFrom ( path ) ;
60+ Console . WriteLine ( "[+] Wait..." ) ;
61+
62+ Memory . Hook ( typeof ( StackTrace ) . GetMethod ( "GetFrame" , BindingFlags . Instance | BindingFlags . Public ) , typeof ( Script ) . GetMethod ( "Hook" , BindingFlags . Instance | BindingFlags . Public ) ) ;
63+
64+ var types = assemblyWriter . moduleDef . GetTypes ( ) ;
65+ var list = ( types as IList < TypeDef > ) ?? types . ToList < TypeDef > ( ) ;
66+
67+ var globalType = assemblyWriter . moduleDef . GlobalType ;
68+
69+ var fieldMDToken = 0 ;
70+
71+ foreach ( FieldDef fieldDef in globalType . Fields )
72+ {
73+ if ( fieldDef . Name == "Invoke" )
74+ fieldMDToken = fieldDef . MDToken . ToInt32 ( ) ;
75+ }
76+ if ( fieldMDToken == 0 )
77+ Console . WriteLine ( "[!] Couldn't find Invoke" ) ;
78+
79+ var fieldValue = assembly . Modules . FirstOrDefault < Module > ( ) . ResolveField ( fieldMDToken ) . GetValue ( null ) ;
80+
81+ var method = fieldValue . GetType ( ) . GetMethod ( "Invoke" ) ;
82+
83+ if ( method == null )
84+ Console . WriteLine ( "[!] Couldn't find InvokeMethod" ) ;
85+
86+ InvokeDelegates ( list , method , fieldValue ) ;
87+
88+ StringDecrypter stringDecrypter = new StringDecrypter ( assembly ) ;
89+ stringDecrypter . ReplaceStrings ( list ) ;
90+
91+ foreach ( var typeDef in junkType )
92+ {
93+ typeDef . DeclaringType . NestedTypes . Remove ( typeDef ) ;
94+ }
95+ MethodDef methodDef = globalType . FindStaticConstructor ( ) ;
96+
97+ if ( methodDef . HasBody )
98+ {
99+ var startIndex = methodDef . Body . Instructions . IndexOf ( methodDef . Body . Instructions . FirstOrDefault ( inst =>
100+ ( inst . OpCode == OpCodes . Call
101+ && ( ( IMethod ) inst . Operand ) . Name == "GetIUnknownForObject" ) ) ) - 2 ;
102+
103+ var endindex = methodDef . Body . Instructions . IndexOf ( methodDef . Body . Instructions . FirstOrDefault ( inst =>
104+ ( inst . OpCode == OpCodes . Call
105+ && ( ( IMethod ) inst . Operand ) . Name == "Release" ) ) ) + 2 ;
106+
107+ methodDef . Body . ExceptionHandlers . Remove ( methodDef . Body . ExceptionHandlers . FirstOrDefault ( exh => exh . HandlerEnd == methodDef . Body . Instructions [ endindex + 1 ] ) ) ;
108+
109+ for ( int i = startIndex ; i <= endindex ; i ++ )
110+ methodDef . Body . Instructions . Remove ( methodDef . Body . Instructions [ startIndex ] ) ;
111+ }
112+
113+ foreach ( var meth in globalType . Methods . Where ( met => ( met . ImplMap ? . Module . Name . ToString ( ) == "Protect32.dll" || met . ImplMap ? . Module . Name . ToString ( ) == "Protect64.dll" ) ) . ToList ( ) )
114+ globalType . Remove ( meth ) ;
115+
116+ var invokeField = globalType . Fields . FirstOrDefault ( fld => fld . Name == "Invoke" ) ;
117+ assemblyWriter . moduleDef . Types . Remove ( invokeField . FieldType . ToTypeDefOrRef ( ) . ResolveTypeDef ( ) ) ;
118+ globalType . Fields . Remove ( invokeField ) ;
119+
120+ assemblyWriter . Save ( ) ;
121+ Console . ForegroundColor = ConsoleColor . Blue ;
122+ Console . WriteLine ( "[!] Program Unpacked" ) ;
123+ }
124+ catch ( Exception ex )
125+ {
126+ Console . WriteLine ( "[!] Exception :\n " + ex . Message ) ;
127+ }
128+ Console . WriteLine ( "[!] Press key to exit..." ) ;
129+ Console . Read ( ) ;
130+ }
131+
132+ private static void InvokeDelegates ( IList < TypeDef > typeDefs , MethodInfo invokeMethod , object invokeField )
133+ {
134+ foreach ( TypeDef typeDef in typeDefs )
135+ {
136+ foreach ( MethodDef methodDef in typeDef . Methods )
137+ {
138+ if ( ! ( methodDef . Module . Name != assembly . ManifestModule . ScopeName ) && methodDef . HasBody && methodDef . Body . Instructions . Count > 2 && methodDef . Body . Instructions [ 0 ] . OpCode == OpCodes . Ldsfld && methodDef . Body . Instructions [ 0 ] . Operand . ToString ( ) . Contains ( "Invoke" ) && methodDef . Body . Instructions [ 1 ] . IsLdcI4 ( ) )
139+ {
140+ currentMethod = methodDef ;
141+
142+ var _MDToken = ( ( IType ) methodDef . Body . Instructions [ 3 ] . Operand ) . MDToken . ToInt32 ( ) ;
143+ junkType . Add ( typeDef . NestedTypes . FirstOrDefault ( net => net . MDToken . ToInt32 ( ) == _MDToken ) ) ;
144+
145+ object method = invokeMethod . Invoke ( invokeField , new object [ ] { ( int ) methodDef . Body . Instructions [ 1 ] . Operand } ) ;
146+
147+ try
148+ {
149+ var dynamicMethodBodyReader = new DynamicMethodBodyReader ( assemblyWriter . moduleDef , method ) ;
150+ dynamicMethodBodyReader . Read ( ) ;
151+ var method2 = dynamicMethodBodyReader . GetMethod ( ) ;
152+ assemblyWriter . WriteMethod ( method2 ) ;
153+ }
154+ catch ( Exception ex )
155+ {
156+ Console . WriteLine ( "Error in Read(): " + ex . Message + "\n Method : " + method . ToString ( ) ) ;
157+ }
158+ }
159+ }
160+ }
161+ }
162+
163+ public StackFrame Hook ( int num )
164+ {
165+ StackFrame [ ] frames = new StackTrace ( ) . GetFrames ( ) ;
166+
167+ for ( int i = 0 ; i < frames . Length ; i ++ )
168+ {
169+ MethodBase method = frames [ i ] . GetMethod ( ) ;
170+
171+ if ( num == 0 && method . ToString ( ) . StartsWith ( "System.Delegate (" ) )
172+ {
173+ return frames [ i ] ;
174+ }
175+ if ( num == 1 && method . ToString ( ) . StartsWith ( "System.Delegate (" ) )
176+ {
177+ MethodBase value = assembly . Modules . FirstOrDefault < Module > ( ) . ResolveMethod ( currentMethod . MDToken . ToInt32 ( ) ) ;
178+ typeof ( StackFrame ) . GetField ( "method" , BindingFlags . Instance | BindingFlags . NonPublic ) . SetValue ( frames [ i + 1 ] , value ) ;
179+ return frames [ i + 1 ] ;
180+ }
181+ }
182+ return null ;
183+ }
184+ }
185+
186+ internal class StringDecrypter
187+ {
188+ private readonly Assembly assembly ;
189+ private object _decryptField ;
190+ private MethodInfo decryptMethod ;
191+
192+ internal StringDecrypter ( Assembly assembly )
193+ {
194+ this . assembly = assembly ;
195+ }
196+
197+ internal void ReplaceStrings ( IList < TypeDef > typeDefs )
198+ {
199+ foreach ( TypeDef typeDef in typeDefs )
200+ {
201+ foreach ( MethodDef methodDef in typeDef . Methods )
202+ {
203+ if ( methodDef . HasBody )
204+ {
205+ IList < Instruction > instructions = methodDef . Body . Instructions ;
206+
207+ for ( int i = 0 ; i < instructions . Count ; i ++ )
208+ {
209+ Instruction instruction = instructions [ i ] ;
210+
211+ if ( instruction . OpCode == OpCodes . Ldsfld && instruction . Operand . ToString ( ) . Contains ( "<Module>::String" ) && instructions [ i + 1 ] . IsLdcI4 ( ) && instructions [ i + 2 ] . OpCode == OpCodes . Callvirt && instructions [ i + 2 ] . Operand . ToString ( ) . Contains ( "Invoke" ) )
212+ {
213+ if ( this . _decryptField == null )
214+ {
215+ FieldDef fieldDef = ( FieldDef ) instruction . Operand ;
216+ this . InitDecryptor ( fieldDef ) ;
217+ }
218+ int idx = ( int ) instructions [ i + 1 ] . Operand ;
219+ instructions [ i ] . OpCode = OpCodes . Ldstr ;
220+ instructions [ i ] . Operand = this . GetString ( idx ) ;
221+ instructions [ i + 1 ] . OpCode = OpCodes . Nop ;
222+ instructions [ i + 2 ] . OpCode = OpCodes . Nop ;
223+ }
224+ }
225+ }
226+ }
227+ }
228+ }
229+
230+ private void InitDecryptor ( FieldDef fieldDef )
231+ {
232+ FieldInfo fieldInfo = this . assembly . Modules . FirstOrDefault < Module > ( ) . ResolveField ( fieldDef . MDToken . ToInt32 ( ) ) ;
233+ this . _decryptField = fieldInfo . GetValue ( null ) ;
234+ this . decryptMethod = this . _decryptField . GetType ( ) . GetMethod ( "Invoke" ) ;
235+ }
236+
237+ private string GetString ( int idx )
238+ {
239+ return ( string ) this . decryptMethod . Invoke ( this . _decryptField , new object [ ] { idx } ) ;
240+ }
241+ }
242+
243+ internal static class Memory
244+ {
245+ [ DllImport ( "kernel32.dll" , ExactSpelling = true , SetLastError = true ) ]
246+ private static extern bool VirtualProtect ( IntPtr lpAddress , IntPtr dwSize , uint flNewProtect , out uint lpflOldProtect ) ;
247+
248+ internal unsafe static void Hook ( MethodBase from , MethodBase to )
249+ {
250+ IntPtr address = Memory . GetAddress ( from ) ;
251+ IntPtr address2 = Memory . GetAddress ( to ) ;
252+ uint flNewProtect ;
253+ Memory . VirtualProtect ( address , ( IntPtr ) 5 , 64u , out flNewProtect ) ;
254+ if ( IntPtr . Size == 8 )
255+ {
256+ byte * ptr = ( byte * ) address . ToPointer ( ) ;
257+ * ptr = 73 ;
258+ ptr [ 1 ] = 187 ;
259+ * ( long * ) ( ptr + 2 ) = address2. ToInt64 ( ) ;
260+ ptr[ 10 ] = 65 ;
261+ ptr [ 11 ] = byte . MaxValue ;
262+ ptr [ 12 ] = 227 ;
263+ }
264+ else if ( IntPtr . Size == 4 )
265+ {
266+ byte * ptr2 = ( byte * ) address . ToPointer ( ) ;
267+ * ptr2 = 233 ;
268+ * ( long * ) ( ptr2 + 1 ) = ( long ) ( address2 . ToInt32 ( ) - address . ToInt32 ( ) - 5 ) ;
269+ ptr2[ 5 ] = 195 ;
270+ }
271+ uint num ;
272+ Memory . VirtualProtect ( address , ( IntPtr ) 5 , flNewProtect , out num ) ;
273+ }
274+
275+ public static IntPtr GetAddress ( MethodBase methodBase )
276+ {
277+ RuntimeHelpers . PrepareMethod ( methodBase . MethodHandle ) ;
278+ return methodBase . MethodHandle . GetFunctionPointer ( ) ;
279+ }
280+ }
281+
282+ internal class AssemblyWriter
283+ {
284+ private readonly string assemblyPath ;
285+
286+ internal ModuleDefMD moduleDef ;
287+ internal AssemblyWriter ( string assemblyPath )
288+ {
289+ this . assemblyPath = assemblyPath ;
290+
291+ AssemblyResolver assemblyResolver = new AssemblyResolver ( ) ;
292+ ModuleContext moduleContext = new ModuleContext ( assemblyResolver ) ;
293+ assemblyResolver . EnableTypeDefCache = true ;
294+ assemblyResolver . DefaultModuleContext = moduleContext ;
295+ moduleDef = ModuleDefMD . Load ( assemblyPath , moduleContext ) ;
296+ moduleDef . Context = moduleContext ;
297+ moduleDef . Context . AssemblyResolver . AddToCache ( moduleDef ) ;
298+ }
299+
300+ internal void WriteMethod ( MethodDef methodDef )
301+ {
302+ MethodDef executingMethod = Script . currentMethod ;
303+
304+ if ( executingMethod == null )
305+ {
306+ Console . WriteLine ( "[!] Failed to write " + methodDef ) ;
307+ return ;
308+ }
309+ Script . currentMethod = null ;
310+ executingMethod . FreeMethodBody ( ) ;
311+ executingMethod . Body = methodDef . Body ;
312+ }
313+
314+ internal void Save ( )
315+ {
316+ try
317+ {
318+ string text = Path . GetDirectoryName ( assemblyPath ) ;
319+
320+ if ( ! text . EndsWith ( "\\ " ) )
321+ {
322+ text += "\\ " ;
323+ }
324+
325+ string filename = text + Path . GetFileNameWithoutExtension ( assemblyPath ) + "_Unpacked" + Path . GetExtension ( assemblyPath ) ;
326+ ModuleWriterOptions options = new ModuleWriterOptions ( moduleDef ) ;
327+ options . Logger = DummyLogger . NoThrowInstance ;
328+ moduleDef . Write ( filename , options ) ;
329+ }
330+ catch ( Exception ex )
331+ {
332+ Console . WriteLine ( "[!] Exception :\n " + ex . Message ) ;
333+ }
334+ }
335+
336+ }
0 commit comments