static void Main(string[] args) { Process process = Process.GetProcessesByName("notepad").FirstOrDefault(); IntPtr hProcess = Processthreadsapi.OpenProcess(Winnt.ProcessAccessFlags.PROCESS_ALL_ACCESS, false, process.Id); if (hProcess == IntPtr.Zero) { Console.WriteLine("Failed on OpenProcess. Handle is invalid."); return; } if (Memoryapi.VirtualQueryEx(hProcess, process.MainModule.BaseAddress, out Winnt.MEMORY_BASIC_INFORMATION basicInformation, Marshal.SizeOf(typeof(Winnt.MEMORY_BASIC_INFORMATION))) == 0) { Console.WriteLine("Failed on VirtualQueryEx. Return is 0 bytes."); return; } IntPtr regionBase = basicInformation.baseAddress; IntPtr regionSize = basicInformation.regionSize; Ntpsapi.NtSuspendProcess(hProcess); RemapMemoryRegion(hProcess, regionBase, regionSize.ToInt32(), Winnt.MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE); Ntpsapi.NtResumeProcess(hProcess); Handleapi.CloseHandle(hProcess); }
public static Task DetourWs2Send() { //ToDo: Add handling W32Send.p3cx = Process.GetProcessesByName("3CXWin8Phone").FirstOrDefault(); W32Send.ws2ModIndex = GetModuleIndex(W32Send.p3cx.Modules, "WS2_32"); if (W32Send.ws2ModIndex == -1) { Debug.WriteLine("Module not found"); return(null); } IntPtr hWinsock = Libloaderapi.LoadLibraryA("WS2_32"); if (hWinsock == IntPtr.Zero) { return(null); } IntPtr sendFunc = Libloaderapi.GetProcAddress(hWinsock, "send"); if (sendFunc == IntPtr.Zero) { return(null); } W32Send.sendOffset = (int)sendFunc - (int)hWinsock; Libloaderapi.FreeLibrary(hWinsock); //The address of the detour int detourAddr = (int)Memoryapi.VirtualAllocEx(W32Send.p3cx.Handle, IntPtr.Zero, (uint)W32Send.Detour.assembly.Length, Winnt.AllocationType.MEM_COMMIT, Winnt.MemoryProtection.PAGE_EXECUTE_READWRITE); byte[] detourAddrArr = BitConverter.GetBytes(detourAddr); //The address of the memory storage int storageAddr = (int)Memoryapi.VirtualAllocEx(W32Send.p3cx.Handle, IntPtr.Zero, (uint)W32Send.PageSize, Winnt.AllocationType.MEM_COMMIT, Winnt.MemoryProtection.PAGE_EXECUTE_READWRITE); byte[] storageAddrArr = BitConverter.GetBytes(storageAddr); //Patching the detour-calling function with the detour address for (int i = W32Send.CallDetour.StartOfMovInstruction; i < W32Send.CallDetour.EndOfMovInstruction; i++) { W32Send.CallDetour.assembly[i] = detourAddrArr[i - 1]; } //Patching the detour function with the storage address for (int i = W32Send.Detour.StartOfMovEaxInstruction; i <= W32Send.Detour.EndOfMovEaxInstruction; i++) { W32Send.Detour.assembly[i] = storageAddrArr[i - 1]; } //Patching the detour function with the return address byte[] returnAddr = BitConverter.GetBytes((int)W32Send.p3cx.Modules[W32Send.ws2ModIndex].BaseAddress + W32Send.sendOffset + 0xA); for (int i = W32Send.Detour.StartOfMovEdxInstruction, x = 0; i < W32Send.Detour.EndOfMovEdxInstruction; i++, x++) { W32Send.Detour.assembly[i] = returnAddr[x]; } //Detouring the send function to the detour calling function IntPtr jmpToDetourAddr = W32Send.p3cx.Modules[W32Send.ws2ModIndex].BaseAddress + W32Send.sendOffset + W32Send.JmpToCallDetour.Offset; if (!Memoryapi.WriteProcessMemory(W32Send.p3cx.Handle, jmpToDetourAddr, W32Send.JmpToCallDetour.assembly, W32Send.JmpToCallDetour.assembly.Length, out IntPtr _)) { Debug.WriteLine(Marshal.GetLastWin32Error()); return(null); } ; //Writing the detour call if (!Memoryapi.WriteProcessMemory(W32Send.p3cx.Handle, (jmpToDetourAddr - 19), W32Send.CallDetour.assembly, W32Send.CallDetour.assembly.Length, out IntPtr _)) { Debug.WriteLine(Marshal.GetLastWin32Error()); return(null); } ; //Writing the detour if (!Memoryapi.WriteProcessMemory(W32Send.p3cx.Handle, (IntPtr)detourAddr, W32Send.Detour.assembly, W32Send.Detour.assembly.Length, out IntPtr _)) { Debug.WriteLine(Marshal.GetLastWin32Error()); return(null); } Task DetourTask = new Task(() => { while (W32Send.detour) { byte[] data = new byte[W32Send.PageSize]; if (!Memoryapi.ReadProcessMemory(W32Send.p3cx.Handle, (IntPtr)storageAddr, data, W32Send.PageSize, out _)) { Debug.WriteLine(Marshal.GetLastWin32Error()); } //IF the byte is signalled if (data[0] == 1) { //Memoryapi.ReadProcessMemory(p.Handle) SocketData sd = new SocketData() { length = BitConverter.ToInt32(data.Skip(1).Take(4).ToArray(), 0), bufferPtr = new byte[4], }; sd.bufferCont = new byte[sd.length]; Array.Copy(data, 5, sd.bufferPtr, 0, sizeof(int)); int bufferPtrAddr = BitConverter.ToInt32(sd.bufferPtr, 0); if (!Memoryapi.ReadProcessMemory(W32Send.p3cx.Handle, (IntPtr)bufferPtrAddr, sd.bufferCont, sd.length, out IntPtr _)) { Debug.Write(Marshal.GetLastWin32Error()); } #if DEBUG Trace.Write($"Socket Length {sd.length}\n"); Trace.Write($"Socket Payload {Encoding.ASCII.GetString(sd.bufferCont, 0, sd.length)}\n"); //Debug uses ascii so messages will be omitted Trace.Write("\n"); #endif //ToDo: USE THE CORRECT CODE HERE, UPDATE IT. Application.Current.Dispatcher.Invoke(() => { packetTable.Rows.Add("ws32_32.send", BitConverter.ToString(sd.bufferCont), sd.length, "NYI"); }); Memoryapi.WriteProcessMemory(W32Send.p3cx.Handle, (IntPtr)storageAddr, new byte[] { 0x0 }, 0x1, out IntPtr _); } //Performance Thread.Sleep(10); } //Remove the detour IntPtr origInstrAddr = W32Send.p3cx.Modules[W32Send.ws2ModIndex].BaseAddress + W32Send.sendOffset + W32Send.JmpToCallDetour.Offset; //Remove the detour jmp if (!Memoryapi.WriteProcessMemory(W32Send.p3cx.Handle, origInstrAddr, W32Send.JmpToCallDetour.originalInstructions, W32Send.JmpToCallDetour.originalInstructions.Length, out IntPtr _)) { ;//ToDo: Do something here } //Remove the jne instruction incase the comparison is mid-check. if (!Memoryapi.WriteProcessMemory(W32Send.p3cx.Handle, (IntPtr)(detourAddr + W32Send.Detour.JNEOffset), new byte[] { 0x90, 0x90 }, 0x2, out IntPtr _)) { ;//ToDo: Do something here } //ToDo: free memory of allocated pages. int me = 5; }); return(DetourTask); }
static void Main(string[] args) { //Set this bool to true if the region data is not obscured. bool sectioned = true; Process targetProc = Process.GetProcessesByName("notepad").FirstOrDefault(); //Open a handle to the target process IntPtr hProcess = Processthreadsapi.OpenProcess(ProcessAccessFlags.PROCESS_ALL_ACCESS, false, targetProc.Id); if (hProcess == IntPtr.Zero) { NativeError("OpenProcess"); } IntPtr baseAddress; int regionSize; if (sectioned) { //Set the base module address and the size. baseAddress = targetProc.MainModule.BaseAddress; regionSize = targetProc.MainModule.ModuleMemorySize; } else { //Query the process and get the baseInfo structure. /*Very specific practice for very specifc apps. .NET has built in methods for standard apps. * See: Process Class Base Address + ModuleMemorySize*/ if (Memoryapi.VirtualQueryEx ( hProcess, targetProc.MainModule.BaseAddress, out MEMORY_BASIC_INFORMATION basicInfo, Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION))) == 0 ) { NativeError("VirtualQueryEx"); } baseAddress = basicInfo.baseAddress; regionSize = (int)basicInfo.regionSize; } Ntpsapi.NtSuspendProcess(hProcess); //Allocate a buffer to read the region to. IntPtr buffer = Memoryapi.VirtualAlloc(IntPtr.Zero, regionSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (buffer == IntPtr.Zero) { NativeError("VirtualAlloc"); } //Read the data into the buffer. if (!Memoryapi.ReadProcessMemory(hProcess, baseAddress, buffer, regionSize, out _)) { NativeError("ReadProcessMemory"); } IntPtr hSection = IntPtr.Zero; long sectionMaxSize = (long)regionSize; //Create a section object to share between local and remote process. if (Ntifs.NtCreateSection ( ref hSection, SECTION_ALL_ACCESS, IntPtr.Zero, ref sectionMaxSize, PAGE_EXECUTE_READWRITE, SEC_COMMIT, IntPtr.Zero ) != Ntifs.Ntstatus.STATUS_SUCCESS) { NativeError("NtCreateSection"); } //Unmap the memory at the base of the remote process. if (Ntapi.NtUnmapViewOfSection(hProcess, baseAddress) != Ntifs.Ntstatus.STATUS_SUCCESS) { NativeError("NtUnmapViewOfSection"); } IntPtr viewBase = baseAddress; long sectionOffset = default; uint viewSize = default; //Map a region back to the original region location with new rights. if (Ntapi.NtMapViewOfSection ( hSection, hProcess, ref viewBase, UIntPtr.Zero, regionSize, ref sectionOffset, ref viewSize, 2 /*ViewUnmap*/, 0, PAGE_EXECUTE_READWRITE /*Set to the desired new access rights*/ ) != Ntifs.Ntstatus.STATUS_SUCCESS) { NativeError("NtMapViewOfSection"); } //Write the memory back to the updated region. if (!Memoryapi.WriteProcessMemory(hProcess, viewBase, buffer, (int)viewSize, out IntPtr _)) { NativeError("WriteProcessMemory"); } //Empty the buffer Memoryapi.VirtualFree(buffer, 0, MemFree.MEM_RELEASE); //Close the section handle Handleapi.CloseHandle(hSection); //Resume the process Ntpsapi.NtResumeProcess(hProcess); }
public static bool RemapMemoryRegion(IntPtr processHandle, IntPtr baseAddress, int regionSize, Winnt.MemoryProtectionConstraints mapProtection) { IntPtr addr = Memoryapi.VirtualAlloc(IntPtr.Zero, regionSize, Winnt.MemoryAllocationType.MEM_COMMIT | Winnt.MemoryAllocationType.MEM_RESERVE, mapProtection); if (addr == IntPtr.Zero) { return(false); } IntPtr copyBuf = Memoryapi.VirtualAlloc(IntPtr.Zero, regionSize, Winnt.MemoryAllocationType.MEM_COMMIT | Winnt.MemoryAllocationType.MEM_RESERVE, mapProtection); if (!Memoryapi.ReadProcessMemory(processHandle, baseAddress, copyBuf, regionSize, out IntPtr bytes)) { return(false); } IntPtr sectionHandle = default; long sectionMaxSize = regionSize; Ntifs.Ntstatus status = Ntifs.NtCreateSection(ref sectionHandle, Winnt.AccessMask.SECTION_ALL_ACCESS, IntPtr.Zero, ref sectionMaxSize, Winnt.MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE, Winnt.SectionProtectionConstraints.SEC_COMMIT, IntPtr.Zero); if (status != Ntifs.Ntstatus.STATUS_SUCCESS) { return(false); } status = Ntapi.NtUnmapViewOfSection(processHandle, baseAddress); if (status != Ntifs.Ntstatus.STATUS_SUCCESS) { return(false); } IntPtr viewBase = baseAddress; long sectionOffset = default; uint viewSize = 0; status = Ntapi.NtMapViewOfSection ( sectionHandle, processHandle, ref viewBase, UIntPtr.Zero, regionSize, ref sectionOffset, ref viewSize, 2, 0, Winnt.MemoryProtectionConstraints.PAGE_EXECUTE_READWRITE ); if (status != Ntifs.Ntstatus.STATUS_SUCCESS) { return(false); } if (!Memoryapi.WriteProcessMemory(processHandle, viewBase, copyBuf, (int)viewSize, out bytes)) { return(false); } if (!Memoryapi.VirtualFree(copyBuf, 0, Winnt.MemFree.MEM_RELEASE)) { return(false); } return(true); }
public static int FindInBaseModule(Process process, byte[] pattern, out IntPtr[] offsets, bool wildcard = false, byte wildcardChar = 0xff, bool findAll = false) { List <IntPtr> offsetList = new List <IntPtr>(); offsets = new IntPtr[] { (IntPtr)0 }; //Create a handle to the process IntPtr processHandle = Processthreadsapi.OpenProcess(0x0010 | 0x0020 | 0x0008, false, process.Id); //Initialize the a modInfo struct as new so the size can be safely obtained var modInfo = new Psapi.ModuleInfo(); //Allocated some memory for a ptr IntPtr modInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(modInfo)); //Get the module info for the process base bool ntStatus = Psapi.GetModuleInformation(processHandle, process.MainModule.BaseAddress, modInfoPtr, (uint)Marshal.SizeOf(modInfo)); if (!ntStatus) { return(Marshal.GetLastWin32Error()); } //Convert the ptr to the structure modInfo = (Psapi.ModuleInfo)Marshal.PtrToStructure(modInfoPtr, typeof(Psapi.ModuleInfo)); //Allocate a new buffer based on the size of the image byte[] lpBuffer = new byte[modInfo.SizeOfImage]; //Read the entire image into the buffer ntStatus = Memoryapi.ReadProcessMemory(processHandle, process.MainModule.BaseAddress, lpBuffer, (int)modInfo.SizeOfImage, out IntPtr _); if (!ntStatus) { return(Marshal.GetLastWin32Error()); } for (int i = 0; i < lpBuffer.Length; i++) { //Create a new array to copy potential matches to byte[] tempArray = new byte[pattern.Length]; if (lpBuffer[i] == pattern[0]) { if ((lpBuffer.Length - lpBuffer[i]) < pattern.Length) { continue; } for (int x = 0; x < pattern.Length; x++) { tempArray[x] = lpBuffer[i + x]; } if (wildcard) { bool match = true; for (int x = 0; x < pattern.Length; x++) { if (pattern[x] == tempArray[x] || pattern[x] == wildcardChar) { continue; } else { match = false; break; } } if (match) { offsetList.Add((IntPtr)i); } } else { if (Enumerable.SequenceEqual(tempArray, pattern)) { //Add the index of the byte[] to the offset list offsetList.Add((IntPtr)i); if (!findAll) { break; } } } } } offsets = offsetList.ToArray(); Handleapi.CloseHandle(processHandle); Marshal.FreeHGlobal(modInfoPtr); return(0); }