1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Diagnostics ;
4+ using System . Linq ;
5+ using System . Reflection ;
6+ using System . Runtime . InteropServices ;
7+ using System . Text ;
8+ using static AntiCrack_DotNet . Structs ;
9+
10+ namespace AntiCrack_DotNet
11+ {
12+ internal sealed class AntiInjection
13+ {
14+
15+ #region WinApi
16+
17+ [ DllImport ( "kernelbase.dll" , SetLastError = true ) ]
18+ private static extern IntPtr GetModuleHandle ( string lib ) ;
19+
20+ [ DllImport ( "kernelbase.dll" , SetLastError = true ) ]
21+ private static extern IntPtr GetProcAddress ( IntPtr ModuleHandle , string Function ) ;
22+
23+ [ DllImport ( "kernelbase.dll" , SetLastError = true ) ]
24+ private static extern bool WriteProcessMemory ( SafeHandle hProcess , IntPtr BaseAddress , byte [ ] Buffer , uint size , int NumOfBytes ) ;
25+
26+ [ DllImport ( "kernelbase.dll" , SetLastError = true ) ]
27+ public static extern bool SetProcessMitigationPolicy ( int policy , ref Structs . PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY lpBuffer , int size ) ;
28+
29+ [ DllImport ( "ntdll.dll" , SetLastError = true ) ]
30+ private static extern uint NtOpenThread ( out IntPtr hThread , uint dwDesiredAccess , ref Structs . OBJECT_ATTRIBUTES ObjectAttributes , ref Structs . CLIENT_ID ClientID ) ;
31+
32+ [ DllImport ( "ntdll.dll" , SetLastError = true ) ]
33+ private static extern int NtQueryInformationThread ( IntPtr ThreadHandle , int ThreadInformationClass , ref IntPtr ThreadInformation , uint ThreadInformationLength , IntPtr ReturnLength ) ;
34+
35+ #endregion
36+
37+ /// <summary>
38+ /// Checks if there are any injected libraries in the current process.
39+ /// </summary>
40+ /// <returns>Returns true if an injected library is detected, otherwise false.</returns>
41+ public static bool IsInjectedLibrary ( )
42+ {
43+ bool IsMalicious = false ;
44+ string Windows = Environment . GetFolderPath ( Environment . SpecialFolder . Windows ) . ToLower ( ) ;
45+ string ProgramData = Windows . Replace ( @"\windows" , @"\programdata" ) ;
46+ foreach ( ProcessModule Module in Process . GetCurrentProcess ( ) . Modules )
47+ {
48+ string FileName = Module . FileName . ToLower ( ) ;
49+ if ( ! FileName . StartsWith ( Windows ) && ! FileName . StartsWith ( ProgramData ) )
50+ IsMalicious = true ;
51+
52+ if ( FileName . StartsWith ( Environment . CurrentDirectory . ToLower ( ) ) )
53+ IsMalicious = false ;
54+ }
55+ return IsMalicious ;
56+ }
57+
58+ /// <summary>
59+ /// Sets the DLL load policy to only allow Microsoft-signed DLLs to be loaded.
60+ /// </summary>
61+ /// <returns>Returns "Success" if the policy was set successfully, otherwise "Failed".</returns>
62+ public static string SetDllLoadPolicy ( )
63+ {
64+ Structs . PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY policy = new Structs . PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY
65+ {
66+ MicrosoftSignedOnly = 1
67+ } ;
68+ if ( SetProcessMitigationPolicy ( 8 , ref policy , Marshal . SizeOf ( policy ) ) )
69+ return "Success" ;
70+ return "Failed" ;
71+ }
72+
73+ /// <summary>
74+ /// Detects if an address is in range inside modules or not.
75+ /// </summary>
76+ /// <param name="Address">The address to check for.</param>
77+ /// <returns>Returns true if the address is in no module, otherwise false.</returns>
78+ private static bool IsAddressInRange ( IntPtr Address )
79+ {
80+ foreach ( ProcessModule module in Process . GetCurrentProcess ( ) . Modules )
81+ {
82+ IntPtr Base = module . BaseAddress ;
83+ IntPtr End = IntPtr . Add ( Base , module . ModuleMemorySize ) ;
84+ if ( Address . ToInt64 ( ) >= Base . ToInt64 ( ) && Address . ToInt64 ( ) < End . ToInt64 ( ) )
85+ {
86+ return true ;
87+ }
88+ }
89+ return false ;
90+ }
91+
92+ /// <summary>
93+ /// Detects if an address is in range inside modules or not.
94+ /// </summary>
95+ /// <param name="Syscall">Specifies whether we use syscalls for the check or not.</param>
96+ /// <param name="CheckModuleRange">Check if the threads start address is within modules range or not.</param>
97+ /// <returns>Returns true if no thread is injected, otherwise false.</returns>
98+ public static bool CheckInjectedThreads ( bool Syscall , bool CheckModuleRange )
99+ {
100+ uint MEM_IMAGE = 0x1000000 ;
101+ uint MEM_COMMIT = 0x1000 ;
102+ int ThreadQuerySetWin32StartAddress = 9 ;
103+ uint THREAD_QUERY_INFORMATION = 0x0040 ;
104+ int PID = Process . GetCurrentProcess ( ) . Id ;
105+ foreach ( ProcessThread thread in Process . GetCurrentProcess ( ) . Threads )
106+ {
107+ CLIENT_ID CI = new CLIENT_ID
108+ {
109+ UniqueProcess = ( IntPtr ) PID ,
110+ UniqueThread = ( IntPtr ) thread . Id
111+ } ;
112+
113+ OBJECT_ATTRIBUTES Attributes = new OBJECT_ATTRIBUTES
114+ {
115+ Length = Marshal . SizeOf ( typeof ( OBJECT_ATTRIBUTES ) ) ,
116+ RootDirectory = IntPtr . Zero ,
117+ ObjectName = IntPtr . Zero ,
118+ Attributes = 0 ,
119+ SecurityDescriptor = IntPtr . Zero ,
120+ SecurityQualityOfService = IntPtr . Zero
121+ } ;
122+
123+ IntPtr hThread = IntPtr . Zero ;
124+ uint Status = NtOpenThread ( out hThread , THREAD_QUERY_INFORMATION , ref Attributes , ref CI ) ;
125+ if ( Status == 0 || hThread != IntPtr . Zero )
126+ {
127+ IntPtr StartAddress = IntPtr . Zero ;
128+ int QueryStatus = Syscall ? Syscalls . SyscallNtQueryInformationThread ( hThread , ThreadQuerySetWin32StartAddress , ref StartAddress , ( uint ) IntPtr . Size , IntPtr . Zero ) : NtQueryInformationThread ( hThread , ThreadQuerySetWin32StartAddress , ref StartAddress , ( uint ) IntPtr . Size , IntPtr . Zero ) ;
129+ Utils . CloseHandle ( hThread ) ;
130+ if ( QueryStatus == 0 )
131+ {
132+ MEMORY_BASIC_INFORMATION MBI = new MEMORY_BASIC_INFORMATION ( ) ;
133+ if ( Utils . GetVirtualMemoryQuery ( Syscall , StartAddress , ref MBI , out _ ) )
134+ {
135+ if ( MBI . Type != MEM_IMAGE || MBI . State != MEM_COMMIT )
136+ {
137+ return true ;
138+ }
139+
140+ if ( CheckModuleRange )
141+ {
142+ if ( ! IsAddressInRange ( StartAddress ) )
143+ {
144+ return true ;
145+ }
146+ }
147+ }
148+ }
149+ }
150+ }
151+ return false ;
152+ }
153+
154+ /// <summary>
155+ /// Generate a random module name.
156+ /// </summary>
157+ /// <returns>the random module name.</returns>
158+ private static string GenerateRandomModule ( )
159+ {
160+ string Letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ;
161+ Random random = new Random ( ) ;
162+ int RandomLength = random . Next ( 6 , 32 ) ;
163+ char [ ] NewModule = new char [ RandomLength ] ;
164+ for ( int i = 0 ; i < RandomLength ; i ++ )
165+ {
166+ NewModule [ i ] = Letters [ random . Next ( Letters . Length ) ] ;
167+ }
168+ return new string ( NewModule ) ;
169+ }
170+
171+ /// <summary>
172+ /// Changes the module information at runtime to avoid modification.
173+ /// </summary>
174+ /// <param name="Module">The module name which we will change it's information, if left null, we get the main module of the process.</param>
175+ /// <param name="ChangeBaseAddress">An indicator to change the base address.</param>
176+ /// <param name="ChangeModuleName">An indicator to change the module name to something random.</param>
177+ /// <returns>Returns true if successfully changed the module info, otherwise false.</returns>
178+ public static bool ChangeModuleInfo ( string Module , bool ChangeBaseAddress , bool ChangeModuleName )
179+ {
180+ try
181+ {
182+ if ( ! ChangeBaseAddress && ! ChangeModuleName )
183+ return false ;
184+ string FinalModuleName = null ;
185+ if ( Module == null )
186+ {
187+ string MainModule = Process . GetCurrentProcess ( ) . MainModule . ModuleName ;
188+ if ( MainModule != null )
189+ FinalModuleName = MainModule ;
190+ }
191+ else
192+ {
193+ FinalModuleName = Module ;
194+ }
195+ string Fake = $ "{ GenerateRandomModule ( ) } .dll";
196+ PEB Peb = Utils . GetPEB ( ) ;
197+ _PEB_LDR_DATA Ldr = Marshal . PtrToStructure < _PEB_LDR_DATA > ( Peb . Ldr ) ;
198+ IntPtr f = Ldr . InMemoryOrderModuleList . Flink ;
199+ int count = 0 ;
200+ while ( count < 256 )
201+ {
202+ _LDR_DATA_TABLE_ENTRY TableEntry = Marshal . PtrToStructure < _LDR_DATA_TABLE_ENTRY > ( f ) ;
203+ string ModuleName = Marshal . PtrToStringUni ( TableEntry . FullDllName . Buffer ) ;
204+ if ( ModuleName != null && ModuleName == FinalModuleName )
205+ {
206+ if ( ChangeBaseAddress )
207+ {
208+ int RandomBaseAddress = new Random ( ) . Next ( 0x100000 / 0x1000 , 0x7FFF000 / 0x1000 ) * 0x1000 ;
209+ TableEntry . DllBase = ( IntPtr ) RandomBaseAddress ;
210+ }
211+
212+ if ( ChangeModuleName )
213+ {
214+ IntPtr FakeDllBuffer = Marshal . StringToHGlobalUni ( Fake ) ;
215+ TableEntry . FullDllName . Buffer = FakeDllBuffer ;
216+ TableEntry . FullDllName . Length = ( ushort ) ( Fake . Length * 2 ) ;
217+ TableEntry . FullDllName . MaximumLength = ( ushort ) ( ( Fake . Length + 1 ) * 2 ) ;
218+ }
219+ Marshal . StructureToPtr ( TableEntry , f , false ) ;
220+ return true ;
221+ }
222+ f = TableEntry . InLoadOrderLinks . Flink ;
223+ count ++ ;
224+ }
225+ }
226+ catch
227+ {
228+
229+ }
230+ return false ;
231+ }
232+
233+ /// <summary>
234+ /// Detects ImageBaseAddress modification which could indicate code injection in our process (process hollowing).
235+ /// </summary>
236+ /// <returns>Returns true if the ImageBaseAddress is suspicious, otherwise false.</returns>
237+ public static bool CheckForSuspiciousBaseAddress ( )
238+ {
239+ try
240+ {
241+ PEB Peb = Utils . GetPEB ( ) ;
242+ if ( Peb . ImageBaseAddress != Process . GetCurrentProcess ( ) . MainModule . BaseAddress )
243+ return true ;
244+ }
245+ catch
246+ {
247+
248+ }
249+ return false ;
250+ }
251+ }
252+ }
0 commit comments