/* Attach to a running process. PID is the process ID to attach to, specified by the user or a higher layer. */ static int win32_attach (unsigned long pid) { HANDLE h; winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL; DWORD err; #ifdef _WIN32_WCE HMODULE dll = GetModuleHandle (_T("COREDLL.DLL")); #else HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL")); #endif DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit); h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid); if (h != NULL) { if (DebugActiveProcess (pid)) { if (DebugSetProcessKillOnExit != NULL) DebugSetProcessKillOnExit (FALSE); /* win32_wait needs to know we're attaching. */ attaching = 1; do_initial_child_stuff (h, pid, 1); return 0; } CloseHandle (h); } err = GetLastError (); error ("Attach to process failed (error %d): %s\n", (int) err, strwinerror (err)); }
static int __open_proc (RIOW32Dbg *dbg, bool attach) { DEBUG_EVENT de; int ret = -1; HANDLE h_proc = OpenProcess (PROCESS_ALL_ACCESS, FALSE, dbg->pid); if (!h_proc) { r_sys_perror ("__open_proc/OpenProcess"); goto att_exit; } if (attach) { /* Attach to the process */ if (!DebugActiveProcess(dbg->pid)) { r_sys_perror ("__open_proc/DebugActiveProcess"); goto att_exit; } /* catch create process event */ if (!WaitForDebugEvent (&de, 10000)) { r_sys_perror ("__open_proc/WaitForDebugEvent"); goto att_exit; } if (de.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) { eprintf ("exception code 0x%04x\n", (ut32)de.dwDebugEventCode); goto att_exit; } dbg->winbase = (ut64)de.u.CreateProcessInfo.lpBaseOfImage; } dbg->pi.hProcess = h_proc; dbg->tid = __w32_first_thread (dbg->pid); ret = dbg->pid; att_exit: if (ret == -1 && h_proc) { CloseHandle (h_proc); } return ret; }
// return thread id static int r_debug_native_attach (RDebug *dbg, int pid) { #if 0 if (!dbg || pid == dbg->pid) return dbg->tid; #endif #if __linux__ return linux_attach (dbg, pid); #elif __WINDOWS__ && !__CYGWIN__ int ret; HANDLE process = w32_open_process (PROCESS_ALL_ACCESS, FALSE, pid); if (process != (HANDLE)NULL && DebugActiveProcess (pid)) { ret = w32_first_thread (pid); } else { ret = -1; } ret = w32_first_thread (pid); CloseHandle (process); return ret; #elif __CYGWIN__ #warning "r_debug_native_attach not supported on this platform" return -1; #elif __APPLE__ return xnu_attach (dbg, pid); #elif __KFBSD__ if (ptrace (PT_ATTACH, pid, 0, 0) != -1) perror ("ptrace (PT_ATTACH)"); return pid; #else int ret = ptrace (PTRACE_ATTACH, pid, 0, 0); if (ret != -1) { perror ("ptrace (PT_ATTACH)"); } return pid; #endif }
extern "C" int __declspec(dllexport) AttachPid(DWORD dwVer_bose,DWORD dwPid,CP_HANDLER cp_handler,LOAD_DLL_HANDLER ld_handler,BP_HANDLER bp_handler,CT_HANDLER ct_handler,SS_HANDLER ss_handler,UNLOAD_DLL_HANDLER uld_handler) { HANDLE hProcess; dwVerbose = dwVer_bose; hProcess = OpenProcess(PROCESS_ALL_ACCESS,0,dwPid); if (hProcess == 0) { Log("OpenProcess Failed:%d:%d",dwPid,GetLastError()); return 0; } if(!DebugActiveProcess(dwPid)) { Log("DebugActiveProcess Failed:%d:%d",dwPid,GetLastError()); return 0; } Log("Attached to PID:%d",dwPid); load_dll_handler = ld_handler; create_process_handler = cp_handler; breakpoint_handler = bp_handler; createthread_handler = ct_handler; singlestep_handler = ss_handler; unload_dll_handler = uld_handler; EnterDebugging(dwPid); // call enter debugging n other init routines.... return 1; }
static void doChild(int argc, char **argv) { struct child_blackbox blackbox; const char *blackbox_file; HANDLE parent; DWORD ppid; BOOL debug; BOOL ret; blackbox_file = argv[4]; sscanf(argv[3], "%08x", &ppid); parent = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, ppid); child_ok(!!parent, "OpenProcess failed, last error %#x.\n", GetLastError()); ret = pCheckRemoteDebuggerPresent(parent, &debug); child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError()); child_ok(!debug, "Expected debug == 0, got %#x.\n", debug); ret = DebugActiveProcess(ppid); child_ok(ret, "DebugActiveProcess failed, last error %#x.\n", GetLastError()); ret = pCheckRemoteDebuggerPresent(parent, &debug); child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError()); child_ok(debug, "Expected debug != 0, got %#x.\n", debug); ret = pDebugActiveProcessStop(ppid); child_ok(ret, "DebugActiveProcessStop failed, last error %#x.\n", GetLastError()); ret = pCheckRemoteDebuggerPresent(parent, &debug); child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError()); child_ok(!debug, "Expected debug == 0, got %#x.\n", debug); ret = CloseHandle(parent); child_ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError()); ret = pIsDebuggerPresent(); child_ok(ret, "Expected ret != 0, got %#x.\n", ret); ret = pCheckRemoteDebuggerPresent(GetCurrentProcess(), &debug); child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError()); child_ok(debug, "Expected debug != 0, got %#x.\n", debug); if (pNtCurrentTeb) { pNtCurrentTeb()->Peb->BeingDebugged = FALSE; ret = pIsDebuggerPresent(); child_ok(!ret, "Expected ret != 0, got %#x.\n", ret); ret = pCheckRemoteDebuggerPresent(GetCurrentProcess(), &debug); child_ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError()); child_ok(debug, "Expected debug != 0, got %#x.\n", debug); pNtCurrentTeb()->Peb->BeingDebugged = TRUE; } blackbox.failures = child_failures; save_blackbox(blackbox_file, &blackbox, sizeof(blackbox)); }
BOOL My_DebugActiveProcess() { DWORD dwProcessId=NULL; BOOL returnVal_Real = NULL; BOOL returnVal_Intercepted = NULL; DWORD error_Real = 0; DWORD error_Intercepted = 0; __try{ disableInterception(); returnVal_Real = DebugActiveProcess (dwProcessId); error_Real = GetLastError(); enableInterception(); returnVal_Intercepted = DebugActiveProcess (dwProcessId); error_Intercepted = GetLastError(); }__except(puts("in filter"), 1){puts("exception caught");} return ((returnVal_Real == returnVal_Intercepted) && (error_Real == error_Intercepted)); }
HL_API bool hl_debug_start( int pid ) { # if defined(HL_WIN) last_pid = -1; return (bool)DebugActiveProcess(pid); # elif defined(USE_PTRACE) return ptrace(PTRACE_ATTACH,pid,0,0) >= 0; # else return false; # endif }
void CDebugger::Attach(DWORD dwProcessId) { cout << "[+] Debugger attach to pid:" << dwProcessId << endl; m_bActive = DebugActiveProcess(dwProcessId); if (m_bActive) { bool bSuccess = DebugSetProcessKillOnExit(m_bKillOnExit); DebugLoop(); } else { cout << "[-] Attach failed!" << endl; } }
void WinDebugger::attach(ProcessId pid) { if (process_ != INVALID_HANDLE_VALUE) { kill(); } process_ = OpenProcess(PROCESS_ALL_ACCESS, false, pid); BOOL ret = DebugActiveProcess(pid); if (!ret) { std::cerr << "error: attach: " << GetLastError() << std::endl; abort(); } }
static void debugThread(void *arg) { DWORD dwProcessId = (DWORD)(UINT_PTR)arg; // attach debuggee if (!DebugActiveProcess(dwProcessId)) { ErrorMessageBox("DebugActiveProcess: %s", LastErrorMessage()); return; } setDumpCallback(appendText); SetSymOptions(debug_options.debug_flag); DebugMainLoop(&debug_options); }
void attach(int PID) { h_process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID); if (DebugActiveProcess(PID)) { debugger_active = true; pid = PID; std::cout << "[*] Success DebugActiveProcess()." << std::endl; } else { std::cout << "[!] Unable to attach to the process." << std::endl; std::cout << "[!] Error Code : " << GetLastError() << std::endl; } }
/****************************************************************** * dbg_attach_debuggee * * Sets the debuggee to <pid> * cofe instructs winedbg what to do when first exception is received * (break=FALSE, continue=TRUE) * wfe is set to TRUE if dbg_attach_debuggee should also proceed with all debug events * until the first exception is received (aka: attach to an already running process) */ BOOL dbg_attach_debuggee(DWORD pid, BOOL cofe) { if (!(dbg_curr_process = dbg_add_process(&be_process_active_io, pid, 0))) return FALSE; if (!DebugActiveProcess(pid)) { dbg_printf("Can't attach process %04x: error %u\n", pid, GetLastError()); dbg_del_process(dbg_curr_process); return FALSE; } dbg_curr_process->continue_on_first_exception = cofe; SetEnvironmentVariableA("DBGHELP_NOLIVE", NULL); dbg_curr_process->active_debuggee = TRUE; return TRUE; }
Target::Process *Process::Attach(ProcessId pid) { if (pid <= 0) return nullptr; BOOL result; HANDLE handle, threadHandle; ThreadId tid; ErrorCode error; auto process = new Target::Process; result = DebugActiveProcess(pid); if (!result) goto fail; handle = OpenProcess(PROCESS_ALL_ACCESS, false, pid); if (!handle) goto fail; tid = GetFirstThreadIdForProcess(pid); if (tid == kAnyThreadId) goto proc_fail; threadHandle = OpenThread(THREAD_ALL_ACCESS, false, tid); if (!threadHandle) goto proc_fail; error = process->initialize(pid, handle, tid, threadHandle, kFlagAttachedProcess); if (error != kSuccess) goto init_fail; return process; init_fail: process->detach(); CloseHandle(threadHandle); proc_fail: CloseHandle(handle); fail: delete process; return nullptr; }
void AttachConHost(DWORD nConHostPID) { DWORD nErrCode = 0; HANDLE hConHost = GetProcessHandleForDebug(nConHostPID, &nErrCode); if (!hConHost) { _printf("Opening ConHost process handle failed, Code=%u\n", nErrCode); } else if (!DebugActiveProcess(nConHostPID)) { nErrCode = GetLastError(); _printf("Attaching to ConHost process handle failed, Code=%u\n", nErrCode); } if (!nErrCode) { //TODO: Запустить ConEmuC (требуемой битности) под админом } }
BOOL WindowsDebugger::debugger_attach( int nProcessId, BOOL bPause ) { if( this->windowsdebugger_token_privilege( SE_DEBUG_NAME, TRUE ) == FALSE ) { return FALSE; } this->bPauseOnAttach = bPause; if( DebugActiveProcess( nProcessId ) == FALSE ) { WinError::winerror_print_last_error( __FUNCTION__ ); dprintflvl( 2, "Unable to debug: %d", nProcessId ); return FALSE; } this->bAttachedToProcess = TRUE; this->nProcessId = nProcessId; return TRUE; }
BOOL CUseDebugger::DebugAttachedProcess() { m_pUI->ShowInfo("Please Enter the PID:\r\n"); system("taskmgr"); //get pid int argc; int pargv[MAXBYTE]; m_pUI->GetInput(&argc, pargv, g_szBuf, MAXBUF); DWORD dwPID = strtoul(g_szBuf, NULL, 10); assert(dwPID != 0 && dwPID != ULONG_MAX); if (DebugActiveProcess(dwPID)) { this->DebugProcess(); return TRUE; } return FALSE; }
int main(int argc,char *argv[]) { DWORD dwPID; if(argc!=2) { printf("Usage:%s pid\n",argv[0]); return 1; } //Attach Process dwPID=atoi(argv[1]); if(!DebugActiveProcess(dwPID)) { printf("DebugActiveProcess(%d) failed!\n","Error code =%d\n",dwPID,GetLastError()); return 1; } //debug loop DebugLoop(); return 0; }
BOOL CDbgHook::DbgAttatch(DWORD dwPid) { CProcessChecker pck; /* pck.SetData(dwPid); if (!pck.IsProcess()) return FALSE; */ if (!DebugActiveProcess(dwPid)) return FALSE; if (!WaitForDebugEvent(&m_de, INFINITE)) return FALSE; if (m_de.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT) return FALSE; memcpy(&m_cpdi, &m_de.u.CreateProcessInfo, sizeof(CREATE_PROCESS_DEBUG_INFO)); return TRUE; }
EXPORT BOOL CreateProcessA(LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation){ pid_t pid = vfork(); //printf("Creating process %s %s\n", lpApplicationName, lpCommandLine); if(pid == 0){ char commandline[256]; strncpy(commandline, lpCommandLine, 255); commandline[255] = 0; // ptrace(PT_TRACE_ME, 0, 0, 0); // parse command line; int i=0; char *p = strchr(commandline, ' '); char *q = commandline; char *argv[16]; while(p){ *p = 0; argv[i++] = q; fflush(stdout); q = p + 1; p = strchr(commandline, ' '); } argv[i] = q; argv[i+1] = 0; //printf("Execing %s %s %s", argv[0], argv[1], argv[2]); fflush(stdout); execv(argv[0], argv); perror("Failed to execv!"); } else { DebugActiveProcess(pid); // ptrace(PT_ATTACH, pid, 0, 0); // ptrace(PT_DETACH, pid, 0, 0); lpProcessInformation->dwProcessId = pid; lpProcessInformation->hProcess = pid; } return 1; }
int main(int argc, char* argv[]) { DWORD dwPID; if( argc != 2 ) { printf("\nUSAGE : hookdbg.exe <pid>\n"); return 1; } // Attach Process dwPID = atoi(argv[1]); if( !DebugActiveProcess(dwPID) ) { printf("DebugActiveProcess(%d) failed!!!\n" "Error Code = %d\n", dwPID, GetLastError()); return 1; } // 디버거 루프 DebugLoop(); return 0; }
void *Ploopgrab(LPVOID args) { DEBUG_EVENT dbg; DWORD cont = DBG_CONTINUE, size = 0; TCHAR pszFilename[MAX_PATH+1]; DWORD64 mod; struct proc_uc *tmp = args; struct ps_prochandle *P = tmp->ps; int first_execp = 0; BOOL wow = 0; char *s; DWORD Options = SymGetOptions(); if (DebugActiveProcess(P->pid) == 0) { dprintf( "failed to debug process (%d): %d\n", P->pid, GetLastError() ); pthread_mutex_lock(&P->mutex); P->status = PS_STOP; P->flags = CREATE_FAILED; if (P->status == PS_STOP) pthread_cond_signal(&P->cond); pthread_mutex_unlock(&P->mutex); return NULL; } DebugSetProcessKillOnExit(FALSE); P->wstat = 0; P->exitcode = 0; P->event = CreateEvent(NULL,FALSE,FALSE,NULL); P->dll_load_order = 1; SymSetOptions(Options|SYMOPT_INCLUDE_32BIT_MODULES|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG); while (1) { if (WaitForDebugEvent(&dbg, INFINITE) == 0) { return NULL; } cont = DBG_CONTINUE; pthread_mutex_lock(&P->mutex); switch (dbg.dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: P->thandle = dbg.u.CreateProcessInfo.hThread; P->phandle = dbg.u.CreateProcessInfo.hProcess; if ((SymInitialize(P->phandle, 0, FALSE) == FALSE)) { dprintf("SymInitialize failed (%d): %d\n", P->pid, GetLastError()); break; } s = GetFileNameFromHandle(dbg.u.CreateProcessInfo.hFile, pszFilename); addmodule(P, dbg.u.CreateProcessInfo.hFile, s, dbg.u.CreateProcessInfo.lpBaseOfImage, PE_TYPE_EXE, P->dll_load_order); size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL); if (size == INVALID_FILE_SIZE) { size = 0; } if ((mod = SymLoadModuleEx(P->phandle, dbg.u.CreateProcessInfo.hFile, s, NULL, (ULONG_PTR) dbg.u.CreateProcessInfo.lpBaseOfImage, size, NULL, 0)) == FALSE) { dprintf("SymLoadModule64 Failed for %s: %d\n", s, GetLastError()); break; } #if __amd64__ if (Is32bitProcess(P->phandle)) { P->model = PR_MODEL_ILP32; wow = 1; } else P->model = PR_MODEL_ILP64; #else P->model = PR_MODEL_ILP32; #endif CloseHandle(dbg.u.CreateProcessInfo.hFile); P->status = PS_RUN; P->msg.type = 0; break; case CREATE_THREAD_DEBUG_EVENT: P->status = PS_RUN; P->msg.type = 0; break; case LOAD_DLL_DEBUG_EVENT: s = GetFileNameFromHandle(dbg.u.LoadDll.hFile, pszFilename); if (first_execp) { P->dll_load_order++; } addmodule(P, dbg.u.LoadDll.hFile, s, dbg.u.LoadDll.lpBaseOfDll, PE_TYPE_DLL, P->dll_load_order); size = GetFileSize(dbg.u.CreateProcessInfo.hFile, NULL); if (size == INVALID_FILE_SIZE) { size = 0; } #if __amd64__ /* Not tracing 64 bit dlls for 32 bit process */ if (P->model == PR_MODEL_ILP32 && is64bitmodule(dbg.u.LoadDll.lpBaseOfDll, s)) { CloseHandle(dbg.u.LoadDll.hFile ); break; } #endif if ((mod = SymLoadModuleEx(P->phandle, dbg.u.LoadDll.hFile, s, NULL, (ULONG_PTR) dbg.u.LoadDll.lpBaseOfDll, size, NULL, 0)) == FALSE) { dprintf("SymLoadModule64 failed for %s: %d\n", s, GetLastError()); break; } CloseHandle(dbg.u.LoadDll.hFile ); if (first_execp == 0) { P->status = PS_RUN; P->msg.type = RD_DLACTIVITY; } else { P->status = PS_STOP; P->msg.type = RD_DLACTIVITY; } break; case UNLOAD_DLL_DEBUG_EVENT: if (SymUnloadModule64(P->phandle, (ULONG_PTR) dbg.u.UnloadDll.lpBaseOfDll) == FALSE) { dprintf("SymUnloadModule64 failed-Imagebase %p: %d\n", dbg.u.UnloadDll.lpBaseOfDll, GetLastError()); break; } delmodule(P, (ULONG64) dbg.u.UnloadDll.lpBaseOfDll); P->status = PS_RUN; P->msg.type = RD_DLACTIVITY; break; case EXIT_PROCESS_DEBUG_EVENT: P->exitcode = dbg.u.ExitProcess.dwExitCode; P->status = PS_UNDEAD; P->msg.type = RD_NONE; //SymCleanup(P->phandle); break; case EXIT_THREAD_DEBUG_EVENT: P->status = PS_RUN; P->msg.type = 0; break; case EXCEPTION_DEBUG_EVENT: switch(dbg.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_BREAKPOINT: if (first_execp++ == 0) { pthread_cond_signal(&P->cond); } P->status = PS_STOP; P->msg.type = 0; break; default: if (dbg.u.Exception.dwFirstChance == 0) P->wstat = dbg.u.Exception.ExceptionRecord.ExceptionCode; P->status = PS_RUN; cont = DBG_EXCEPTION_NOT_HANDLED; break; } break; default: P->status = PS_RUN; dprintf("Debug Event not processed: %d\n", dbg.dwDebugEventCode); break; } if (P->status != PS_RUN) SetEvent(P->event); while (P->status == PS_STOP) pthread_cond_wait(&P->cond, &P->mutex); pthread_mutex_unlock(&P->mutex); ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, cont); } }
static void doDebugger(int argc, char** argv) { const char* logfile; debugger_blackbox_t blackbox; HANDLE start_event, done_event, debug_event; blackbox.argc=argc; logfile=(argc >= 4 ? argv[3] : NULL); blackbox.pid=(argc >= 5 ? atol(argv[4]) : 0); if (strstr(myARGV[2], "attach")) { blackbox.attach_rc=DebugActiveProcess(blackbox.pid); if (!blackbox.attach_rc) blackbox.attach_err=GetLastError(); } else blackbox.attach_rc=TRUE; debug_event=(argc >= 6 ? (HANDLE)atol(argv[5]) : NULL); if (debug_event && strstr(myARGV[2], "event")) { blackbox.debug_rc=SetEvent(debug_event); if (!blackbox.debug_rc) blackbox.debug_err=GetLastError(); } else blackbox.debug_rc=TRUE; get_events(logfile, &start_event, &done_event); if (strstr(myARGV[2], "order")) { trace("debugger: waiting for the start signal...\n"); WaitForSingleObject(start_event, INFINITE); } if (strstr(myARGV[2], "nokill")) { blackbox.nokill_rc=pDebugSetProcessKillOnExit(FALSE); if (!blackbox.nokill_rc) blackbox.nokill_err=GetLastError(); } else blackbox.nokill_rc=TRUE; if (strstr(myARGV[2], "detach")) { blackbox.detach_rc=pDebugActiveProcessStop(blackbox.pid); if (!blackbox.detach_rc) blackbox.detach_err=GetLastError(); } else blackbox.detach_rc=TRUE; save_blackbox(logfile, &blackbox, sizeof(blackbox)); trace("debugger: done debugging...\n"); SetEvent(done_event); /* Just exit with a known value */ ExitProcess(0xdeadbeef); }
static void test_NtSuspendProcess(char *process_name) { PROCESS_INFORMATION info; DEBUG_EVENT ev; STARTUPINFOA startup; NTSTATUS status; HANDLE event; char buffer[MAX_PATH]; ULONG count; DWORD ret; status = pNtResumeProcess(GetCurrentProcess()); ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); event = CreateEventA(NULL, TRUE, FALSE, "wine_suspend_event"); ok(!!event, "Failed to create event: %u\n", GetLastError()); memset(&startup, 0, sizeof(startup)); startup.cb = sizeof(startup); sprintf(buffer, "%s tests/process.c dummy_process wine_suspend_event", process_name); ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info); ok(ret, "CreateProcess failed with error %u\n", GetLastError()); ret = WaitForSingleObject(event, 500); ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret); status = pNtSuspendProcess(info.hProcess); ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); ResetEvent(event); ret = WaitForSingleObject(event, 200); ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); status = NtResumeThread(info.hThread, &count); ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); ok(count == 1, "Expected count 1, got %d\n", count); ret = WaitForSingleObject(event, 200); ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret); status = pNtResumeProcess(info.hProcess); ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); status = pNtSuspendThread(info.hThread, &count); ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status); ok(count == 0, "Expected count 0, got %d\n", count); ResetEvent(event); ret = WaitForSingleObject(event, 200); ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); status = pNtResumeProcess(info.hProcess); ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); ret = WaitForSingleObject(event, 200); ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret); status = pNtSuspendThread(info.hThread, &count); ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status); ok(count == 0, "Expected count 0, got %d\n", count); status = pNtSuspendThread(info.hThread, &count); ok(status == STATUS_SUCCESS, "NtSuspendThread failed: %x\n", status); ok(count == 1, "Expected count 1, got %d\n", count); ResetEvent(event); ret = WaitForSingleObject(event, 200); ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); status = pNtResumeProcess(info.hProcess); ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); ret = WaitForSingleObject(event, 200); ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); status = pNtResumeProcess(info.hProcess); ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); ret = WaitForSingleObject(event, 200); ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret); ret = DebugActiveProcess(info.dwProcessId); ok(ret, "Failed to debug process: %d\n", GetLastError()); ResetEvent(event); ret = WaitForSingleObject(event, 200); ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); for (;;) { ret = WaitForDebugEvent(&ev, INFINITE); ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError()); if (!ret) break; if (ev.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT) break; ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE); ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError()); if (!ret) break; } ResetEvent(event); ret = WaitForSingleObject(event, 200); ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); status = pNtResumeProcess(info.hProcess); ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); ret = WaitForSingleObject(event, 200); ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); status = NtResumeThread(info.hThread, &count); ok(status == STATUS_SUCCESS, "NtResumeProcess failed: %x\n", status); ok(count == 0, "Expected count 0, got %d\n", count); ret = WaitForSingleObject(event, 200); ok(ret == WAIT_TIMEOUT, "Expected timeout, got: %d\n", ret); ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE); ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError()); ret = WaitForSingleObject(event, 200); ok(ret == WAIT_OBJECT_0, "Event was not signaled: %d\n", ret); TerminateProcess(info.hProcess, 0); CloseHandle(info.hProcess); CloseHandle(info.hThread); }
DWORD WINAPI DebugThread(LPVOID lpvParam) { DWORD nWait = WAIT_TIMEOUT; //DWORD nExternalExitCode = -1; wchar_t szInfo[1024]; if (gpSrv->DbgInfo.pszDebuggingCmdLine != NULL) { STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; if (gpSrv->DbgInfo.bDebugProcessTree) { SetEnvironmentVariable(ENV_CONEMU_BLOCKCHILDDEBUGGERS_W, ENV_CONEMU_BLOCKCHILDDEBUGGERS_YES); } if (!CreateProcess(NULL, gpSrv->DbgInfo.pszDebuggingCmdLine, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE| DEBUG_PROCESS | (gpSrv->DbgInfo.bDebugProcessTree ? 0 : DEBUG_ONLY_THIS_PROCESS), NULL, NULL, &si, &pi)) { DWORD dwErr = GetLastError(); wchar_t szProc[64]; szProc[0] = 0; PROCESSENTRY32 pi = {sizeof(pi)}; if (GetProcessInfo(gpSrv->dwRootProcess, &pi)) _wcscpyn_c(szProc, countof(szProc), pi.szExeFile, countof(szProc)); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't start debugging process. ErrCode=0x%08X\n", dwErr); lstrcpyn(szInfo+lstrlen(szInfo), gpSrv->DbgInfo.pszDebuggingCmdLine, 400); wcscat_c(szInfo, L"\n"); _wprintf(szInfo); return CERR_CANTSTARTDEBUGGER; } gpSrv->hRootProcess = pi.hProcess; gpSrv->hRootThread = pi.hThread; gpSrv->dwRootProcess = pi.dwProcessId; gpSrv->dwRootThread = pi.dwThreadId; gpSrv->dwRootStartTime = GetTickCount(); } /* ************************* */ int iDbgIdx = 0, iAttachedCount = 0; while (true) { HANDLE hDbgProcess = NULL; DWORD nDbgProcessID = 0; bool bFirstPID = ((iDbgIdx++) == 0); if (bFirstPID) { hDbgProcess = gpSrv->hRootProcess; nDbgProcessID = gpSrv->dwRootProcess; } else { // Взять из pDebugAttachProcesses if (!gpSrv->DbgInfo.pDebugAttachProcesses) break; if (!gpSrv->DbgInfo.pDebugAttachProcesses->pop_back(nDbgProcessID)) break; hDbgProcess = GetProcessHandleForDebug(nDbgProcessID); if (!hDbgProcess) { _ASSERTE(hDbgProcess!=NULL && "Can't open debugging process handle"); continue; } } _ASSERTE(hDbgProcess!=NULL && "Process handle must be opened"); // Битность отладчика должна соответствовать битности приложения! if (IsWindows64()) { int nBits = GetProcessBits(nDbgProcessID, hDbgProcess); if ((nBits == 32 || nBits == 64) && (nBits != WIN3264TEST(32,64))) { if (gpSrv->DbgInfo.pszDebuggingCmdLine != NULL) { _printf("Bitness of ConEmuC and debugging program does not match\n"); if (bFirstPID) return CERR_CANTSTARTDEBUGGER; else continue; } wchar_t szExe[MAX_PATH+16]; wchar_t szCmdLine[MAX_PATH*2]; if (GetModuleFileName(NULL, szExe, countof(szExe)-16)) { wchar_t* pszName = (wchar_t*)PointToName(szExe); _wcscpy_c(pszName, 16, (nBits == 32) ? L"ConEmuC.exe" : L"ConEmuC64.exe"); _wsprintf(szCmdLine, SKIPLEN(countof(szCmdLine)) L"\"%s\" /DEBUGPID=%u %s", szExe, nDbgProcessID, (gpSrv->DbgInfo.nDebugDumpProcess == 1) ? L"/DUMP" : (gpSrv->DbgInfo.nDebugDumpProcess == 2) ? L"/MINIDUMP" : (gpSrv->DbgInfo.nDebugDumpProcess == 3) ? L"/FULLDUMP" : L""); STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {}; if (CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { // Ждать НЕ будем, сразу на выход //HANDLE hEvents[2] = {pi.hProcess, ghExitQueryEvent}; //nWait = WaitForMultipleObjects(countof(hEvents), hEvents, FALSE, INFINITE); //if (nWait == WAIT_OBJECT_0) //{ // //GetExitCodeProcess(pi.hProcess, &nExternalExitCode); // nExternalExitCode = 0; //} //CloseHandle(pi.hProcess); //CloseHandle(pi.hThread); //if (nExternalExitCode == 0) //{ // goto done; //} // Может там еще процессы в списке на дамп? continue; } else { DWORD dwErr = GetLastError(); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't start external debugger '%s'. ErrCode=0x%08X\n", szCmdLine, dwErr); _wprintf(szInfo); if (bFirstPID) return CERR_CANTSTARTDEBUGGER; else continue; } } wchar_t szProc[64]; szProc[0] = 0; PROCESSENTRY32 pi = {sizeof(pi)}; if (GetProcessInfo(nDbgProcessID, &pi)) _wcscpyn_c(szProc, countof(szProc), pi.szExeFile, countof(szProc)); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Bits are incompatible. Can't debug '%s' PID=%i\n", szProc[0] ? szProc : L"not found", nDbgProcessID); _wprintf(szInfo); if (bFirstPID) return CERR_CANTSTARTDEBUGGER; else continue; } } if (gpSrv->DbgInfo.pszDebuggingCmdLine == NULL) { if (!DebugActiveProcess(nDbgProcessID)) { DWORD dwErr = GetLastError(); wchar_t szProc[64]; szProc[0] = 0; PROCESSENTRY32 pi = {sizeof(pi)}; if (GetProcessInfo(nDbgProcessID, &pi)) _wcscpyn_c(szProc, countof(szProc), pi.szExeFile, countof(szProc)); _wsprintf(szInfo, SKIPLEN(countof(szInfo)) L"Can't attach debugger to '%s' PID=%i. ErrCode=0x%08X\n", szProc[0] ? szProc : L"not found", nDbgProcessID, dwErr); _wprintf(szInfo); return CERR_CANTSTARTDEBUGGER; } } iAttachedCount++; } if (iAttachedCount == 0) { return CERR_CANTSTARTDEBUGGER; } /* **************** */ // Дополнительная инициализация, чтобы закрытие дебагера (наш процесс) не привело // к закрытию "отлаживаемой" программы pfnDebugActiveProcessStop = (FDebugActiveProcessStop)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"DebugActiveProcessStop"); pfnDebugSetProcessKillOnExit = (FDebugSetProcessKillOnExit)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"DebugSetProcessKillOnExit"); if (pfnDebugSetProcessKillOnExit) pfnDebugSetProcessKillOnExit(FALSE/*KillOnExit*/); gpSrv->DbgInfo.bDebuggerActive = TRUE; PrintDebugInfo(); SetEvent(gpSrv->DbgInfo.hDebugReady); while (nWait == WAIT_TIMEOUT) { ProcessDebugEvent(); if (ghExitQueryEvent) nWait = WaitForSingleObject(ghExitQueryEvent, 0); } //done: gbRootAliveLess10sec = FALSE; gbInShutdown = TRUE; gbAlwaysConfirmExit = FALSE; _ASSERTE(gbTerminateOnCtrlBreak==FALSE); if (!nExitQueryPlace) nExitQueryPlace = 12+(nExitPlaceStep); SetTerminateEvent(ste_DebugThread); return 0; }
static bool Launch() { return DebugActiveProcess(GetCurrentProcessId()) != FALSE; }
int wmain(int argc, WCHAR *argv[]) { /* Display welcome message */ printf("handle_monitor %s - Adam Kramer\n", VERSION_NUMBER); /* These variables hold configuration options, which can be altered by arguments passed */ BOOL bIncludeSigned = FALSE; BOOL bSuspendProcess = FALSE; BOOL bVerbose = FALSE; DWORD dNumberCycles = 10; DWORD dHandleChangeThreshold = 10; DWORD dIterationPause = 1000; /* Process arguments */ if (argc > 1) { for (int iNumberArgs = 1; iNumberArgs < argc; iNumberArgs++) { /* /signed - will include signed files in the alerts */ if (!wcscmp(argv[iNumberArgs], L"/signed")) { bIncludeSigned = TRUE; printf("Info: Will show signed files as well as unsigned\n"); } /* /suspect - will attempt to suspend suspicious processes */ else if (!wcscmp(argv[iNumberArgs], L"/suspend")) { bSuspendProcess = TRUE; printf("Info: Will attempt to suspend suspicious processes\n"); } /* /verbose - will display details of iterations and hidden results */ else if (!wcscmp(argv[iNumberArgs], L"/verbose")) { bVerbose = TRUE; printf("Info: Will display verbose status messages\n"); } /* /cycles - allows the user to set cycles completed before analysis */ else if (WCHAR* wSetCycles = wcsstr(argv[iNumberArgs], L"/cycles=")) { wSetCycles = wcschr(wSetCycles, '='); if (!(dNumberCycles = _wtol(++wSetCycles))) { printf("Error: Invalid /cycles parameter\n"); return 1; } printf("Info: Setting number of cycles to %d\n", dNumberCycles); } /* /threshold - allows the user to set the threshold for minimum number of new handles which are suspicious */ else if (WCHAR* wSetThreshold = wcsstr(argv[iNumberArgs], L"/threshold=")) { wSetThreshold = wcschr(wSetThreshold, '='); if (!(dHandleChangeThreshold = _wtol(++wSetThreshold))) { printf("Error: Invalid /threshold parameter\n"); return 1; } printf("Info: Setting handle threshold to %d\n", dHandleChangeThreshold); } /* /pause - allows the user to set a pause between cycles (reduce system load, increase window for finding something) */ else if (WCHAR* wSetPause = wcsstr(argv[iNumberArgs], L"/pause=")) { wSetPause = wcschr(wSetPause, '='); dIterationPause = _wtol(++wSetPause); printf("Info: Setting pause between cycles to %dms\n", dIterationPause); } } /* End of argument processing */ } else { /* No argument passed, accordingly display the usage instructions */ printf("Usage: handle_monitor.exe <optional parameters>\n\n"); printf("Optional parameters:\n"); printf("/cycles=X - Set number of cycles before a review [Default: 10]\n"); printf("/threshold=X - Set suspicion threshold for number of new handles [Default: 10]\n"); printf("/pause=X - Set pause in milliseconds between cycles [Default: 1000]\n"); printf("/signed - Include signed executables in review process\n"); printf("/suspend - Suspend processes identified as suspicious\n"); printf("/verbose - Display verbose progress messages\n\n"); printf("Info: No parameters specified, launching monitoring (Ctrl+C to stop)\n"); } /* Import functions manually from NTDLL */ _NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation"); _NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtDuplicateObject"); _NtQueryObject NtQueryObject = (_NtQueryObject)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryObject"); /* Master loop! - This runs forever until a user presses Ctrl+C */ for (;;) { /* Update user that process is starting (if /verbose mode activiated) */ if (bVerbose) printf("Verbose Info: Starting sequence\n"); /* Variables used for retrieving handles */ NTSTATUS status; ULONG handleInfoSize = 0x10000; HANDLE processHandle; ULONG i; PSYSTEM_HANDLE_INFORMATION handleInfo; /* Used in each handle iteration to identify the index in iProcessArray of the specific process */ int iCurrentProcess_ArrayIndex = -1; /* Handle array - PROCESS INDEX / HANDLE NUMBER / TEXT OF HANDLE This holds all handles which have been found per process */ auto cHandleArray = new WCHAR[MAX_PROCESSES][MAX_FILE_HANDLES][MAX_PATH](); signed int iProcessArray[MAX_PROCESSES][3] = { 0 }; /* Set process array to -1, which indicates nothing has been set */ for (int j = 0; j < (MAX_PROCESSES - 1); j++) iProcessArray[j][0] = -1; /* Loop dNumberCycles [default: 10] times before analysing result */ for (unsigned int iCycleCounter = 1; iCycleCounter <= dNumberCycles; iCycleCounter++) { handleInfoSize = 0x10000; handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); /* NtQuerySystemInformation won't give us the correct buffer size, so we guess by doubling the buffer size. */ while ((status = NtQuerySystemInformation(SystemHandleInformation, handleInfo, handleInfoSize, NULL)) == STATUS_INFO_LENGTH_MISMATCH) handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2); /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */ if (!NT_SUCCESS(status)) { printf("NtQuerySystemInformation failed!\n"); return 1; } /* Loop for each handle on the system, processing it accordingly... */ for (i = 0; i < handleInfo->HandleCount; i++) { SYSTEM_HANDLE handle = handleInfo->Handles[i]; HANDLE dupHandle = NULL; POBJECT_TYPE_INFORMATION objectTypeInfo; /* Open a handle to the process associated with the handle */ if (!(processHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, handle.ProcessId))) continue; /* Duplicate the handle so we can query it. */ if (!NT_SUCCESS(NtDuplicateObject(processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &dupHandle, GENERIC_READ, 0, 0))) { CloseHandle(processHandle); CloseHandle(dupHandle); continue; } /* Query the object type */ objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); if (!NT_SUCCESS(NtQueryObject(dupHandle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL))) { free(objectTypeInfo); CloseHandle(processHandle); CloseHandle(dupHandle); continue; } /* If it's not a file handle, go to next one (as we're only interested in file handles) */ if (wcscmp(objectTypeInfo->Name.Buffer, L"File")) { free(objectTypeInfo); CloseHandle(processHandle); CloseHandle(dupHandle); continue; } /* Identify the filename from the handle we're looking at */ WCHAR* wHandleFileName = new WCHAR[MAX_PATH](); if (!GetFileNameFromHandle(dupHandle, wHandleFileName)) { free(objectTypeInfo); free(wHandleFileName); CloseHandle(processHandle); CloseHandle(dupHandle); continue; } /* This is where we add our findings to the database */ iCurrentProcess_ArrayIndex = -1; /* Check whether we've already got an entry for the process we're looking at */ for (int j = 0; j < (MAX_PROCESSES - 1); j++) if (iProcessArray[j][PROCESS_ARRAY_INDEX] == handle.ProcessId) iCurrentProcess_ArrayIndex = j; /* If not, create a new entry for the process associated with the current handle */ if (iCurrentProcess_ArrayIndex == -1) for (int j = 0; j < (MAX_PROCESSES - 1); j++) if (iProcessArray[j][PROCESS_ARRAY_INDEX] == -1) { iProcessArray[j][PROCESS_ARRAY_INDEX] = handle.ProcessId; iCurrentProcess_ArrayIndex = j; break; } /* If there's more than MAX_PROCESSES, throw an error TODO: Tidy this up, identify number of running processes dynamically and set array size accordingly */ if (iCurrentProcess_ArrayIndex == -1) { printf("Error: Too many processes running!\n"); return 1; } /* Look through the handle array, to see whether the filename can be found */ WCHAR cCurrentHandleText[MAX_PATH]; for (int j = 0; j < (MAX_FILE_HANDLES - 1); j++) { /* If we hit NULL, there are no more to find, so add ours */ swprintf_s(cCurrentHandleText, MAX_PATH, L"%ls", wHandleFileName); if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], L"")){ wcscpy_s(cHandleArray[iCurrentProcess_ArrayIndex][j], cCurrentHandleText); break; } /* If we find ours, then stop searching */ else if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], cCurrentHandleText)) break; } /* If it's the first (or last) cycle, tally how many entries in the handle array for this particular process we have so far */ if (iCycleCounter == 1) for (int j = 0; j < (MAX_FILE_HANDLES - 1); j++) if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], L"")){ iProcessArray[iCurrentProcess_ArrayIndex][PROCESS_ARRAY_COUNT_START_CYCLE] = (j - 1); break; } if (iCycleCounter == dNumberCycles) for (int j = 0; j < (MAX_FILE_HANDLES - 1); j++) if (!wcscmp(cHandleArray[iCurrentProcess_ArrayIndex][j], L"")) { iProcessArray[iCurrentProcess_ArrayIndex][PROCESS_ARRAY_COUNT_END_CYCLE] = (j - 1); break; } free(objectTypeInfo); free(wHandleFileName); CloseHandle(dupHandle); CloseHandle(processHandle); } free(handleInfo); /* If the iteration pause is not 0, sleep for the requested time [Default: 1000ms] */ if (dIterationPause) Sleep(dIterationPause); /* If /verbose active - inform user which cycle we are on */ if (bVerbose) if (iCycleCounter == 1) printf("Verbose Info: Completed cycle %d", iCycleCounter); else if (iCycleCounter == dNumberCycles) printf(" %d\n", iCycleCounter); else printf(" %d", iCycleCounter); } /* If /verbose active - inform user we are now starting a review */ if (bVerbose) printf("Verbose Info: Cycles completed, beginning review\n"); /* Check if any of them met threshold*/ for (int j = 0; j < (MAX_PROCESSES - 1); j++) { if (iProcessArray[j][PROCESS_ARRAY_COUNT_END_CYCLE] < iProcessArray[j][PROCESS_ARRAY_COUNT_START_CYCLE]) continue; /* dHandleDelta is the difference between number of handles for a process from first cycle to the last one */ DWORD dHandleDelta = (iProcessArray[j][PROCESS_ARRAY_COUNT_END_CYCLE] - iProcessArray[j][PROCESS_ARRAY_COUNT_START_CYCLE]); /* Check whether the delta is equal or above the threshold */ if (dHandleDelta >= dHandleChangeThreshold) { HANDLE pHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, iProcessArray[j][PROCESS_ARRAY_INDEX]); TCHAR tProcessName[MAX_PATH]; GetModuleFileNameEx(pHandle, 0, tProcessName, MAX_PATH); CloseHandle(pHandle); /* If we don't want signed, yet it is signed, skip... */ if (!bIncludeSigned && (is_signed(tProcessName) == 0)) { if (bVerbose) wprintf(L"Verbose Info: Skipping alert on %s (%d) despite trigger, as it is signed (use /signed to alert on signed executables too)\n", tProcessName, iProcessArray[j][PROCESS_ARRAY_INDEX]); continue; } /* Inform the user if we have a suspicious process */ wprintf(L"Alert! Process: %s (%d) has had a suspicious number of handles (%d) created in the last cycle\nNew handles created during this cycle:\n", tProcessName, iProcessArray[j][PROCESS_ARRAY_INDEX], dHandleDelta); for (DWORD k = 1; k <= dHandleDelta; k++) wprintf(L"%s\n", cHandleArray[j][iProcessArray[j][PROCESS_ARRAY_COUNT_START_CYCLE] + k]); if (bSuspendProcess) { printf("Info: Attempting to suspend process %d\n", iProcessArray[j][PROCESS_ARRAY_INDEX]); /* Attach debugger to process (freeze it!)*/ if (!DebugActiveProcess(iProcessArray[j][PROCESS_ARRAY_INDEX])) { printf("Info: Could not attach to process %d as a debugger\n", iProcessArray[j][PROCESS_ARRAY_INDEX]); } else { DebugSetProcessKillOnExit(FALSE); printf("Info: Successfully attached to process %d as debugger\n", iProcessArray[j][PROCESS_ARRAY_INDEX]); printf("Info: It will remain frozen until this process is terminated\n"); } } printf("------------------------------------------------------------------------------\n"); } } if (bVerbose) printf("Verbose Info: Review complete\n"); free(cHandleArray); } return 0; }
void stAttachDebugger( DWORD processId, std::string fnIncludes, std::string fnExcludes, bool activeProcess = true) /*++ Routine Description: Our mini-debugger implementation. It does following things: - Attach to a running process - On first breakpoint, inject the IAT patching DLL into target - Print information of any exception in target process - Print the debug spew from target process Arguments: processId - PID of the process to attach fnIncludes - List of include filters fnExclude - List of exclude filters activeProcess - If we are attaching to an already running process then we pass activeProcess = true, this causes us to call DebugActiveProcess and not wait for process creation event --*/ { int threadCount = 0; bool processInfected = false; if (activeProcess) { if (!DebugActiveProcess(processId)) { gView->PrintError(L"\nCould not attach to the process (PID = %d).", processId); stHandleError(GetLastError()); goto funcExit; } } HMODULE hMod = GetModuleHandle(L"Kernel32.dll"); if (hMod) { PFNDEBUGSETPROCESSKILLONEXIT pfnDebugSetProcessKillOnExit = (PFNDEBUGSETPROCESSKILLONEXIT)GetProcAddress(hMod, "DebugSetProcessKillOnExit"); if (pfnDebugSetProcessKillOnExit) { pfnDebugSetProcessKillOnExit(FALSE); } } gProcessId = processId; DEBUG_EVENT debugEvent; DWORD dwContinueStatus = DBG_CONTINUE; bool keepAlive = true; while(keepAlive) { WaitForDebugEvent(&debugEvent, INFINITE); dwContinueStatus = DBG_CONTINUE; if (debugEvent.dwProcessId == processId) { switch (debugEvent.dwDebugEventCode) { case EXCEPTION_DEBUG_EVENT: { switch (debugEvent.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_BREAKPOINT: { //IHU_DBG_LOG(TRC_STRACE, HX_LEVEL_INFO, (L"EXCEPTION_BREAKPOINT\n")); if (!processInfected) { if (gRemovePatchOnExit) { HRSRC hRes; HGLOBAL hResG; LPVOID pRes; DWORD dwResSize; hRes = FindResource( NULL, MAKEINTRESOURCE(IDR_BIN_DLL), L"BIN"); hResG = LoadResource(NULL, hRes); pRes = LockResource(hResG); dwResSize = SizeofResource(NULL, hRes); wchar_t tempPath[MAX_PATH]; wchar_t tempFile[MAX_PATH]; GetTempPath(MAX_PATH, tempPath); GetTempFileName(tempPath, L"", 0, tempFile); gInjectorDllPath = tempFile; HANDLE oFile = CreateFile( gInjectorDllPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (oFile == INVALID_HANDLE_VALUE) { gView->PrintError( L"Failed to create the temporary DLL [%s]. Error code = %x\n", gInjectorDllPath.c_str(), GetLastError()); return; } DWORD bytesWritten; if (!WriteFile( oFile, pRes, dwResSize, &bytesWritten, NULL)) { gView->PrintError( L"Failed to write the temporary DLL. Error code = %x\n", GetLastError()); return; } CloseHandle(oFile); } else { wchar_t exePath[MAX_PATH]; if (GetModuleFileName( NULL, exePath, MAX_PATH)) { std::wstring dllPath = exePath; int slashPos = dllPath.find_last_of(L'\\'); if (slashPos != -1) { dllPath = dllPath.substr(0, slashPos + 1); } dllPath += L"stserum.dll"; gInjectorDllPath = dllPath; } } ihiInjectDll( ghProcess, (LPCWSTR)gInjectorDllPath.c_str(), (LPCSTR)fnIncludes.c_str(), (LPCSTR)fnExcludes.c_str()); processInfected = true; } break; } default: { if (debugEvent.u.Exception.dwFirstChance) { gView->PrintWarning(L"Exception = %x, Address = %x (first-chance!)\n", debugEvent.u.Exception.ExceptionRecord.ExceptionCode, debugEvent.u.Exception.ExceptionRecord.ExceptionAddress); } else { gView->PrintError(L"Exception = %x, Address = %x (second-chance!)\n", debugEvent.u.Exception.ExceptionRecord.ExceptionCode, debugEvent.u.Exception.ExceptionRecord.ExceptionAddress); } // // If this was a second chance exception, it will cause // the process to terminate // dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED; break; } } break; } case CREATE_THREAD_DEBUG_EVENT: { ++threadCount; break; } case CREATE_PROCESS_DEBUG_EVENT: { if (ghProcess == INVALID_HANDLE_VALUE) { ghProcess = debugEvent.u.CreateProcessInfo.hProcess; } //IHU_DBG_LOG(TRC_STRACE, HX_LEVEL_INFO, (L"Create Process\n")); break; } case EXIT_THREAD_DEBUG_EVENT: { --threadCount; break; } case EXIT_PROCESS_DEBUG_EVENT: { gView->PrintMessage( L"Target process has been terminated. Exit Code = %d.\n", debugEvent.u.ExitProcess.dwExitCode); keepAlive = false; break; } case LOAD_DLL_DEBUG_EVENT: { break; } case UNLOAD_DLL_DEBUG_EVENT: { break; } case OUTPUT_DEBUG_STRING_EVENT: { DWORD cbRead = 0; ReadProcessMemory( ghProcess, debugEvent.u.DebugString.lpDebugStringData, gDbgString, debugEvent.u.DebugString.nDebugStringLength, &cbRead); if (debugEvent.u.DebugString.fUnicode) { if (gDbgString[0] == L'$') { gView->PrintTrace(L"%ws", &gDbgString[1]); } else if (gDbgString[0] == L'#') { gView->PrintError(L"%ws", &gDbgString[1]); } else { gView->PrintTraceOrig(L"%ws", gDbgString); } } else { if (gDbgString[0] == L'$') { gView->PrintTraceA("%s", &gDbgString[1]); } else if (gDbgString[0] == L'#') { gView->PrintErrorA("%s", &gDbgString[1]); } else { gView->PrintTraceOrigA("%s", gDbgString); } } break; } } } ContinueDebugEvent( debugEvent.dwProcessId, debugEvent.dwThreadId, dwContinueStatus); } // // If we need to remove the patching on exit, it means we created a // temporary injector dll, we should delete that now // if (gRemovePatchOnExit) { DeleteFile(gInjectorDllPath.c_str()); } //IHU_DBG_LOG(TRC_STRACE, HX_LEVEL_INFO, (L"Total thread count = %d\n", threadCount)); funcExit: return; }
void debug(DWORD processId) { DebugActiveProcess(processId); }
static int NaClDebugExceptionHandlerStandaloneMain(int argc, char **argv) { int target_pid; NaClHandle socket; char *rest1; char *rest2; void *info; size_t info_size; HANDLE process_handle; DWORD written; if (argc != 3) { NaClLog(LOG_FATAL, "NaClDebugExceptionHandlerStandaloneMain: " "Expected 3 arguments: target_pid, socket, data\n"); } target_pid = strtol(argv[0], &rest1, 0); socket = (NaClHandle)(uintptr_t) strtol(argv[1], &rest2, 0); if (*rest1 != '\0' || *rest2 != '\0') { NaClLog(LOG_FATAL, "NaClDebugExceptionHandlerStandaloneMain: " "Bad string argument\n"); } info_size = strlen(argv[2]); if (info_size % 2 != 0) { NaClLog(LOG_FATAL, "NaClDebugExceptionHandlerStandaloneMain: " "Odd string length\n"); } info_size /= 2; info = malloc(info_size); if (info == NULL) { NaClLog(LOG_FATAL, "NaClDebugExceptionHandlerStandaloneMain: " "malloc() failed\n"); } DecodeHexString((uint8_t *) info, argv[2], info_size); if (!DebugActiveProcess(target_pid)) { NaClLog(LOG_FATAL, "NaClDebugExceptionHandlerStandaloneMain: " "Failed to attach with DebugActiveProcess()\n"); } process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_SUSPEND_RESUME | PROCESS_TERMINATE | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE | SYNCHRONIZE, /* bInheritHandle= */ FALSE, target_pid); if (process_handle == NULL) { NaClLog(LOG_FATAL, "NaClDebugExceptionHandlerStandaloneMain: " "Failed to get process handle with OpenProcess()\n"); } /* Send message to indicate that we attached to the process successfully. */ if (!WriteFile(socket, "k", 1, &written, NULL) || written != 1) { NaClLog(LOG_FATAL, "NaClDebugExceptionHandlerStandaloneMain: " "Failed to send reply\n"); } NaClDebugExceptionHandlerRun(process_handle, info, info_size); return 0; }
static void test_debug_loop(int argc, char **argv) { const char *arguments = " debugger child "; struct child_blackbox blackbox; char blackbox_file[MAX_PATH]; PROCESS_INFORMATION pi; STARTUPINFOA si; BOOL debug; DWORD pid; char *cmd; BOOL ret; if (!pDebugActiveProcessStop || !pCheckRemoteDebuggerPresent) { win_skip("DebugActiveProcessStop or CheckRemoteDebuggerPresent not available, skipping test.\n"); return; } pid = GetCurrentProcessId(); ret = DebugActiveProcess(pid); ok(!ret, "DebugActiveProcess() succeeded on own process.\n"); get_file_name(blackbox_file); cmd = HeapAlloc(GetProcessHeap(), 0, strlen(argv[0]) + strlen(arguments) + strlen(blackbox_file) + 10); sprintf(cmd, "%s%s%08x %s", argv[0], arguments, pid, blackbox_file); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); ret = CreateProcessA(NULL, cmd, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi); ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError()); HeapFree(GetProcessHeap(), 0, cmd); ret = pCheckRemoteDebuggerPresent(pi.hProcess, &debug); ok(ret, "CheckRemoteDebuggerPresent failed, last error %#x.\n", GetLastError()); ok(debug, "Expected debug != 0, got %#x.\n", debug); for (;;) { DEBUG_EVENT ev; ret = WaitForDebugEvent(&ev, INFINITE); ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError()); if (!ret) break; if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE); ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError()); if (!ret) break; } ret = CloseHandle(pi.hThread); ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError()); ret = CloseHandle(pi.hProcess); ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError()); load_blackbox(blackbox_file, &blackbox, sizeof(blackbox)); ok(!blackbox.failures, "Got %d failures from child process.\n", blackbox.failures); ret = DeleteFileA(blackbox_file); ok(ret, "DeleteFileA failed, last error %#x.\n", GetLastError()); }