internal VirtualAllocSubRegion(MEMORY_BASIC_INFORMATION64 info, bool is32bit, ColorString detail) : base(new Address(info.BaseAddress, is32bit), info.RegionSize, new ColorString($"MEM_{info.State} PAGE_{(info.Protect == 0 ? PAGE.NOACCESS : info.Protect)} ").Append(detail)) { State = info.State; Protect = info.Protect; }
public UIntPtr VirtualQueryEx(IntPtr hProcess, UIntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer) { UIntPtr retVal; // TODO: Need to change this to only check once. if (mProc.Is64Bit || IntPtr.Size == 8) { // 64 bit MEMORY_BASIC_INFORMATION64 tmp64 = new MEMORY_BASIC_INFORMATION64(); retVal = Native_VirtualQueryEx(hProcess, lpAddress, out tmp64, new UIntPtr((uint)Marshal.SizeOf(tmp64))); lpBuffer.BaseAddress = tmp64.BaseAddress; lpBuffer.AllocationBase = tmp64.AllocationBase; lpBuffer.AllocationProtect = tmp64.AllocationProtect; lpBuffer.RegionSize = (long)tmp64.RegionSize; lpBuffer.State = tmp64.State; lpBuffer.Protect = tmp64.Protect; lpBuffer.Type = tmp64.Type; return(retVal); } MEMORY_BASIC_INFORMATION32 tmp32 = new MEMORY_BASIC_INFORMATION32(); retVal = Native_VirtualQueryEx(hProcess, lpAddress, out tmp32, new UIntPtr((uint)Marshal.SizeOf(tmp32))); lpBuffer.BaseAddress = tmp32.BaseAddress; lpBuffer.AllocationBase = tmp32.AllocationBase; lpBuffer.AllocationProtect = tmp32.AllocationProtect; lpBuffer.RegionSize = tmp32.RegionSize; lpBuffer.State = tmp32.State; lpBuffer.Protect = tmp32.Protect; lpBuffer.Type = tmp32.Type; return(retVal); }
public byte[] GetByteArrayAt(long offset, int size, bool verify = false) { byte[] returnValue = new byte[size]; if (verify) { MEMORY_BASIC_INFORMATION64 memBasicInfo = new MEMORY_BASIC_INFORMATION64(); VirtualQueryEx(ProcessHandle, new IntPtr(offset), out memBasicInfo, new IntPtr(48)); bool hasAnyRead = memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_READONLY) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_READWRITE) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_EXECUTE_READ) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_EXECUTE_READWRITE) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_WRITECOPY); // WRITECOPY also works? if (!(hasAnyRead && memBasicInfo.State.HasFlag(MemoryFlags.MEM_COMMIT))) { return(returnValue); } } IntPtr bytesRead = IntPtr.Zero; if (!ReadProcessMemory(ProcessHandle, offset, returnValue, size, out bytesRead)) { int win32Error = Marshal.GetLastWin32Error(); throw new Win32Exception(win32Error, ((Win32Error)win32Error).ToString()); } return(returnValue); }
public IEnumerable <MEMORY_BASIC_INFORMATION64> MemoryRegions() { // getting minimum & maximum address SYSTEM_INFO sys_info = new SYSTEM_INFO(); GetSystemInfo(out sys_info); IntPtr proc_min_address = sys_info.minimumApplicationAddress; IntPtr proc_max_address = sys_info.maximumApplicationAddress; // saving the values as long ints so I won't have to do a lot of casts later ulong proc_min_address_l = (ulong)proc_min_address; ulong proc_max_address_l = (ulong)proc_max_address; MEMORY_BASIC_INFORMATION64 mem_basic_info = new MEMORY_BASIC_INFORMATION64(); ulong current = proc_min_address_l; while (current < proc_max_address_l) { var informationSize = VirtualQueryEx(processHandle, (IntPtr)current, out mem_basic_info, (uint)Marshal.SizeOf(mem_basic_info)); if (informationSize == 0) { throw new Win32Exception(); } if (mem_basic_info.RegionSize < ChunkSize) { yield return(mem_basic_info); } else { Int64 remaining = mem_basic_info.RegionSize; UInt64 currentBase = unchecked ((UInt64)(Int64)mem_basic_info.BaseAddress); while (remaining >= ChunkSize) { MEMORY_BASIC_INFORMATION64 chunk = mem_basic_info; chunk.BaseAddress = (IntPtr)(long)currentBase; chunk.RegionSize = ChunkSize; yield return(chunk); remaining -= ChunkSize; currentBase = checked (currentBase + ChunkSize); } if (remaining > 0) { MEMORY_BASIC_INFORMATION64 chunk = mem_basic_info; chunk.BaseAddress = (IntPtr)(long)currentBase; chunk.RegionSize = ChunkSize; yield return(chunk); } } // move to the next memory chunk current += (ulong)mem_basic_info.RegionSize; } }
public static MEMORY_BASIC_INFORMATION64 GetMemInfo64(IntPtr ProcessHandle, IntPtr MinAddress) { var MemInfo = new MEMORY_BASIC_INFORMATION64(); int QueryResult = VirtualQueryEx(ProcessHandle, MinAddress, out MemInfo, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION64))); if (QueryResult == 0) { Debug.WriteLine("Error on VirtualQueryEx, returned 0!"); } return(MemInfo); }
internal int QueryVirtual(ulong addr, out MEMORY_BASIC_INFORMATION64 mem) { if (_spaces2 == null) { mem = new MEMORY_BASIC_INFORMATION64(); return(-1); } SetClientInstance(); return(_spaces2.QueryVirtual(addr, out mem)); }
private static MEMORY_BASIC_INFORMATION64 MapMemInfo(MEMORY_BASIC_INFORMATION32 memInfo) { MEMORY_BASIC_INFORMATION64 result = new MEMORY_BASIC_INFORMATION64(); result.AllocationBase = (ulong)memInfo.AllocationBase; result.AllocationProtect = (uint)memInfo.AllocationProtect; result.BaseAddress = (ulong)memInfo.BaseAddress; result.Protect = (uint)memInfo.Protect; result.RegionSize = (ulong)memInfo.RegionSize; result.State = (uint)memInfo.State; result.Type = (uint)memInfo.Type; return(result); }
/// <summary> /// Search the system's memory space for memory allocated to a target process and retrieve its sections via ReadProcessMemory /// </summary> /// <param name="hProcess"></param> /// <returns>A byte[] containing process's accessible memory</returns> static byte[] GetProcessMemoryBytes(IntPtr hProcess) { // Get lowest and highest addresses where memory can be allocated for user-mode applications SYSTEM_INFO systemInfo; GetSystemInfo(out systemInfo); IntPtr minimumAddress = systemInfo.minimumApplicationAddress; IntPtr maximumAddress = systemInfo.maximumApplicationAddress; MEMORY_BASIC_INFORMATION64 memBasicInfo = new MEMORY_BASIC_INFORMATION64(); int bytesRead = 0; // Initialise MemoryStream to store all found chunks of memory MemoryStream processMemory = new MemoryStream(); // Iterate over all addressable memory searching for memory blocks belonging to the target process while (minimumAddress.ToInt64() < maximumAddress.ToInt64()) { // Check for memory belonging to target process VirtualQueryEx(hProcess, minimumAddress, out memBasicInfo, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION64))); /* Check for sections of memory that are RWX or RW. Remove protection checks to dump all committed pages. * Shouldn't have access issues if running as admin and handle to process was obtained using ProcessAccessFlags.All. * Removing protection checks will significantly increase size of memory stream. */ if ((memBasicInfo.Protect == MemoryBasicInformationProtection.PAGE_READWRITE || memBasicInfo.Protect == MemoryBasicInformationProtection.PAGE_EXECUTE_READWRITE) && memBasicInfo.State == MemoryBasicInformationState.MEM_COMMIT) { // Write chunk of memory to buffer byte[] buffer = new byte[(int)memBasicInfo.RegionSize]; ReadProcessMemory(hProcess, (IntPtr)memBasicInfo.BaseAddress, buffer, (int)memBasicInfo.RegionSize, ref bytesRead); // Append chunk of memory to MemoryStream processMemory.Write(buffer, 0, buffer.Length); } // Move to the next section of memory try { minimumAddress = new IntPtr(minimumAddress.ToInt64() + (Int64)memBasicInfo.RegionSize); } catch (OverflowException) { break; } } return(processMemory.ToArray()); }
public int SetByteArrayAt(long offset, byte[] data) { MEMORY_BASIC_INFORMATION64 memBasicInfo = new MEMORY_BASIC_INFORMATION64(); IntPtr bytesWritten = IntPtr.Zero; VirtualQueryEx(ProcessHandle, new IntPtr(offset), out memBasicInfo, new IntPtr(48)); bool hasAnyRead = memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_READONLY) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_READWRITE) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_EXECUTE_READ) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_EXECUTE_READWRITE); if (hasAnyRead && memBasicInfo.State.HasFlag(MemoryFlags.MEM_COMMIT)) { if (!WriteProcessMemory(ProcessHandle, offset, data, data.Length, out bytesWritten)) { int win32Error = Marshal.GetLastWin32Error(); throw new Win32Exception(win32Error, ((Win32Error)win32Error).ToString()); } } return(bytesWritten.ToInt32()); }
public bool VirtualQuery(ulong addr, out VirtualQueryData vq) { _CheckClosed(); using (new DbgEngContextSaver(m_umd, m_target.Context)) { vq = new VirtualQueryData(); try { MEMORY_BASIC_INFORMATION64 mem = m_umd.QueryVirtual(addr); vq.BaseAddress = mem.BaseAddress; vq.Size = mem.RegionSize; return(true); } catch (DbgProviderException dpe) { LogManager.Trace("DbgShellDebugClientDataReader.VirtualQuery: ignoring \"{0}\".", Util.GetExceptionMessages(dpe)); return(false); } } } // end VirtualQuery()
private string GetMemoryProtectFlags(IntPtr offset) { try { System.Text.StringBuilder sb = new System.Text.StringBuilder(); #if x64 MEMORY_BASIC_INFORMATION64 memBasicInfo = new MEMORY_BASIC_INFORMATION64(); VirtualQueryEx(ProcessHandle, offset, out memBasicInfo, memoryBasicInfoSize); sb.AppendLine("[MEMORY_BASIC_INFORMATION64]"); sb.AppendFormat("BaseAddress: {0}\r\n", memBasicInfo.BaseAddress); sb.AppendFormat("AllocationBase: {0}\r\n", memBasicInfo.AllocationBase); sb.AppendFormat("AllocationProtect: {0}\r\n", memBasicInfo.AllocationProtect); sb.AppendFormat("__alignment1: {0}\r\n", memBasicInfo.__alignment1); sb.AppendFormat("RegionSize: {0}\r\n", memBasicInfo.RegionSize); sb.AppendFormat("State: {0}\r\n", memBasicInfo.State); sb.AppendFormat("Protect: {0}\r\n", memBasicInfo.Protect); sb.AppendFormat("Type: {0}\r\n", memBasicInfo.Type); sb.AppendFormat("__alignment2: {0}\r\n", memBasicInfo.__alignment2); #else MEMORY_BASIC_INFORMATION32 memBasicInfo = new MEMORY_BASIC_INFORMATION32(); VirtualQueryEx(ProcessHandle, offset, out memBasicInfo, memoryBasicInfoSize); sb.AppendLine("[MEMORY_BASIC_INFORMATION32]"); sb.AppendFormat("BaseAddress: {0}\r\n", memBasicInfo.BaseAddress); sb.AppendFormat("AllocationBase: {0}\r\n", memBasicInfo.AllocationBase); sb.AppendFormat("AllocationProtect: {0}\r\n", memBasicInfo.AllocationProtect); sb.AppendFormat("RegionSize: {0}\r\n", memBasicInfo.RegionSize); sb.AppendFormat("State: {0}\r\n", memBasicInfo.State); sb.AppendFormat("Protect: {0}\r\n", memBasicInfo.Protect); sb.AppendFormat("Type: {0}\r\n", memBasicInfo.Type); #endif return(sb.ToString()); } catch (Exception ex) { return(string.Format("[GetMemoryProtectFlags EXCEPTION: {0}]", ex.ToString())); } }
public Task <HashSet <long> > ScanMemoryAsync(byte[] searchValue, CancellationToken cancelToken) { return(Task.Factory.StartNew(() => { HashSet <long> returnValue = new HashSet <long>(); long procMinAddress = sysInfo.minimumApplicationAddress.ToInt64(); long procMaxAddress = sysInfo.maximumApplicationAddress.ToInt64(); MEMORY_BASIC_INFORMATION64 memBasicInfo = new MEMORY_BASIC_INFORMATION64(); IntPtr bytesRead = IntPtr.Zero; byte[] buffer = null; while (procMinAddress < procMaxAddress) { VirtualQueryEx(ProcessHandle, new IntPtr(procMinAddress), out memBasicInfo, new IntPtr(48)); bool hasAnyRead = memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_READONLY) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_READWRITE) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_EXECUTE_READ) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_EXECUTE_READWRITE); if (hasAnyRead && memBasicInfo.State.HasFlag(MemoryFlags.MEM_COMMIT)) { buffer = new byte[memBasicInfo.RegionSize.ToInt64()]; ReadProcessMemory(ProcessHandle, memBasicInfo.BaseAddress.ToInt64(), buffer, (int)memBasicInfo.RegionSize, out bytesRead); foreach (int offset in FindIndexesOf(buffer, 0, searchValue)) { returnValue.Add(memBasicInfo.BaseAddress.ToInt64() + (long)offset); } buffer = null; GC.Collect(); } procMinAddress += memBasicInfo.RegionSize.ToInt64(); } return returnValue; }, cancelToken, taskOpts, taskSched)); }
public static UIntPtr VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, bool x64) { UIntPtr retVal; if (x64) { // 64 bit var tmp64 = new MEMORY_BASIC_INFORMATION64(); retVal = Native_VirtualQueryEx(hProcess, lpAddress, out tmp64, new UIntPtr((uint)Marshal.SizeOf(tmp64))); lpBuffer.BaseAddress = tmp64.BaseAddress; lpBuffer.AllocationBase = tmp64.AllocationBase; lpBuffer.AllocationProtect = tmp64.AllocationProtect; lpBuffer.RegionSize = (long)tmp64.RegionSize; lpBuffer.State = tmp64.State; lpBuffer.Protect = tmp64.Protect; lpBuffer.Type = tmp64.Type; return(retVal); } var tmp32 = new MEMORY_BASIC_INFORMATION32(); retVal = Native_VirtualQueryEx(hProcess, lpAddress, out tmp32, new UIntPtr((uint)Marshal.SizeOf(tmp32))); lpBuffer.BaseAddress = tmp32.BaseAddress; lpBuffer.AllocationBase = tmp32.AllocationBase; lpBuffer.AllocationProtect = tmp32.AllocationProtect; lpBuffer.RegionSize = tmp32.RegionSize; lpBuffer.State = tmp32.State; lpBuffer.Protect = tmp32.Protect; lpBuffer.Type = tmp32.Type; return(retVal); }
public IEnumerable <byte[]> DumpMemory() { long procMinAddress = sysInfo.minimumApplicationAddress.ToInt64(); long procMaxAddress = sysInfo.maximumApplicationAddress.ToInt64(); MEMORY_BASIC_INFORMATION64 memBasicInfo = new MEMORY_BASIC_INFORMATION64(); IntPtr bytesRead = IntPtr.Zero; while (procMinAddress < procMaxAddress) { VirtualQueryEx(ProcessHandle, new IntPtr(procMinAddress), out memBasicInfo, new IntPtr(48)); bool hasAnyRead = memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_READONLY) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_READWRITE) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_EXECUTE_READ) || memBasicInfo.Protect.HasFlag(AllocationProtect.PAGE_EXECUTE_READWRITE); if (hasAnyRead && memBasicInfo.State.HasFlag(MemoryFlags.MEM_COMMIT)) { byte[] buffer = new byte[memBasicInfo.RegionSize.ToInt64()]; ReadProcessMemory(ProcessHandle, memBasicInfo.BaseAddress.ToInt64(), buffer, (int)memBasicInfo.RegionSize, out bytesRead); yield return(buffer); } procMinAddress += memBasicInfo.RegionSize.ToInt64(); } }
public static extern Int32 VirtualQueryEx64(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION64 lpBuffer, UInt32 dwLength);
static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION64 lpBuffer, uint dwLength);
// Function that checks the Access protection level of a memory location public static void MemInfo() { int pid; string pidString; uint pageSize = 0x1000; string memAddrStr; // Prompt fo user input of the pid of the process that contains the loaded module that the user wants protection info for Console.WriteLine("\nInput the Process Id for the module you want the protection information for:"); // Get user input for the pid pidString = Console.ReadLine(); // ensure the input is an integer try { pid = Convert.ToInt32(pidString); } // If not, go back to the menu and alert the usre catch (Exception ex) { Console.WriteLine("Input not an integer. Please try again"); menu(); pid = 0; } // Ensure the pid is to a running process try { Process proc = Process.GetProcessById(pid); } // If not return to the menu an dinform the user catch (Exception ex) { Console.WriteLine("Not a valid process. \nError: {0}", ex); menu(); } // Prompt user for memory address in hex of the module the user wants protection info for Console.WriteLine("\nInput the module base memory address in hex format (0x7ff...) to list protection Information:"); // get user input address memAddrStr = Console.ReadLine(); // ensure that the user entered a hex address try { Convert.ToInt64(memAddrStr, 16); } // If not alert the user and returnt o the menu catch (Exception ex) { Console.WriteLine("Invalid Memory address format. Must be in hex, 0x... format. Error: {0}", ex); menu(); } // Create a new pointer from converting the user input string to a 64 bit integer IntPtr base_mem_address = new IntPtr(Convert.ToInt64(memAddrStr, 16)); try { // Create a new basic memory information instancefrom the struct created belwo MEMORY_BASIC_INFORMATION64 mem_basic_info = new MEMORY_BASIC_INFORMATION64(); // Winsows APOI function callopening the process with desired access level and saving the handle to the process IntPtr pHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_WM_READ, false, pid); // Windows API funciton call to query the process memory information and save the information in the basic information struct instance created above VirtualQueryEx(pHandle, base_mem_address, out mem_basic_info, pageSize); // Call the get Memory Constant String funciton and save it a s a string string memProtectConstStr = getMemProtectConstStr(mem_basic_info.Protect); // Write the Memory protection information string to the console Console.WriteLine("\nProtection Information: {0}", memProtectConstStr); } // Or else return to the menu and alert the user of the failure catch (Exception ex) { Console.WriteLine("\nFailed to Open memory location. \nError: {0}", ex); menu(); } // Return to the menu menu(); }
public void TestGetMemInfo() { MEMORY_BASIC_INFORMATION64 Info = SystemInfoHelper.GetMemInfo32(Process.GetProcessesByName("ditto").FirstOrDefault().Handle, SystemInfoHelper.GetSysInfo().MinimumApplicationAddress); }
internal VirtualAllocRegion(MEMORY_BASIC_INFORMATION64 info, DbgEngDebugger debugger) : this(info, debugger, GetInfoDetails(info, debugger)) { }
public static extern uint VirtualQueryEx(IntPtr hProcess, IntPtr basePtr, out MEMORY_BASIC_INFORMATION64 lpBuffer, uint dwLength);
public static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION64 lpBuffer, uint dwLength);
private static extern Int64 VirtualQueryEx(HandleRef hProcess, Int64 lpAddress, out MEMORY_BASIC_INFORMATION64 lpBuffer, Int64 dwLength);
public ulong RvaToOffset(ulong Rva) { var sectionId = SectionStart; uint sections = 0; MEMORY_BASIC_INFORMATION64 mbi = new MEMORY_BASIC_INFORMATION64(); mbi = DebugApi.AddressType(BaseAddress); if (!DebugApi.IsIDNA && mbi.Protect == PAGE.NOACCESS) { DebugApi.WriteLine("Unable to read memory at %p", BaseAddress); return(0); } bool bIsImage = (DebugApi.IsIDNA || mbi.Type == MEM.IMAGE || mbi.Type == MEM.PRIVATE); if (FileImageType == ImageType.Pe32bit) { sections = NTHeader32.FileHeader.NumberOfSections; sectionId += (ulong)Marshal.OffsetOf(typeof(IMAGE_NT_HEADERS32), "OptionalHeader") + NTHeader32.FileHeader.SizeOfOptionalHeader; } if (FileImageType == ImageType.Pe64bit) { sections = NTHeader.FileHeader.NumberOfSections; sectionId += (ulong)Marshal.OffsetOf(typeof(IMAGE_NT_HEADERS64), "OptionalHeader") + NTHeader.FileHeader.SizeOfOptionalHeader; } for (int i = 0; i < sections; i++) { IMAGE_SECTION_HEADER section = new IMAGE_SECTION_HEADER(); if (!DebugApi.ReadMemory <IMAGE_SECTION_HEADER>(sectionId, out section)) { Debug.WriteLine("[RVA] Unable to read IMAGE_SECTION_HEADER"); return(0); } if ((Rva >= section.VirtualAddress) && (Rva < (section.VirtualAddress + section.SizeOfRawData))) { // RVA is in this section, we can now resolve it. ulong start = 0; if (bIsImage) { start = section.VirtualAddress; } else { start = section.PointerToRawData; } ulong address = BaseAddress + (ulong)Rva - (ulong)section.VirtualAddress + start; // (ulong)section.PointerToRawData; return(address); } // Next section sectionId += (uint)Marshal.SizeOf(typeof(IMAGE_SECTION_HEADER)); } // RVA could not be found return(0); }
private VirtualAllocRegion(MEMORY_BASIC_INFORMATION64 info, DbgEngDebugger debugger, (ulong size, List <VirtualAllocSubRegion> subRegions) details)
public bool SaveToStream(Stream ModuleStream) { MEMORY_BASIC_INFORMATION64 mbi = new MEMORY_BASIC_INFORMATION64(); mbi = DebugApi.AddressType(BaseAddress); if (mbi.Protect == PAGE.NOACCESS && !DebugApi.IsIDNA) { DebugApi.WriteLine("Unable to read memory at %p", BaseAddress); return(false); } bool bIsImage = DebugApi.IsIDNA || (mbi.Type == MEM.IMAGE || mbi.Type == MEM.PRIVATE); IMAGE_DOS_HEADER dosHeader = DOSHeader; if (!dosHeader.isValid) { return(false); } // NT PE Headers ulong dwAddr = BaseAddress; ulong dwEnd = 0; uint nRead; IMAGE_SECTION_HEADER section = new IMAGE_SECTION_HEADER(); ulong sectionAddr = 0; int nSection = 0; if (FileImageType == ImageType.Pe64bit) { sectionAddr = BaseAddress + (ulong)dosHeader.e_lfanew + (ulong)Marshal.OffsetOf(typeof(IMAGE_NT_HEADERS64), "OptionalHeader") + NTHeader.FileHeader.SizeOfOptionalHeader; nSection = NTHeader.FileHeader.NumberOfSections; dwEnd = BaseAddress + NTHeader.OptionalHeader.SizeOfHeaders; } if (FileImageType == ImageType.Pe32bit) { sectionAddr = BaseAddress + (ulong)dosHeader.e_lfanew + (ulong)Marshal.OffsetOf(typeof(IMAGE_NT_HEADERS32), "OptionalHeader") + NTHeader32.FileHeader.SizeOfOptionalHeader; nSection = NTHeader32.FileHeader.NumberOfSections; dwEnd = BaseAddress + NTHeader32.OptionalHeader.SizeOfHeaders; } MemLocation[] memLoc = new MemLocation[nSection]; int indxSec = -1; int slot; for (int n = 0; n < nSection; n++) { if (!DebugApi.ReadMemory <IMAGE_SECTION_HEADER>(sectionAddr, out section)) { DebugApi.WriteLine("[IMAGE_SECTION_HEADER] Fail to read PE section info at %p\n", sectionAddr); return(false); } for (slot = 0; slot <= indxSec; slot++) { if ((ulong)section.PointerToRawData < (ulong)memLoc[slot].FileAddr) { break; } } for (int k = indxSec; k >= slot; k--) { memLoc[k + 1] = memLoc[k]; } memLoc[slot].VAAddr = (IntPtr)section.VirtualAddress; memLoc[slot].VASize = (IntPtr)section.VirtualSize; memLoc[slot].FileAddr = (IntPtr)section.PointerToRawData; memLoc[slot].FileSize = (IntPtr)section.SizeOfRawData; indxSec++; sectionAddr += (ulong)Marshal.SizeOf(section); } uint pageSize; DebugApi.Control.GetPageSize(out pageSize); byte[] buffer = new byte[pageSize]; IDebugDataSpaces3 data = (IDebugDataSpaces3)DebugApi.Client; while (dwAddr < dwEnd) { nRead = pageSize; if (dwEnd - dwAddr < nRead) { nRead = (uint)(dwEnd - dwAddr); } if (data.ReadVirtual(dwAddr, buffer, nRead, out nRead) == (int)HRESULT.S_OK) { ModuleStream.Write(buffer, 0, (int)nRead); } else { DebugApi.WriteLine("Fail to read memory\n"); return(false); } dwAddr += nRead; } for (slot = 0; slot <= indxSec; slot++) { //if (!DebugApi.IsTaget64Bits) //{ if (bIsImage) { dwAddr = BaseAddress + (ulong)memLoc[slot].VAAddr; } else { dwAddr = BaseAddress + (ulong)memLoc[slot].FileAddr; } //} //else // dwAddr = BaseAddress + (ulong)memLoc[slot].FileAddr; dwEnd = (ulong)memLoc[slot].FileSize + dwAddr - 1; while (dwAddr <= dwEnd) { nRead = pageSize; if (dwEnd - dwAddr + 1 < pageSize) { nRead = (uint)(dwEnd - dwAddr + 1); } if (data.ReadVirtual(dwAddr, buffer, nRead, out nRead) == (int)HRESULT.S_OK) { ModuleStream.Write(buffer, 0, (int)nRead); } else { DebugApi.WriteLine("Fail to read memory\n"); return(false); } dwAddr += pageSize; } } return(true); }
public static List <InjectedThread> InjectedThreads() { // Check if running as administrator first? Or at least check if SeDebugPrivilege enabled? if (IsUserAnAdmin() == false) { Console.WriteLine("Program is not running as Administrator. Exiting..."); System.Environment.Exit(1); } List <InjectedThread> injectedThreads = new List <InjectedThread>(); // Create array of Process objects for each running process Process[] runningProcesses = Process.GetProcesses(); // Iterate over each process and get all threads by ID foreach (Process process in runningProcesses) { // PID 0 and PID 4 aren't valid targets for injection if (process.Id != 0 && process.Id != 4) { IntPtr hProcess; try { // Get handle to the process hProcess = OpenProcess(ProcessAccessFlags.All, false, process.Id); } catch (System.ComponentModel.Win32Exception) { Console.WriteLine($"Couldn't get handle to process: {process.Id} - System.ComponentModel.Win32Exception - Access Is Denied"); continue; } catch (System.InvalidOperationException) { Console.WriteLine($"Couldn't get handle to process {process.Id} - System.InvalidOperationException - Process has Exited"); continue; } // Get all threads under running process ProcessThreadCollection threadCollection = process.Threads; // Iterate over each thread under the process foreach (ProcessThread thread in threadCollection) { // Get handle to the thread IntPtr hThread = OpenThread(ThreadAccess.AllAccess, false, thread.Id); // Create buffer to store pointer to the thread's base address - NTQueryInformationThread writes to this buffer IntPtr buf = Marshal.AllocHGlobal(IntPtr.Size); // Retrieve thread's Win32StartAddress - Different to thread.StartAddress Int32 result = NtQueryInformationThread(hThread, ThreadInfoClass.ThreadQuerySetWin32StartAddress, buf, IntPtr.Size, IntPtr.Zero); if (result == 0) { // Need to Marshal Win32 type pointer from CLR type IntPtr to access the thread's base address via pointer IntPtr threadBaseAddress = Marshal.ReadIntPtr(buf); // Retrieve MEMORY_BASIC_INFORMATION struct for each thread - assumes 64bit processes, otherwise need to use MEMORY_BASIC_INFORMATION32 MEMORY_BASIC_INFORMATION64 memBasicInfo = new MEMORY_BASIC_INFORMATION64(); VirtualQueryEx(hProcess, threadBaseAddress, out memBasicInfo, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION64))); // Check the State and Type fields for the thread's MEMORY_BASIC_INFORMATION // Resolve to false suggests code running from this thread does not have a corresponding image file on disk, likely code injection if (memBasicInfo.State == MemoryBasicInformationState.MEM_COMMIT && memBasicInfo.Type != MemoryBasicInformationType.MEM_IMAGE) { // Create new InjectedThread object and set initial variables InjectedThread injectedThread = new InjectedThread() { ProcessName = process.ProcessName, ProcessID = process.Id, ThreadId = thread.Id, BaseAddress = threadBaseAddress, Path = process.MainModule.FileName, Size = (int)memBasicInfo.RegionSize, CommandLine = GetProcessCommandLine(process), MemoryState = Enum.GetName(typeof(MemoryBasicInformationState), memBasicInfo.State), MemoryType = Enum.GetName(typeof(MemoryBasicInformationType), memBasicInfo.Type), MemoryProtection = Enum.GetName(typeof(MemoryBasicInformationProtection), memBasicInfo.Protect), AllocatedMemoryProtection = Enum.GetName(typeof(MemoryBasicInformationProtection), memBasicInfo.AllocationProtect), BasePriority = thread.BasePriority, ThreadStartTime = thread.StartTime }; // Get handle to thread token. If Impersonation is not being used, thread will use Process access token // Try OpenThreadToken() - if it fails, use OpenProcessToken() if (OpenThreadToken(hThread, TokenAccessFlags.TOKEN_QUERY, false, out IntPtr hToken) == false) { // Thread doesn't have a unique token injectedThread.IsUniqueThreadToken = false; // Open process token instead if (OpenProcessToken(hProcess, TokenAccessFlags.TOKEN_QUERY, out hToken) == false) { Console.WriteLine($"Error opening thread and process token: {Marshal.GetLastWin32Error()}\nProcess ID {process.Id}"); } } else { injectedThread.IsUniqueThreadToken = true; } // Query process or thread token information injectedThread.SecurityIdentifier = QueryToken(hToken, TOKEN_INFORMATION_CLASS.TokenUser); injectedThread.Privileges = QueryToken(hToken, TOKEN_INFORMATION_CLASS.TokenPrivileges); injectedThread.Integrity = QueryToken(hToken, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel); injectedThread.LogonId = QueryToken(hToken, TOKEN_INFORMATION_CLASS.TokenOrigin); injectedThread.Username = GetProcessOwner(process.Id); // Get logon session information and add it to the InjectedThread object if (!string.IsNullOrEmpty(injectedThread.LogonId)) { GetLogonSessionData(hToken, injectedThread); } // Get thread's allocated memory via ReadProcessMemory injectedThread.ThreadBytes = GetThreadMemoryBytes(hProcess, threadBaseAddress, injectedThread.Size); // Read the full process memory ; injectedThread.ProcessBytes = GetProcessMemoryBytes(hProcess); // Read full name of executable image for the process int capacity = 1024; StringBuilder stringBuilder = new StringBuilder(capacity); QueryFullProcessImageName(hProcess, 0, stringBuilder, ref capacity); injectedThread.KernelPath = stringBuilder.ToString(0, capacity); // Check whether the kernel image path matches Process.MainModule.Filename if (injectedThread.Path.ToLower() != injectedThread.KernelPath.ToLower()) { injectedThread.PathMismatch = true; } injectedThreads.Add(injectedThread); CloseHandle(hToken); } CloseHandle(hThread); } } CloseHandle(hProcess); } } return(injectedThreads); }
public static extern UIntPtr Native_VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION64 lpBuffer, UIntPtr dwLength);
private void SystemSearch() { SYSTEM_INFO sys_info = new SYSTEM_INFO(); UnsafeNativeMethods.GetSystemInfo(out sys_info); MEMORY_BASIC_INFORMATION64 mem_basic_info = new MEMORY_BASIC_INFORMATION64(); List <MEMORY_BASIC_INFORMATION64> MemReg = new List <MEMORY_BASIC_INFORMATION64>(); long bip = ProcessModel.GetProcessBaseAddress(process); foreach (Signature sig in Signatures.Resolve(true)) { if (sig.Heap) { IntPtr hModuleSnapshot = new IntPtr(); hModuleSnapshot = UnsafeNativeHeap.CreateToolhelp32Snapshot(UnsafeNativeHeap.TH32CS_SNAPHEAPLIST | UnsafeNativeHeap.TH32CS_SNAPMODULE32, (uint)process.Id); if ((int)hModuleSnapshot == UnsafeNativeHeap.INVALID_HANDLE_VALUE) { System.Windows.Forms.MessageBox.Show("Not Heap Access. " + Marshal.GetLastWin32Error().ToString()); return; } UnsafeNativeHeap.HEAPENTRY64 pe64 = new UnsafeNativeHeap.HEAPENTRY64(); UnsafeNativeHeap.HEAPLIST64 heaplist = new UnsafeNativeHeap.HEAPLIST64(); heaplist.dwSize = (uint)Marshal.SizeOf(heaplist); UnsafeNativeHeap.PROCESS_HEAP_ENTRY64 phe64 = new UnsafeNativeHeap.PROCESS_HEAP_ENTRY64(); System.Threading.Thread.Sleep(10); bool r = UnsafeNativeHeap.Heap32ListFirst(hModuleSnapshot, ref heaplist); r = UnsafeNativeHeap.Heap32ListNext(hModuleSnapshot, ref heaplist); bool r2; while (r) { phe64.lpData = IntPtr.Zero; int a = Marshal.SizeOf(phe64); //28 (32) a = Marshal.SizeOf(phe64.lpData); //4 a = Marshal.SizeOf(phe64.cbData); //4 a = Marshal.SizeOf(phe64.cbOverhead); //2 a = Marshal.SizeOf(phe64.iRegionIndex); //2 a = Marshal.SizeOf(phe64.wFlags); //2 r2 = UnsafeNativeHeap.HeapWalk((IntPtr)heaplist.th32HeapID, ref phe64); System.Windows.Forms.MessageBox.Show("Not Heap Access. " + Marshal.GetLastWin32Error().ToString()); int cc = 0; //System.Windows.Forms.MessageBox.Show("Not Heap Access. " + Marshal.GetLastWin32Error().ToString()); while (r2 && cc < 100) { if (pe64.dwBlockSize == 883) { int t = 1; } r2 = UnsafeNativeHeap.Heap32Next(ref pe64); cc++; } r = UnsafeNativeHeap.Heap32ListNext(hModuleSnapshot, ref heaplist); } System.Windows.Forms.MessageBox.Show(Marshal.GetLastWin32Error().ToString()); UnsafeNativeHeap.CloseHandle(hModuleSnapshot); continue; //この方法もダメ sig.BaseAddress = (long)MemoryLib.ReadPointer((IntPtr)sig.PointerAddress); Locations[sig.Key] = sig; continue; ulong proc_min_address = (ulong)sys_info.minimumApplicationAddress; ulong proc_max_address = (ulong)sys_info.maximumApplicationAddress; // saving the values as long ints so I won't have to do a lot of casts later ulong proc_min_address_l = (ulong)proc_min_address; ulong proc_max_address_l = (ulong)proc_max_address; bool exitFg = true; while (proc_min_address_l < proc_max_address_l && exitFg) { VirtualQueryEx(processHandle, (IntPtr)proc_min_address, out mem_basic_info, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION64))); // if this memory chunk is accessible if (mem_basic_info.Protect == MemoryLib.PAGE_READWRITE && mem_basic_info.State == MemoryLib.MEM_COMMIT) { /* * * if (sig.Key == "PARTYCOUNT") * { * //check Mmeory PalyerNmae * ReadPlayerInfo(); * byte[] pattan = new byte[PlayerInfo.d.Name.Length]; * byte[] pattan0 = new byte[PlayerInfo.d.Name.Length+1]; * * pattan = System.Text.Encoding.ASCII.GetBytes(PlayerInfo.d.Name); * pattan.CopyTo(pattan0,1); * pattan0[0] = 1; * // read everything in the buffer above * int hp = (int)processHandle; * int readSize = (int)mem_basic_info.RegionSize;// < 64*1024 ? (int)mem_basic_info.RegionSize : 64 * 1024; * byte[] buffer = new byte[readSize]; * int bytesRead = 0; * UnsafeNativeMethods.ReadProcessMemory(hp, (Int64)mem_basic_info.BaseAddress, buffer, readSize, ref bytesRead); * int pickup = MemoryLib.FindSuperSig(buffer, pattan0); * if (pickup == -1) * { * proc_min_address_l += mem_basic_info.RegionSize; * proc_min_address = proc_min_address_l; * continue; * }else * { * sig.BaseAddress = (Int64)mem_basic_info.BaseAddress; * sig.Offset = pickup - (0x10 * 24) - 1; * Locations[sig.Key] = sig; * exitFg = false; * } * } */ } proc_min_address_l += mem_basic_info.RegionSize; proc_min_address = proc_min_address_l; } } else { if (sig.Value == "") { sig.BaseAddress = bip; Locations[sig.Key] = sig; continue; } else { Signature retrnSig = MemoryLib.FindExtendedSignatures(sig); //toDo Active Search... sig.BaseAddress = retrnSig.BaseAddress; Locations[sig.Key] = sig; } } } }