public static void InjectShellcode(this Process process, byte[] shellcodeBuffer) { // WRITE SHELLCODE TO TARGET MEMORY var shellcodeRemoteCall = process.AllocateAndWrite(shellcodeBuffer, NT.AllocationType.Commit | NT.AllocationType.Reserve, NT.MemoryProtection.ExecuteReadWrite); // CALL THE SHELLCODE TO CALL OUR SHELLCODE var shellcodeThread = process.CreateThread(shellcodeRemoteCall, 0, out threadId); // WAIT FOR THE THREAD TO FINISH NTM.WaitForThread(shellcodeThread); // FREE THE SHELLCODE process.FreeMemory(shellcodeRemoteCall); }
public static ulong GetModuleByName(this Process process, string moduleName) { ulong[] moduleHandleArray = new ulong[1000]; fixed(ulong *hMods = moduleHandleArray) { if (NT.EnumProcessModules(process.Handle, (ulong)hMods, (uint)(sizeof(ulong) * moduleHandleArray.Length), out uint cbNeeded) > 0) { for (int moduleIndex = 0; moduleIndex < cbNeeded / sizeof(ulong); moduleIndex++) { string name = NTM.GetModuleBaseName(process.Handle, moduleHandleArray[moduleIndex]); if (String.Equals(name, moduleName, StringComparison.InvariantCultureIgnoreCase)) { return(moduleHandleArray[moduleIndex]); } } } } return(0); }
public static Dictionary <string, ulong> GetModules(this Process process) { var result = new Dictionary <string, ulong>(); ulong[] moduleHandleArray = new ulong[1000]; fixed(ulong *hMods = moduleHandleArray) { if (NT.EnumProcessModules(process.Handle, (ulong)hMods, (uint)(sizeof(ulong) * moduleHandleArray.Length), out uint cbNeeded) > 0) { for (int moduleIndex = 0; moduleIndex < cbNeeded / sizeof(ulong); moduleIndex++) { string name = NTM.GetModuleBaseName(process.Handle, moduleHandleArray[moduleIndex]); result[name.ToLower()] = moduleHandleArray[moduleIndex]; //if (String.Equals(name, moduleName, StringComparison.InvariantCultureIgnoreCase)) // return moduleHandleArray[moduleIndex]; } } } return(result); }
public void FixImportTable(UInt32 localImage, NT.IMAGE_OPTIONAL_HEADER64 optionalHeader) { NT.IMAGE_IMPORT_DESCRIPTOR *importDescriptor = (NT.IMAGE_IMPORT_DESCRIPTOR *)(localImage + optionalHeader.ImportTable.VirtualAddress); for (; importDescriptor->FirstThunk > 0; ++importDescriptor) { string libraryName = Marshal.PtrToStringAnsi((IntPtr)(localImage + importDescriptor->Name)); // RECODE THIS, THIS IS STUPID & DANGEROUS // I AM ONLY DOING THIS BECAUSE OF API-SET DLLS // I COULDNT BE ARSED TO MAKE A PINVOKE FOR ApiSetResolveToHost ulong localLibraryHandle = NT.LoadLibrary(libraryName); libraryName = NTM.GetModuleBaseName(Process.GetCurrentProcess().Handle, localLibraryHandle).ToLower(); // IF WE MAPPED DEPENDENCY EARLIER, WE SHOULD USE RVA // INSTEAD OF STATIC MEMORY ADDRESS bool mappedDependency = MappedModules.TryGetValue(libraryName, out ulong remoteLibraryHandle); bool linkedInProcess = LinkedModules.TryGetValue(libraryName, out remoteLibraryHandle); if (!mappedDependency && !linkedInProcess) // DEPENDENCY NOT FOUND, MAP IT! { string dependencyPath = Tools.FindDll(libraryName); // SKIP IF DEPENDENCY COULDN'T BE FOUND if (dependencyPath == null) { continue; } // [8:44 PM] markhc: i had something similar // [8:44 PM] markhc: it was deep inside CRT initialization(edited) // [8:45 PM] Ch40zz: how did you fix it? // [8:46 PM] markhc: i didnt fix it // [8:46 PM] markhc: i thought it was something wrong with my manual mapper code, but i couldnt figure out what was it // [8:46 PM] markhc: so i threw it all away if (libraryName == "msvcp140.dll") { var tempOptions = Options; tempOptions.EraseHeaders = false; new LoadLibraryInjection(TargetProcess, TypeOfExecution, tempOptions).InjectImage(dependencyPath); --importDescriptor; continue; } remoteLibraryHandle = MapImage(libraryName, File.ReadAllBytes(dependencyPath)); mappedDependency = true; } UInt32 *functionAddress = (UInt32 *)(localImage + importDescriptor->FirstThunk); UInt32 *importEntry = (UInt32 *)(localImage + importDescriptor->OriginalFirstThunk); do { ulong procNamePointer = *importEntry < 0x8000000000000000 /*IMAGE_ORDINAL_FLAG64*/ ? // IS ORDINAL? localImage + *importEntry + sizeof(ushort) /*SKIP HINT*/ : // FUNCTION BY NAME *importEntry & 0xFFFF; // ORDINAL var localFunctionPointer = NT.GetProcAddress(localLibraryHandle, procNamePointer); var rva = localFunctionPointer - localLibraryHandle; // SET NEW FUNCTION POINTER *functionAddress = (UInt32)(mappedDependency ? remoteLibraryHandle + rva : localFunctionPointer); // GET NEXT ENTRY ++functionAddress; ++importEntry; } while (*importEntry > 0); } }
public static ulong GetNativeHandle(this ProcessThread thread, NT.ThreadAccess accessRights) => NTM.OpenThread(accessRights, thread.Id);
public static uint CreateAndWaitForThread(this Process process, ulong startAddress, ulong argumentAddress, out ulong threadHandle) { threadHandle = NT.CreateRemoteThread(process.Handle, 0, 0, startAddress, argumentAddress, 0, out ulong threadId); NTM.WaitForThread(threadHandle); return(NTM.GetThreadExitCode(threadHandle)); }
public bool InjectImage(string imagePath) { Log.LogGeneral($"Injecting {imagePath} -> {TargetProcess.ProcessName}_{TargetProcess.Id}"); // GET MODULE NAME FOR LATER USE string moduleName = Path.GetFileName(imagePath); // GET LOAD LIBRARY POINTER ulong loadLibraryPointer = NTM.GetModuleFunction("kernel32.dll", "LoadLibraryA"); // ALLOCATE IMAGE PATH IN TARGET PROCESS var rawImagePath = Encoding.Default.GetBytes(imagePath); ulong allocatedImagePath = TargetProcess.AllocateAndWrite(rawImagePath, NT.AllocationType.Commit | NT.AllocationType.Reserve, NT.MemoryProtection.ReadWrite); ulong threadHandle = 0; ulong moduleHandle = 0; bool injectionFailed = false; switch (TypeOfExecution) { #region Create Thread case ExecutionType.CreateThread: // CREATE A THREAD TO REMOTELY CALL LOADLIBRARY TargetProcess.CreateAndWaitForThread(loadLibraryPointer, allocatedImagePath, out threadHandle); // GET MODULE HANDLE FOR LATER USE moduleHandle = TargetProcess.GetModuleByName(moduleName); break; #endregion #region Hijack Thread case ExecutionType.HijackThread: byte[] shellcode = ShellcodeGenerator.CallLoadLibrary(allocatedImagePath, loadLibraryPointer); // ALLOCATE AND WRITE SHELLCODE TO TARGET ulong remoteShellcodePointer = TargetProcess.AllocateAndWrite(shellcode, NT.AllocationType.Commit | NT.AllocationType.Reserve, NT.MemoryProtection.ExecuteReadWrite); // GET THREAD HANDLE WITH PROPER ACCESS RIGHTS var usableThreads = TargetProcess.Threads.Cast <ProcessThread>().Where( x => x.ThreadState == System.Diagnostics.ThreadState.Wait && x.WaitReason == ThreadWaitReason.UserRequest); ProcessThread targetThread = usableThreads.ElementAt(NTM.RandomEngine.Next(usableThreads.Count())); threadHandle = targetThread.GetNativeHandle((NT.ThreadAccess) 0x1FFFFF); // ELEVATE HANDLE VIA DRIVER EXPLOIT if (Options.ElevateHandle) { ElevateHandle.Elevate(threadHandle, 0x1FFFFF); } Log.LogInfo($"Thread {targetThread.Id} - {targetThread.ThreadState} - {/*targetThread.WaitReason} - {targetThread.PriorityLevel} - {*/targetThread.CurrentPriority}"); // INITIALISE THREAD CONTEXT STRUCT NT.CONTEXT64 ctx = new NT.CONTEXT64() { ContextFlags = NT.CONTEXT_FLAGS.CONTEXT_FULL }; // SUSPEND THE THREAD SO WE CAN MODIFY REGISTERS if (NT.SuspendThread(threadHandle) == uint.MaxValue /*-1*/) { Log.LogError($"Failed to suspend thread - {Marshal.GetLastWin32Error().ToString("x2")}"); } // GET CONTEXT if (!NT.GetThreadContext(threadHandle, ref ctx)) { throw new Win32Exception($"GetThreadContext - {Marshal.GetLastWin32Error().ToString("x2")}"); } Log.LogInfo($"Stack Pointer: {ctx.Rsp.ToString("x2")} - {ctx.Rsp % 0x10}"); // ALLOCATE 8 BYTES ON STACK ctx.Rsp -= sizeof(ulong); // 'RET' WILL CALL POP AND JUMP TO THAT VALUE // SO WE WRITE OLD INSTRUCTION POINTER TO THE STACK SO WE CAN RETURN // SO DONT F**K UP THE STACK // F*****G RETARD TargetProcess.WriteRawMemory(BitConverter.GetBytes(ctx.Rip), ctx.Rsp); // OVERWRITE INSTRUCTION POINTER ctx.Rip = remoteShellcodePointer; // SET THREAD CONTEXT TO APPLY CHANGES if (!NT.SetThreadContext(threadHandle, ref ctx)) { throw new Win32Exception($"SetThreadContext- {Marshal.GetLastWin32Error().ToString("x2")}"); } // RESUME THREAD if (NT.ResumeThread(threadHandle) == uint.MaxValue /*-1*/) { Log.LogError($"Failed to resume thread - {Marshal.GetLastWin32Error().ToString("x2")}"); } // CLOSE THREAD HANDLE NT.CloseHandle(threadHandle); // WAIT FOR MODULE TO LOAD FULLY BEFORE FREEING SHELLCODE // IF WE DONT WAIT, WE MIGHT FREE BEFORE LOADLIBRARY HAS FINISHED // WHICH MEANS IT WILL JUMP BACK TO A NON-EXISTING MEMORY PAGE // ALSO WE DO LIMIT HOW LONG WE WAIT, AS WE MIGHT HAVE HIJACKED // A STUBBORN, RETARDED, SHITTY, USELESS, FILTHY NIGGER THREAD // THAT ISN'T GOING TO DO SHIT BUT SLEEP, LEAVING US HANGING // todo: look into stubborn threads Stopwatch watch = Stopwatch.StartNew(); while (watch.ElapsedMilliseconds < 2500) { moduleHandle = TargetProcess.GetModuleByName(moduleName); if (moduleHandle != 0) { break; } Thread.Sleep(1); } // IF WE HIJACKED A STUBBORN THREAD // WE CAN'T JUST FREE THE SHELLCODE NOR // THE ALLOCATED IMAGE PATH // AS IT MIGHT JUST RUN IT AFTER SOME TIME // RAISING AN EXCEPTION if (!(injectionFailed = moduleHandle == 0)) { TargetProcess.FreeMemory(remoteShellcodePointer); } //Console.ReadLine(); break; #endregion } // ERASE PE HEADERS if (Options.EraseHeaders && moduleHandle != 0) { TargetProcess.NukeMemoryPage(moduleHandle); } if (!injectionFailed) { TargetProcess.FreeMemory(allocatedImagePath); } // WE'LL HAVE TO REDO IF WE HIJACKED A STUBBORN THREAD return(injectionFailed ? new LoadLibraryInjection(TargetProcess, TypeOfExecution, Options).InjectImage(imagePath) : true); }