@@ -102,6 +102,57 @@ static bool acquireDebugPrivilege() {
102102
103103#endif
104104
105+ static HANDLE RtlCreateUserThread (HANDLE hProcess, LPVOID lpBaseAddress,
106+ LPVOID lpSpace) {
107+ typedef DWORD (WINAPI * functypeRtlCreateUserThread)(
108+ HANDLE ProcessHandle, PSECURITY_DESCRIPTOR SecurityDescriptor,
109+ BOOL CreateSuspended, ULONG StackZeroBits, PULONG StackReserved,
110+ PULONG StackCommit, LPVOID StartAddress, LPVOID StartParameter,
111+ HANDLE ThreadHandle, LPVOID ClientID);
112+ HANDLE hRemoteThread = NULL ;
113+ HMODULE hNtDllModule = GetModuleHandle (" ntdll.dll" );
114+ if (hNtDllModule == NULL ) {
115+ return NULL ;
116+ }
117+ functypeRtlCreateUserThread funcRtlCreateUserThread =
118+ (functypeRtlCreateUserThread)GetProcAddress (hNtDllModule,
119+ " RtlCreateUserThread" );
120+ if (!funcRtlCreateUserThread) {
121+ return NULL ;
122+ }
123+ funcRtlCreateUserThread (hProcess, NULL , 0 , 0 , 0 , 0 , lpBaseAddress, lpSpace,
124+ &hRemoteThread, NULL );
125+ DWORD lastError = GetLastError ();
126+ if (lastError)
127+ throw std::runtime_error (std::to_string (lastError));
128+ return hRemoteThread;
129+ }
130+
131+ static HANDLE NtCreateThreadEx (HANDLE hProcess, LPVOID lpBaseAddress,
132+ LPVOID lpSpace) {
133+ typedef DWORD (WINAPI * functypeNtCreateThreadEx)(
134+ PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes,
135+ HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress,
136+ LPVOID lpParameter, BOOL CreateSuspended, DWORD dwStackSize,
137+ DWORD Unknown1, DWORD Unknown2, LPVOID Unknown3);
138+ HANDLE hRemoteThread = NULL ;
139+ HMODULE hNtDllModule = NULL ;
140+ functypeNtCreateThreadEx funcNtCreateThreadEx = NULL ;
141+ hNtDllModule = GetModuleHandle (" ntdll.dll" );
142+ if (hNtDllModule == NULL ) {
143+ return NULL ;
144+ }
145+ funcNtCreateThreadEx = (functypeNtCreateThreadEx)GetProcAddress (
146+ hNtDllModule, " NtCreateThreadEx" );
147+ if (!funcNtCreateThreadEx) {
148+ return NULL ;
149+ }
150+ funcNtCreateThreadEx (&hRemoteThread, GENERIC_ALL , NULL , hProcess,
151+ (LPTHREAD_START_ROUTINE )lpBaseAddress, lpSpace, FALSE ,
152+ NULL , NULL , NULL , NULL );
153+ return hRemoteThread;
154+ }
155+
105156namespace blook {
106157
107158static DWORD ProtectToWin (Protect protect) {
@@ -420,4 +471,54 @@ std::vector<Thread> Process::threads() {
420471 }
421472 return threads;
422473}
474+
475+ void *Process::inject (const std::string &dll_path, Process::InjectMethod method) {
476+ LPVOID lpSpace =
477+ (LPVOID )VirtualAllocEx (h, NULL , dll_path.length (),
478+ MEM_RESERVE | MEM_COMMIT , PAGE_EXECUTE_READWRITE );
479+ if (!lpSpace)
480+ throw std::runtime_error (std::format (" Failed to alloc in proc" ));
481+
482+ int n = WriteProcessMemory (h, lpSpace, dll_path.c_str (),
483+ dll_path.length (), NULL );
484+ if (n == 0 )
485+ throw std::runtime_error (std::format (" failed to write into process" ));
486+
487+ switch (method) {
488+ case InjectMethod::NtCreateThread:
489+ return NtCreateThreadEx (h, (void *)LoadLibraryA, lpSpace);
490+ case InjectMethod::RtlCreateUserThread:
491+ return RtlCreateUserThread (h, (void *)LoadLibraryA, lpSpace);
492+ default :
493+ return CreateRemoteThread (h, NULL , 0 ,
494+ (LPTHREAD_START_ROUTINE )(void *)LoadLibraryA,
495+ lpSpace, NULL , NULL );
496+ }
497+ }
498+
499+ void Process::suspend () {
500+ for (auto &t : threads ())
501+ t.suspend ();
502+ }
503+
504+ void Process::resume () {
505+ for (auto &t : threads ())
506+ t.resume ();
507+ }
508+
509+ std::shared_ptr<Process> Process::launch (const std::string &path,
510+ bool suspended) {
511+ STARTUPINFOA si = {sizeof (si)};
512+ PROCESS_INFORMATION pi = {};
513+ if (!CreateProcessA (path.c_str (), NULL , NULL , NULL , FALSE ,
514+ suspended ? CREATE_SUSPENDED : 0 , NULL , NULL , &si, &pi))
515+ throw std::runtime_error (std::format (" Failed to launch process: {}" ,
516+ GetLastError ()));
517+ CloseHandle (pi.hThread );
518+ return attach (pi.hProcess );
519+ }
520+
521+ std::shared_ptr<Process> Process::launch_suspended (const std::string &path) {
522+ return launch (path, true );
523+ }
423524} // namespace blook
0 commit comments