private void PopulateConfigStruct() { string path = Path.GetDirectoryName(ModulePath); string name = Path.GetFileName(ModulePath); bool dll = true; if (Path.GetExtension(ModulePath) != ".dll" && Path.GetExtension(ModulePath) != ".DLL") { dll = false; } var MaLRet = ErcCore.MapAndLoad(name, path, out loadedImage, dll, true); var modPtr = ErcCore.ImageLoad(name, path); if (ModuleMachineType == MachineType.I386) { IMAGE_LOAD_CONFIG_DIRECTORY32 ImageConfigDir = new IMAGE_LOAD_CONFIG_DIRECTORY32(); var check = ErcCore.GetImageConfigInformation32(ref loadedImage, ref ImageConfigDir); } else if (ModuleMachineType == MachineType.x64) { IMAGE_LOAD_CONFIG_DIRECTORY64 ImageConfigDir = new IMAGE_LOAD_CONFIG_DIRECTORY64(); var check = ErcCore.GetImageConfigInformation64(ref loadedImage, ref ImageConfigDir); } }
/// <summary> /// Takes a string of characters and returns the location of the first character in a pattern created by Pattern_Create. /// </summary> /// <param name="pattern">The pattern to be searched for.</param> /// <param name="core">An ErcCore object</param> /// <param name="extended">(Optional) bool specifying whether the extended character set should be used</param> /// <returns>Returns an ErcResult int containing the offset of the supplied pattern within the generated pattern</returns> public static ErcResult <int> PatternOffset(string pattern, ErcCore core, bool extended = false) { string digits = "0123456789"; string patternFull; if (extended == true) { digits += ": ,.;+=-_!&()#@'({})[]%"; patternFull = File.ReadAllText(core.PatternExtendedPath); } else { patternFull = File.ReadAllText(core.PatternStandardPath); } ErcResult <int> result = new ErcResult <int>(core); if (pattern.Length < 3) { result.Error = new ERCException("User Input Error: Pattern length must be 3 characters or longer."); result.LogEvent(); return(result); } if (patternFull.Contains(pattern)) { result.ReturnValue = patternFull.IndexOf(pattern); return(result); } result.Error = new ERCException("Error: Pattern not found."); result.ReturnValue = -1; return(result); }
internal ErcResult <string> PopulateTEB() { ErcResult <string> returnString = new ErcResult <string>(ThreadCore); var retInt = ErcCore.ZwQueryInformationThread(ThreadHandle, 0, ref ThreadBasicInfo, Marshal.SizeOf(typeof(ThreadBasicInformation)), IntPtr.Zero); if (retInt != 0) { Console.WriteLine("NTSTATUS Error was thrown: " + retInt); returnString.Error = new ERCException("NTSTATUS Error was thrown: " + retInt); return(returnString); } byte[] tebBytes; int ret = 0; if (X64 == MachineType.x64) { tebBytes = new byte[0x16A0]; ErcCore.ReadProcessMemory(ThreadProcess.ProcessHandle, ThreadBasicInfo.TebBaseAdress, tebBytes, 0x16A0, out ret); } else { tebBytes = new byte[3888]; ErcCore.ReadProcessMemory(ThreadProcess.ProcessHandle, ThreadBasicInfo.TebBaseAdress, tebBytes, 3888, out ret); } if (ret == 0) { ERCException e = new ERCException("System error: An error occured when executing ReadProcessMemory\n Process Handle = 0x" + ThreadProcess.ProcessHandle.ToString("X") + " TEB Base Address = 0x" + ThreadBasicInfo.TebBaseAdress.ToString("X") + " Return value = " + ret); returnString.Error = e; return(returnString); } if (X64 == MachineType.x64) { PopulateTEBStruct64(tebBytes); } else { PopulateTEBStruct32(tebBytes); } var bSehChain = BuildSehChain(); if (bSehChain.Error != null) { returnString.Error = bSehChain.Error; return(returnString); } return(returnString); }
/// <summary> /// Compares a byte array with an area in memory of equal size. This method should be used in conjunction with the ByteArrayConstructor to identify /// bytes which can not be passed into a program without corrupting the input. /// </summary> /// <param name="info">The process to compare memory from</param> /// <param name="startAddress">The address at which to start the comparison</param> /// <param name="bytes">The byte array containing the bytes to be compared</param> /// <returns>Returns a Tuple containing a bool which is true if the comparison was identical and false if it was not, a byte array containing /// the bytes provided and a byte array containing the bytes read from process memory</returns> public static Tuple <bool, byte[], byte[]> ByteCompare(ProcessInfo info, IntPtr startAddress, byte[] bytes) { byte[] memoryBytes = new byte[bytes.Length]; ErcCore.ReadProcessMemory(info.ProcessHandle, startAddress, bytes, bytes.Length, out int bytesRead); for (int i = 0; i < bytes.Length; i++) { if (bytes[i] != memoryBytes[i]) { return(Tuple.Create(false, bytes, memoryBytes)); } } return(Tuple.Create(true, bytes, memoryBytes)); }
public HeapInfo(ProcessInfo info) { HeapProcess = info; HEAPLIST32 firstHeapList = new HEAPLIST32(); firstHeapList.dwSize = (IntPtr)Marshal.SizeOf(typeof(HEAPLIST32)); IntPtr Handle = ErcCore.CreateToolhelp32Snapshot(SnapshotFlags.HeapList, (uint)info.ProcessID); if ((int)Handle == -1) { throw new ERCException("CreateToolhelp32Snapshot returned an invalid handle value (-1)"); } if (ErcCore.Heap32ListFirst(Handle, ref firstHeapList)) { HeapLists.Add(firstHeapList); bool moreHeaps = false; do { HEAPLIST32 currentHeap = new HEAPLIST32(); currentHeap.dwSize = (IntPtr)Marshal.SizeOf(typeof(HEAPLIST32)); moreHeaps = ErcCore.Heap32ListNext(Handle, ref currentHeap); if (HeapEntries.Count == 0) { currentHeap = firstHeapList; } if (moreHeaps) { HeapLists.Add(currentHeap); HEAPENTRY32 heapentry32 = new HEAPENTRY32(); heapentry32.dwSize = (IntPtr)Marshal.SizeOf(typeof(HEAPENTRY32)); if (ErcCore.Heap32First(ref heapentry32, (uint)HeapProcess.ProcessID, currentHeap.th32HeapID)) { bool moreheapblocks = false; do { HeapEntries.Add(heapentry32); moreheapblocks = ErcCore.Heap32Next(ref heapentry32); }while (moreheapblocks); } } }while (moreHeaps); } else { throw new ERCException("Heap32ListFirst returned an invalid response. Error: " + Utilities.Win32Errors.GetLastWin32Error()); } }
/// <summary> /// Takes a string of characters and returns the location of the first character in a pattern created by Pattern_Create. /// </summary> /// <param name="pattern">The pattern to be searched for.</param> /// <param name="core">An ErcCore object</param> /// <param name="extended">(Optional) bool specifying whether the extended character set should be used</param> /// <returns>Returns an ErcResult int containing the offset of the supplied pattern within the generated pattern</returns> public static ErcResult <string> PatternOffset(string pattern, ErcCore core, bool extended = false) { //create string with reversed version of pattern to be searched for. char[] reversedChars = pattern.ToCharArray(); Array.Reverse(reversedChars); string reversed = new string(reversedChars); //Create pattern to search within. Either extended or normal. string digits = "0123456789"; string patternFull; if (extended == true) { digits += ": ,.;+=-_!&()#@'*^[]%$?"; patternFull = File.ReadAllText(core.PatternExtendedPath); } else { patternFull = File.ReadAllText(core.PatternStandardPath); } ErcResult <string> result = new ErcResult <string>(core); if (pattern.Length < 3) { result.Error = new ERCException("User Input Error: Pattern length must be 3 characters or longer."); result.LogEvent(); return(result); } if (patternFull.Contains(pattern)) { result.ReturnValue = "Value found at postiont " + patternFull.IndexOf(pattern).ToString() + " in pattern."; return(result); } else if (patternFull.Contains(reversed)) { result.ReturnValue = "Value found reversed at postiont " + patternFull.IndexOf(reversed).ToString() + " in pattern."; return(result); } result.Error = new ERCException("Error: Value not found."); result.ReturnValue = "Value not found in pattern."; return(result); }
internal ThreadInfo(ProcessThread thread, ErcCore core, ProcessInfo process) { ThreadID = thread.Id; ThreadCurrent = thread; ThreadCore = core; ThreadProcess = process; if (process.ProcessMachineType == MachineType.x64) { X64 = MachineType.x64; } else if (process.ProcessMachineType == MachineType.I386) { X64 = MachineType.I386; } try { ThreadHandle = ErcCore.OpenThread(ThreadAccess.All_ACCESS, false, (uint)thread.Id); if (ThreadHandle == null) { ThreadFailed = true; throw new ERCException(new Win32Exception(Marshal.GetLastWin32Error()).Message); } } catch (ERCException e) { ErcResult <Exception> exceptionThrower = new ErcResult <Exception>(ThreadCore) { Error = e }; exceptionThrower.LogEvent(); } var errorCheck = PopulateTEB(); //This needs to be revisited. if (errorCheck.Error != null && errorCheck.Error.Message != "Error: No SEH chain has been generated yet. An SEH chain will not be generated until a crash occurs.") { throw errorCheck.Error; } }
/// <summary> /// Searches for a string of bytes within a specific module. Takes a byte array to be searched for. /// </summary> /// <param name="searchBytes">A byte array to be searched for</param> /// <returns>Returns ERC_Result of pointers to the search term</returns> public ErcResult <List <IntPtr> > SearchModule(byte[] searchBytes) { ErcResult <List <IntPtr> > results = new ErcResult <List <IntPtr> >(ModuleCore); List <IntPtr> ptrs = new List <IntPtr>(); IntPtr baseAddress = ModuleBase; byte[] buffer = new byte[ModuleSize]; int bytesread = 0; ErcCore.ReadProcessMemory(ModuleProcess.Handle, ModuleBase, buffer, buffer.Length, out bytesread); List <int> positions = SearchBytePattern(searchBytes, buffer); for (int i = 0; i < positions.Count; i++) { ptrs.Add((IntPtr)(positions[i] + (long)ModuleBase)); } results.ReturnValue = ptrs; return(results); }
/// <summary> /// Compares a byte array with an area in memory of equal size. This method should be used in conjunction with the ByteArrayConstructor to identify /// bytes which can not be passed into a program without corrupting the input. /// </summary> /// <param name="info">The process to compare memory from</param> /// <param name="startAddress">The address at which to start the comparison</param> /// <param name="byteFilePath">The path to a file containing the bytes to be compared</param> /// <returns>Returns a Tuple containing a bool which is true if the comparison was identical and false if it was not, a byte array containing /// the bytes provided and a byte array containing the bytes read from process memory</returns> public static Tuple <bool, byte[], byte[]> ByteCompare(ProcessInfo info, IntPtr startAddress, string byteFilePath) { if (File.Exists(byteFilePath)) { byte[] bytes = File.ReadAllBytes(byteFilePath); byte[] memoryBytes = new byte[bytes.Length]; ErcCore.ReadProcessMemory(info.ProcessHandle, startAddress, bytes, bytes.Length, out int bytesRead); for (int i = 0; i < bytes.Length; i++) { if (bytes[i] != memoryBytes[i]) { return(Tuple.Create(false, bytes, memoryBytes)); } } return(Tuple.Create(true, bytes, memoryBytes)); } else { throw new FileNotFoundException(byteFilePath); } }
internal ThreadInfo(ProcessThread thread, ErcCore core, ProcessInfo process) { ThreadID = thread.Id; ThreadCurrent = thread; ThreadCore = core; ThreadProcess = process; if (process.ProcessMachineType == MachineType.x64) { X64 = MachineType.x64; } else if (process.ProcessMachineType == MachineType.I386) { X64 = MachineType.I386; } try { ThreadHandle = ErcCore.OpenThread(ThreadAccess.All_ACCESS, false, (uint)thread.Id); if (ThreadHandle == null) { ThreadFailed = true; throw new ERCException(new Win32Exception(Marshal.GetLastWin32Error()).Message); } } catch (ERCException e) { ErcResult <Exception> exceptionThrower = new ErcResult <Exception>(ThreadCore) { Error = e }; exceptionThrower.LogEvent(); } PopulateTEB(); }
/// <summary> /// Creates a string of non repeating characters. /// </summary> /// <param name="length">The length of the pattern to be created as integer</param> /// <param name="core">An ErcCore object</param> /// <param name="extended">(Optional) bool specifying whether the extended character set should be used</param> /// <returns>Returns an ErcResult string containing the generated pattern</returns> public static ErcResult <string> PatternCreate(int length, ErcCore core, bool extended = false) { string digits = "0123456789"; ErcResult <string> result = new ErcResult <string>(core); if (extended == true) { digits += ": ,.;+=-_!&()#@'*^[]%$?"; if (length > 66923) { result.Error = new ERCException("User input error: Pattern length must be less that 66923"); result.LogEvent(); return(result); } } else { if (length > 20277) { result.Error = new ERCException("User input error: Pattern length must be less that 20277. Add the extended flag to create larger strings."); result.LogEvent(); return(result); } } result.ReturnValue = ""; if (length < 1) { result.Error = new ERCException("User Input Error: Pattern length must be greate than 0."); result.LogEvent(); return(result); } for (int i = 0; i < uppercase.Length; i++) { for (int j = 0; j < lowercase.Length; j++) { for (int k = 0; k < digits.Length; k++) { char pos1 = uppercase[i]; char pos2 = lowercase[j]; char pos3 = digits[k]; if (result.ReturnValue.Length > length) { result.Error = new ERCException("Procedural Error: Pattern string has exceeded the length supplied"); result.ReturnValue = ""; return(result); } if (result.ReturnValue.Length == length) { return(result); } if (result.ReturnValue.Length < length - 2) { result.ReturnValue += pos1; result.ReturnValue += pos2; result.ReturnValue += pos3; if (result.ReturnValue.Length == length) { return(result); } } else if (result.ReturnValue.Length < length - 1) { result.ReturnValue += pos1; result.ReturnValue += pos2; if (result.ReturnValue.Length == length) { return(result); } } else if (result.ReturnValue.Length < length) { result.ReturnValue += pos1; if (result.ReturnValue.Length == length) { return(result); } } } } } result.Error = new ERCException("An unknown error has occured. Function exited incorrectly. Function: ERC.Pattern_Tools.Pattern_Create"); result.LogEvent(); return(result); }
internal ErcResult <List <Tuple <byte[], byte[]> > > BuildSehChain() { ErcResult <List <Tuple <byte[], byte[]> > > sehList = new ErcResult <List <Tuple <byte[], byte[]> > >(ThreadCore); sehList.ReturnValue = new List <Tuple <byte[], byte[]> >(); if (Teb.Equals(default(TEB))) { sehList.Error = new Exception("Error: TEB structure for this thread has not yet been populated. Call PopulateTEB first"); return(sehList); } if (Teb.CurrentSehFrame == IntPtr.Zero) { sehList.Error = new Exception("Error: No SEH chain has been generated yet. An SEH chain will not be generated until a crash occurs."); return(sehList); } byte[] sehEntry; byte[] sehFinal; int arraySize = 0; if (X64 == MachineType.x64) { arraySize = 8; sehEntry = new byte[arraySize]; sehFinal = new byte[arraySize]; sehEntry = BitConverter.GetBytes((long)Teb.CurrentSehFrame); } else { arraySize = 4; sehEntry = new byte[arraySize]; sehFinal = new byte[arraySize]; sehEntry = BitConverter.GetBytes((int)Teb.CurrentSehFrame); } for (int i = 0; i < sehFinal.Length; i++) { sehFinal[i] = 0xFF; } byte[] prevSEH = new byte[] { 0xFF }; string pattern_standard = File.ReadAllText(ThreadCore.PatternStandardPath); string pattern_extended = File.ReadAllText(ThreadCore.PatternExtendedPath); while (!sehEntry.SequenceEqual(sehFinal)) { byte[] reversedSehEntry = new byte[arraySize]; byte[] nSeh = new byte[arraySize]; byte[] sehHolder = new byte[arraySize * 2]; int ret = 0; if (X64 == MachineType.x64) { ret = ErcCore.ReadProcessMemory(ThreadProcess.ProcessHandle, (IntPtr)BitConverter.ToInt64(sehEntry, 0), sehHolder, arraySize * 2, out int retInt); Array.Copy(sehHolder, 0, sehEntry, 0, arraySize); Array.Copy(sehHolder, arraySize, nSeh, 0, arraySize); } else { ret = ErcCore.ReadProcessMemory(ThreadProcess.ProcessHandle, (IntPtr)BitConverter.ToInt32(sehEntry, 0), sehHolder, arraySize * 2, out int retInt); Array.Copy(sehHolder, 0, sehEntry, 0, arraySize); Array.Copy(sehHolder, arraySize, nSeh, 0, arraySize); } if (ret != 0 && ret != 1) { ERCException e = new ERCException("System error: An error occured when executing ReadProcessMemory\n Process Handle = 0x" + ThreadProcess.ProcessHandle.ToString("X") + " TEB Current Seh = 0x" + Teb.CurrentSehFrame.ToString("X") + " Return value = " + ret + Environment.NewLine + "Win32Exception: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); sehList.Error = e; sehList.LogEvent(); return(sehList); } Array.Reverse(nSeh); for (int i = 0; i < sehEntry.Length; i++) { reversedSehEntry[i] = sehEntry[i]; } Array.Reverse(reversedSehEntry, 0, reversedSehEntry.Length); if (prevSEH.SequenceEqual(reversedSehEntry)) { sehEntry = new byte[sehFinal.Length]; Array.Copy(sehFinal, 0, sehEntry, 0, sehFinal.Length); } else if (!sehEntry.SequenceEqual(sehFinal) && !sehList.ReturnValue.Any(e => e.Item1.SequenceEqual(reversedSehEntry))) { Tuple <byte[], byte[]> tuple = new Tuple <byte[], byte[]>(reversedSehEntry, nSeh); sehList.ReturnValue.Add(tuple); } if (pattern_standard.Contains(Encoding.Unicode.GetString(reversedSehEntry)) || pattern_extended.Contains(Encoding.Unicode.GetString(reversedSehEntry))) { sehEntry = new byte[sehFinal.Length]; Array.Copy(sehFinal, 0, sehEntry, 0, sehFinal.Length); } if (pattern_standard.Contains(Encoding.ASCII.GetString(reversedSehEntry)) || pattern_extended.Contains(Encoding.ASCII.GetString(reversedSehEntry))) { sehEntry = new byte[sehFinal.Length]; Array.Copy(sehFinal, 0, sehEntry, 0, sehFinal.Length); } if (pattern_standard.Contains(Encoding.UTF32.GetString(reversedSehEntry)) || pattern_extended.Contains(Encoding.UTF32.GetString(reversedSehEntry))) { sehEntry = new byte[sehFinal.Length]; Array.Copy(sehFinal, 0, sehEntry, 0, sehFinal.Length); } if (pattern_standard.Contains(Encoding.UTF7.GetString(reversedSehEntry)) || pattern_extended.Contains(Encoding.UTF7.GetString(reversedSehEntry))) { sehEntry = new byte[sehFinal.Length]; Array.Copy(sehFinal, 0, sehEntry, 0, sehFinal.Length); } if (pattern_standard.Contains(Encoding.UTF8.GetString(reversedSehEntry)) || pattern_extended.Contains(Encoding.UTF8.GetString(reversedSehEntry))) { sehEntry = new byte[sehFinal.Length]; Array.Copy(sehFinal, 0, sehEntry, 0, sehFinal.Length); } prevSEH = new byte[reversedSehEntry.Length]; Array.Copy(reversedSehEntry, 0, prevSEH, 0, reversedSehEntry.Length); } SehChain = new List <Tuple <byte[], byte[]> >(sehList.ReturnValue); return(sehList); }
/// <summary> /// Gets the register values of a thread and populates the CONTEXT structs. Should only be used on a suspended thread, results on an active thread are unreliable. /// </summary> /// <returns>Returns an ErcResult, the return value can be ignored, the object should only be checked for error values</returns> public ErcResult <string> Get_Context() { ErcResult <string> result = new ErcResult <string>(ThreadCore); if (X64 == MachineType.x64) { Context64 = new CONTEXT64(); Context64.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL; try { bool returnVar = ErcCore.GetThreadContext64(ThreadHandle, ref Context64); if (returnVar == false) { throw new ERCException("Win32 Exception encountered when attempting to get thread context: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); } } catch (ERCException e) { result.Error = e; result.LogEvent(); return(result); } catch (Exception e) { result.Error = e; result.LogEvent(e); } } else if (Environment.Is64BitOperatingSystem == true && X64 != MachineType.x64) { Context32 = new CONTEXT32(); Context32.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL; try { bool returnVar = ErcCore.Wow64GetThreadContext(ThreadHandle, ref Context32); if (returnVar == false) { throw new ERCException("Win32 Exception encountered when attempting to get thread context: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); } } catch (ERCException e) { result.Error = e; result.LogEvent(); return(result); } catch (Exception e) { result.Error = e; result.LogEvent(e); } } else { Context32 = new CONTEXT32(); Context32.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL; try { bool returnVar = ErcCore.GetThreadContext32(ThreadHandle, ref Context32); if (returnVar == false) { throw new ERCException("Win32 Exception encountered when attempting to get thread context: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); } } catch (ERCException e) { result.Error = e; result.LogEvent(); return(result); } catch (Exception e) { result.Error = e; result.LogEvent(e); } } return(result); }
private unsafe void PopulateHeaderStructs(FileStream fin) { byte[] Data = new byte[4096]; int iRead = fin.Read(Data, 0, 4096); fin.Flush(); fin.Close(); fixed(byte *p_Data = Data) { IMAGE_DOS_HEADER * idh = (IMAGE_DOS_HEADER *)p_Data; IMAGE_NT_HEADERS32 *inhs = (IMAGE_NT_HEADERS32 *)(idh->nt_head_ptr + p_Data); ModuleMachineType = (MachineType)inhs->FileHeader.Machine; if (ModuleMachineType == MachineType.I386) { IMAGE_NT_HEADERS32 *inhs32 = (IMAGE_NT_HEADERS32 *)(idh->nt_head_ptr + p_Data); ImageFileHeader = inhs32->FileHeader; ModuleMachineType = (MachineType)inhs32->FileHeader.Machine; ImageOptionalHeader32 = inhs32->OptionalHeader; ModuleImageBase = (IntPtr)inhs32->OptionalHeader.ImageBase; ImageNTHeaders32 = new IMAGE_NT_HEADERS32 { Signature = inhs32->Signature, FileHeader = inhs32->FileHeader, OptionalHeader = inhs32->OptionalHeader }; byte[] bytes = new byte[256]; var ret = ErcCore.ReadProcessMemory(ModuleProcess.Handle, (IntPtr)((uint)ModuleBase + ImageOptionalHeader32.LoadConfigTable.VirtualAddress), bytes, 256, out int BytesRead); if (BitConverter.ToUInt32(bytes, 58) > 0 || BitConverter.ToUInt32(bytes, 62) > 0) { ModuleSafeSEH = true; } } else if (ModuleMachineType == MachineType.x64) { IMAGE_NT_HEADERS64 *inhs64 = (IMAGE_NT_HEADERS64 *)(idh->nt_head_ptr + p_Data); ImageFileHeader = inhs64->FileHeader; ImageOptionalHeader64 = inhs64->OptionalHeader; ModuleImageBase = (IntPtr)inhs64->OptionalHeader.ImageBase; ImageNTHeaders64 = new IMAGE_NT_HEADERS64 { Signature = inhs64->Signature, FileHeader = inhs64->FileHeader, OptionalHeader = inhs64->OptionalHeader }; byte[] bytes = new byte[256]; var ret = ErcCore.ReadProcessMemory(ModuleProcess.Handle, (IntPtr)((long)ModuleBase + (long)ImageOptionalHeader64.LoadConfigTable.VirtualAddress), bytes, 256, out int BytesRead); if (BitConverter.ToUInt64(bytes, 88) > 0 || BitConverter.ToUInt64(bytes, 96) > 0) { ModuleSafeSEH = true; } } else { ModuleFailed = true; } } }
/// <summary> /// Constructor for the ModuleInfo object. Takes (string)modules filepath (IntPtr)module handle (Process)Process from which the module is loaded /// </summary> /// <param name="module">Filepath of the module</param> /// <param name="ptr">Handle to the module</param> /// <param name="process">Process where the module is loaded</param> /// <param name="core">An ErcCore object</param> internal unsafe ModuleInfo(string module, IntPtr ptr, Process process, ErcCore core) { try { ModuleCore = core; ModuleProcess = process; ModuleName = FileVersionInfo.GetVersionInfo(module).InternalName; ModulePath = FileVersionInfo.GetVersionInfo(module).FileName; ModuleBase = ptr; FileInfo fileInfo = new FileInfo(ModulePath); FileStream file = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read); PopulateHeaderStructs(file); if (!string.IsNullOrEmpty(FileVersionInfo.GetVersionInfo(module).FileVersion)) { ModuleVersion = FileVersionInfo.GetVersionInfo(module).FileVersion.Split(' ')[0]; } else { ModuleVersion = ""; } ModuleProduct = FileVersionInfo.GetVersionInfo(module).ProductName; if (ModuleMachineType == MachineType.I386) { ModuleEntry = (IntPtr)ImageOptionalHeader32.AddressOfEntryPoint; ModuleSize = (int)ImageOptionalHeader32.SizeOfImage; ModuleImageBase = (IntPtr)ImageOptionalHeader32.ImageBase; byte[] dllByte = BitConverter.GetBytes(ImageOptionalHeader32.DllCharacteristics); BitArray bits = new BitArray(dllByte); for (int i = 0; i < bits.Count; i++) { if (bits[i] == true && i == 6) { ModuleASLR = true; } else { ModuleASLR = false; } if (bits[i] == true && i == 8) { ModuleNXCompat = true; } else { ModuleNXCompat = false; } } if (ModuleMachineType == MachineType.I386) { PopulateConfigStruct(); if (ImageConfigDir32.SEHandlerCount == 0 && ImageConfigDir32.SEHandlerTable == 0) { ModuleSafeSEH = false; } else { ModuleSafeSEH = true; } } else { ModuleSafeSEH = true; } } else if (ModuleMachineType == MachineType.x64) { ModuleEntry = (IntPtr)ImageOptionalHeader64.AddressOfEntryPoint; ModuleSize = (int)ImageOptionalHeader64.SizeOfImage; ModuleImageBase = (IntPtr)ImageOptionalHeader64.ImageBase; byte[] dllByte = BitConverter.GetBytes(ImageOptionalHeader64.DllCharacteristics); BitArray bits = new BitArray(dllByte); for (int i = 0; i < bits.Count; i++) { if (bits[i] == true && i == 6) { ModuleASLR = true; } else if (bits[i] == false && i == 6) { ModuleASLR = false; } if (bits[i] == true && i == 8) { ModuleNXCompat = true; } else if (bits[i] == false && i == 8) { ModuleNXCompat = false; } } PopulateConfigStruct(); if (ImageConfigDir64.SEHandlerCount == 0 && ImageConfigDir64.SEHandlerTable == 0) { ModuleSafeSEH = false; } else { ModuleSafeSEH = true; } } else { ModuleFailed = true; throw new ERCException("Unsupported machine type: " + ModuleMachineType.ToString()); } if (ModuleProduct == "Microsoft® Windows® Operating System") { ModuleOsDll = true; } else { ModuleOsDll = false; } if (ModuleImageBase != ptr) { ModuleRebase = true; } else { ModuleRebase = false; } } catch (Exception e) { ErcResult <Exception> ExceptionLogger = new ErcResult <Exception>(ModuleCore); ExceptionLogger.Error = e; ExceptionLogger.LogEvent(); ModuleFailed = true; } }
/// <summary> /// Constructor for the ModuleInfo object. Takes (string)modules filepath (IntPtr)module handle (Process)Process from which the module is loaded /// </summary> /// <param name="module">Filepath of the module</param> /// <param name="ptr">Handle to the module</param> /// <param name="process">Process where the module is loaded</param> /// <param name="core">An ErcCore object</param> internal unsafe ModuleInfo(string module, IntPtr ptr, Process process, ErcCore core) { try { ModuleCore = core; ModuleProcess = process; ModuleName = FileVersionInfo.GetVersionInfo(module).InternalName; ModulePath = FileVersionInfo.GetVersionInfo(module).FileName; ModuleBase = ptr; FileInfo fileInfo = new FileInfo(ModulePath); FileStream file = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read); PopulateHeaderStructs(file); if (!string.IsNullOrEmpty(FileVersionInfo.GetVersionInfo(module).FileVersion)) { ModuleVersion = FileVersionInfo.GetVersionInfo(module).FileVersion.Split(' ')[0]; } else { ModuleVersion = ""; } ModuleProduct = FileVersionInfo.GetVersionInfo(module).ProductName; if (ModuleMachineType == MachineType.I386) { ModuleEntry = (IntPtr)ImageOptionalHeader32.AddressOfEntryPoint; ModuleSize = (int)ImageOptionalHeader32.SizeOfImage; ModuleImageBase = (IntPtr)ImageOptionalHeader32.ImageBase; byte[] dllByte = BitConverter.GetBytes(ImageOptionalHeader32.DllCharacteristics); BitArray bits = new BitArray(dllByte); for (int i = 0; i < bits.Count; i++) { if (bits[i] == true && i == 6) { ModuleASLR = true; } else { ModuleASLR = false; } if (bits[i] == true && i == 8) { ModuleNXCompat = true; } else { ModuleNXCompat = false; } } if (ModuleMachineType == MachineType.I386) { PopulateConfigStruct(); if (ImageConfigDir32.SEHandlerCount == 0 && ImageConfigDir32.SEHandlerTable == 0) { ModuleSafeSEH = false; } else { ModuleSafeSEH = true; } } else { ModuleSafeSEH = true; } } else if (ModuleMachineType == MachineType.x64) { ModuleEntry = (IntPtr)ImageOptionalHeader64.AddressOfEntryPoint; ModuleSize = (int)ImageOptionalHeader64.SizeOfImage; ModuleImageBase = (IntPtr)ImageOptionalHeader64.ImageBase; byte[] dllByte = BitConverter.GetBytes(ImageOptionalHeader64.DllCharacteristics); BitArray bits = new BitArray(dllByte); for (int i = 0; i < bits.Count; i++) { if (bits[i] == true && i == 6) { ModuleASLR = true; } else if (bits[i] == false && i == 6) { ModuleASLR = false; } if (bits[i] == true && i == 8) { ModuleNXCompat = true; } else if (bits[i] == false && i == 8) { ModuleNXCompat = false; } } PopulateConfigStruct(); if (ImageConfigDir64.SEHandlerCount == 0 && ImageConfigDir64.SEHandlerTable == 0) { ModuleSafeSEH = false; } else { ModuleSafeSEH = true; } } else { ModuleFailed = true; throw new ERCException("Unsupported machine type: " + ModuleMachineType.ToString()); } if (ModuleProduct == "Microsoft® Windows® Operating System") { ModuleOsDll = true; } else { ModuleOsDll = false; } if (ModuleImageBase != ptr) { ModuleRebase = true; } else { ModuleRebase = false; } long MaxAddress = 0x7fffffff; long address = (long)ModuleBase; if (!ProcessInfo.Is64Bit(process)) { List <ERC.Structures.MEMORY_BASIC_INFORMATION32> ProcessMemoryBasicInfo32 = new List <ERC.Structures.MEMORY_BASIC_INFORMATION32>(); long oldAddress = 0; do { ERC.Structures.MEMORY_BASIC_INFORMATION32 m; int result = ErcCore.VirtualQueryEx32(ModuleProcess.Handle, (IntPtr)address, out m, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION32))); if (address == (long)m.BaseAddress + (long)m.RegionSize) { break; } address = (long)m.BaseAddress + (long)m.RegionSize; if (oldAddress > address) { address = long.MaxValue; } oldAddress = address; ModuleProtection = m.AllocationProtect; } while (address <= MaxAddress); } else { List <ERC.Structures.MEMORY_BASIC_INFORMATION64> ProcessMemoryBasicInfo64 = new List <ERC.Structures.MEMORY_BASIC_INFORMATION64>(); long oldAddress = 0; do { ERC.Structures.MEMORY_BASIC_INFORMATION64 m; int result = ErcCore.VirtualQueryEx64(ModuleProcess.Handle, (IntPtr)address, out m, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION64))); if (address == (long)m.BaseAddress + (long)m.RegionSize) { break; } address = (long)m.BaseAddress + (long)m.RegionSize; if (oldAddress > address) { address = long.MaxValue; } oldAddress = address; ModuleProtection = m.AllocationProtect; } while (address <= MaxAddress); } } catch (Exception e) { ErcResult <Exception> ExceptionLogger = new ErcResult <Exception>(ModuleCore); ExceptionLogger.Error = e; ExceptionLogger.LogEvent(); ModuleFailed = true; } }
/// <summary> /// Takes a string of characters and returns the location of the first character in a pattern created by Pattern_Create. /// </summary> /// <param name="pattern">The pattern to be searched for.</param> /// <param name="core">An ErcCore object</param> /// <param name="extended">(Optional) bool specifying whether the extended character set should be used</param> /// <returns>Returns an ErcResult int containing the offset of the supplied pattern within the generated pattern</returns> public static ErcResult <string> PatternOffset(string pattern, ErcCore core, bool extended = false) { //create string with reversed version of pattern to be searched for. char[] reversedChars = pattern.ToCharArray(); Array.Reverse(reversedChars); string reversed = new string(reversedChars); //Create pattern to search within. Either extended or normal. string digits = "0123456789"; string patternFull; if (extended == true) { digits += ": ,.;+=-_!&()#@'*^[]%$?"; patternFull = File.ReadAllText(core.PatternExtendedPath); } else { patternFull = File.ReadAllText(core.PatternStandardPath); } ErcResult <string> result = new ErcResult <string>(core); if (pattern.Length < 3) { result.Error = new ERCException("User Input Error: Pattern length must be 3 characters or longer."); result.LogEvent(); return(result); } if (patternFull.Contains(pattern)) { result.ReturnValue = "Value found at postiont " + patternFull.IndexOf(pattern).ToString() + " in pattern."; return(result); } else if (patternFull.Contains(reversed)) { result.ReturnValue = "Value found reversed at postiont " + patternFull.IndexOf(reversed).ToString() + " in pattern."; return(result); } bool validHexString = true; foreach (char c in pattern) { if ((c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F')) { validHexString = false; } } if (validHexString == true) { byte[] patternBytes = ERC.Utilities.Convert.HexToBytes(pattern); byte[] patternBytesReversed = ERC.Utilities.Convert.HexToBytes(reversed); byte[] patternFullBytes = Encoding.ASCII.GetBytes(patternFull); string hexString = BitConverter.ToString(patternBytes).Replace("-", ""); string hexStringReversed = BitConverter.ToString(patternBytesReversed).Replace("-", ""); string hexPatternFull = BitConverter.ToString(patternFullBytes).Replace("-", ""); if (hexPatternFull.Contains(hexString)) { result.ReturnValue = "Value found at postiont " + (hexPatternFull.IndexOf(hexString) / 2).ToString() + " in pattern."; return(result); } else if (hexPatternFull.Contains(hexStringReversed)) { result.ReturnValue = "Value found reversed at postiont " + (hexPatternFull.IndexOf(hexStringReversed) / 2).ToString() + " in pattern."; return(result); } } result.Error = new ERCException("Error: Value not found."); result.ReturnValue = "Value not found in pattern."; return(result); }