/* 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)); }
/* Detach from all inferiors. */ static int win32_detach (void) { winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL; winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL; #ifdef _WIN32_WCE HMODULE dll = GetModuleHandle (_T("COREDLL.DLL")); #else HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL")); #endif DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop); DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit); if (DebugSetProcessKillOnExit == NULL || DebugActiveProcessStop == NULL) return -1; { struct thread_resume resume; resume.thread = -1; resume.step = 0; resume.sig = 0; resume.leave_stopped = 0; win32_resume (&resume); } if (!DebugActiveProcessStop (current_process_id)) return -1; DebugSetProcessKillOnExit (FALSE); win32_clear_inferiors (); return 0; }
BOOL My_DebugSetProcessKillOnExit() { BOOL KillOnExit=NULL; BOOL returnVal_Real = NULL; BOOL returnVal_Intercepted = NULL; DWORD error_Real = 0; DWORD error_Intercepted = 0; disableInterception(); returnVal_Real = DebugSetProcessKillOnExit (KillOnExit); error_Real = GetLastError(); enableInterception(); returnVal_Intercepted = DebugSetProcessKillOnExit (KillOnExit); error_Intercepted = GetLastError(); return ((returnVal_Real == returnVal_Intercepted) && (error_Real == error_Intercepted)); }
//------------------------------------------------------------------------------ // Name: DebuggerCore() // Desc: constructor //------------------------------------------------------------------------------ DebuggerCore::DebuggerCore() : page_size_(0), process_handle_(0), start_address(0), image_base(0) { DebugSetProcessKillOnExit(false); SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); page_size_ = sys_info.dwPageSize; set_debug_privilege(GetCurrentProcess(), true); // gogo magic powers }
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 spwanAndHook_(char *dlltoinject,opt *options){ STARTUPINFO sInfo; PROCESS_INFORMATION pInfo; printf("[Info] Launching process: %s\n",options->cmdline); ZeroMemory(&sInfo, sizeof(sInfo)); sInfo.cb = sizeof(sInfo); ZeroMemory(&pInfo, sizeof(pInfo)); if (CreateProcess(options->cmdline, NULL, NULL, NULL, FALSE, DEBUG_ONLY_THIS_PROCESS/*CREATE_SUSPENDED*/, NULL, NULL, &sInfo, &pInfo)) { char cmd[512]; printf("[info] New pid: %d\n",pInfo.dwProcessId); sprintf(cmd,"EXECUTING \"%s\" HOOKING PID %d",options->cmdline,pInfo.dwProcessId); logger(options->ini,"injector",cmd,strlen(cmd)); DEBUG_EVENT debugEvent; do{ // printf(">> %x\n",debugEvent.dwDebugEventCode); if(!WaitForDebugEvent(&debugEvent, 1000)) break; if(debugEvent.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT) { // SuspendThread(debugEvent.u.CreateProcessInfo.hThread); // printf("Injecting!\n"); injecta(pInfo.dwProcessId,dlltoinject,options); Sleep(1000); // ResumeThread(debugEvent.u.CreateProcessInfo.hThread); DebugSetProcessKillOnExit(FALSE); DebugActiveProcessStop(debugEvent.dwProcessId); break; } ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE); } while(1); /* if(WaitForInputIdle((void*)pInfo.hProcess,5)==WAIT_FAILED) printf("[info] Wait failed, console app? :p"); if(options->waitKeyPress){ printf("Press [intro] to resume process..\n"); getchar(); }*/ // injecta(pInfo.dwProcessId,dlltoinject,options); // ResumeThread((void*)pInfo.hThread); // WaitForInputIdle((void*)pInfo.dwProcessId,INFINITE); // Sleep(100); CloseHandle(pInfo.hThread); CloseHandle(pInfo.hProcess); }else{ printf("[Error] Unable to create the process (path not found?)\n"); } }
void CDebugger::Start() { // Reset debugger status Reset(); STARTUPINFO startInfo; PROCESS_INFORMATION processInfo; ZeroMemory(&startInfo, sizeof(startInfo)); startInfo.cb = sizeof(startInfo); ZeroMemory(&processInfo, sizeof(processInfo)); bool bSuccess = CreateProcess(m_pExePath, m_pArg, NULL, NULL, false, DEBUG_PROCESS, NULL, NULL, &startInfo, &processInfo); if (bSuccess) { cout << "[+] Start debugging process: " << m_pExePath << endl; } else { cout << "[-] Could not start debugging process: " << m_pExePath << " Error = " << GetLastError() << endl; } m_bActive = true; DebugSetProcessKillOnExit(m_bKillOnExit); return DebugLoop(); }
/* Detach from inferior PID. */ static int win32_detach (int pid) { struct process_info *process; winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL; winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL; #ifdef _WIN32_WCE HMODULE dll = GetModuleHandle (_T("COREDLL.DLL")); #else HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL")); #endif DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop); DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit); if (DebugSetProcessKillOnExit == NULL || DebugActiveProcessStop == NULL) return -1; { struct thread_resume resume; resume.thread = minus_one_ptid; resume.kind = resume_continue; resume.sig = 0; win32_resume (&resume, 1); } if (!DebugActiveProcessStop (current_process_id)) return -1; DebugSetProcessKillOnExit (FALSE); process = find_process_pid (pid); remove_process (process); win32_clear_inferiors (); 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); } }
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; }
int main(int argc, char **argv){ if( argc<2){ printf("Usage: %s <ip address>\n", argv[0]); return 1; } if( IsDebuggerPresent()){ HANDLE iphlpapi=LoadLibrary("iphlpapi.dll"); if( !iphlpapi){ perror("iphlpapi.dll"); return 1; } FARPROC IcmpSendEcho=GetProcAddress(iphlpapi, "IcmpSendEcho"); FARPROC IcmpCreateFile=GetProcAddress(iphlpapi, "IcmpCreateFile"); FARPROC IcmpCloseHandle=GetProcAddress(iphlpapi, "IcmpCloseHandle"); if( (IcmpSendEcho && IcmpCreateFile && IcmpCloseHandle)==0){ perror("icmp functions"); return 1; } unsigned long ipaddr=INADDR_NONE, params[2]; HANDLE hIcmpFile; char data[32], *reply; int replySize=sizeof(ICMP_ECHO_REPLY)+sizeof(data); if( (ipaddr=inet_addr(argv[1]))==INADDR_NONE){ perror("Illegal IP address!"); return 1; } if( (hIcmpFile=(HANDLE)IcmpCreateFile())==INVALID_HANDLE_VALUE){ perror("IcmpCreateFile"); return 1; } reply=(char *)malloc(replySize); ZeroMemory(data, sizeof(data)); params[0]=PARAM; params[1]=(unsigned long)GetProcAddress(iphlpapi, "IcmpSendEcho2Ex"); RaiseException(EXCEPTION_BREAKPOINT, 0, 2, params); puts("Exception raised!"); IcmpSendEcho(hIcmpFile, ipaddr, data, sizeof(data), NULL, reply, replySize, 1000); puts("This line should never be shown..."); IcmpCloseHandle(hIcmpFile); return 0; } PROCESS_INFORMATION pi; STARTUPINFO si; HANDLE hProcess, hThread; DEBUG_EVENT debugEvent; EXCEPTION_RECORD *ExceptionRecord=&debugEvent.u.Exception.ExceptionRecord; CONTEXT context; FARPROC IcmpSendEcho2Ex=NULL; char path[256], args[512], originalByte[1]; ZeroMemory(?, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); ZeroMemory(&debugEvent, sizeof(DEBUG_EVENT)); ZeroMemory(&context, sizeof(CONTEXT)); ZeroMemory(path, sizeof(path)); ZeroMemory(args, sizeof(args)); si.cb=sizeof(STARTUPINFO); si.dwFlags=STARTF_USESHOWWINDOW; si.wShowWindow=SW_HIDE; context.ContextFlags=CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; GetModuleFileName(NULL, path, sizeof(path)-1); snprintf(args, sizeof(args)-1, "%s %s", path, argv[1]); if( !CreateProcess( NULL, args, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, ? )){ perror("CreateProcess"); return 1; } if( (hProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId))==NULL){ perror("OpenProcess"); return 1; } HANDLE kernel32=LoadLibrary("kernel32.dll"); FARPROC DebugSetProcessKillOnExit=GetProcAddress(kernel32, "DebugSetProcessKillOnExit"); FARPROC DebugActiveProcessStop=GetProcAddress(kernel32, "DebugActiveProcessStop"); FARPROC OpenThread=GetProcAddress(kernel32, "OpenThread"); CloseHandle(kernel32); DebugSetProcessKillOnExit(TRUE); while(WaitForDebugEvent(&debugEvent, INFINITE) && debugEvent.dwDebugEventCode!=EXIT_PROCESS_DEBUG_EVENT){ if( debugEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT && ExceptionRecord->ExceptionCode==EXCEPTION_BREAKPOINT){ if( ExceptionRecord->NumberParameters>1 && ExceptionRecord->ExceptionInformation[0]==PARAM){ IcmpSendEcho2Ex=(FARPROC)ExceptionRecord->ExceptionInformation[1]; printf("IcmpSendEcho2Ex %p\n", IcmpSendEcho2Ex); if( !BreakpointSet(hProcess, IcmpSendEcho2Ex, &originalByte)){ perror("BreakpointSet"); break; } } else if( ExceptionRecord->ExceptionAddress==IcmpSendEcho2Ex){ printf("EIP %p\n", IcmpSendEcho2Ex); if( !BreakpointRetrieve(hProcess, IcmpSendEcho2Ex, &originalByte)){ perror("BreakpointRetrieve"); break; } if((hThread=(HANDLE)OpenThread(THREAD_ALL_ACCESS, FALSE, debugEvent.dwThreadId))==NULL) puts("OpenThread"); if(!GetThreadContext(hThread, &context)) puts("GetThreadContext"); context.Eip -= 1; if(!SetThreadContext(hThread, &context)) puts("SetThreadContext"); CreateThread(NULL, 0, (void *)Terminate, hProcess, 0, NULL); } } else if( debugEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT){ puts("Exception!"); DebugActiveProcessStop(debugEvent.dwProcessId); break; } ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE); ZeroMemory(&debugEvent, sizeof(DEBUG_EVENT)); } return 0; }
void DebuggerThread::run() { if ( !DebugActiveProcess( debugger->processId ) ) return; DebugSetProcessKillOnExit( FALSE ); HANDLE hImageFile = NULL; //bool go = false; //HANDLE target_thread = 0; while( !commit_suicide ) { DEBUG_EVENT dbgEvent; if ( !WaitForDebugEvent( &dbgEvent, 100 ) ) { //if ( go ) //{ // DWORD t0 = GetTickCount(); // CONTEXT threadcontext; // threadcontext.ContextFlags = CONTEXT_i386 | CONTEXT_CONTROL; // HRESULT result = SuspendThread(target_thread); // if(result == 0xffffffff) // __asm int 3 // SetThreadPriority( target_thread, THREAD_PRIORITY_TIME_CRITICAL ); // result = GetThreadContext(target_thread, &threadcontext); // SetThreadPriority( target_thread, THREAD_PRIORITY_NORMAL ); // ResumeThread(target_thread); // // DWORD t1 = GetTickCount(); // char buf[256]; // sprintf(buf, "%08x - %ims\n", t1, t1 - t0); // OutputDebugString(buf); //} DWORD err = GetLastError(); continue; } WaitForSingleObject( hMutex, INFINITE ); switch (dbgEvent.dwDebugEventCode) { case EXCEPTION_DEBUG_EVENT: SetEvent( readyEvent ); //go = true; break; case CREATE_THREAD_DEBUG_EVENT: debugger->hThreads.push_back( ThreadInfo( dbgEvent.dwThreadId, dbgEvent.u.CreateThread.hThread ) ); break; case CREATE_PROCESS_DEBUG_EVENT: debugger->hProcess = dbgEvent.u.CreateProcessInfo.hProcess; hImageFile = dbgEvent.u.CreateProcessInfo.hFile; debugger->hThreads.push_back( ThreadInfo( dbgEvent.dwThreadId, dbgEvent.u.CreateProcessInfo.hThread ) ); //target_thread = dbgEvent.u.CreateProcessInfo.hThread; break; case EXIT_THREAD_DEBUG_EVENT: // Display the thread's exit code. break; case EXIT_PROCESS_DEBUG_EVENT: // Display the process's exit code. break; case LOAD_DLL_DEBUG_EVENT: // Read the debugging information included in the newly // loaded DLL. Be sure to close the handle to the loaded DLL // with CloseHandle. break; case UNLOAD_DLL_DEBUG_EVENT: // Display a message that the DLL has been unloaded. break; case OUTPUT_DEBUG_STRING_EVENT: // Display the output debugging string. break; } ReleaseMutex( hMutex ); ContinueDebugEvent( dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED ); } if ( hImageFile ) CloseHandle( hImageFile ); DebugActiveProcessStop( debugger->processId ); }
DWORD WINAPI DebugThread(LPVOID arg) { DEBUG_EVENT evt; DWORD dwContinue; DWORD dwBPAddress = 0x44D471; DWORD dwBPEnd = 0x44D47C; DWORD dwDataRead = 0x443848; DWORD dwDataSucceed = 0x44384D; BYTE bBPAddr = 0; BYTE bBPEnd = 0; BYTE bDataRead = 0; BYTE bDataSucceed = 0; DWORD dwRead; DWORD dwDataLength = 0; //[ESP + 0x10] at 0x443848 char szName[16]; //[ESP + 0x0C] at 0x44384D char szHeader[8]; //[ESP + 0x08] at 0x44384D This value should "BSE 1.0\0" BOOL bFlag = FALSE; BOOL bFlag2 = FALSE; BOOL bAlpha = FALSE; CONTEXT lcContext; HANDLE hThread = NULL; HANDLE hProcess = NULL; LPVOID ptr, ptr2; BYTE *pBMPData; DWORD dwLength; BYTE *pData; Image *result; // SYSTEMTIME time; WCHAR str[64]; unsigned short width; unsigned short height; szName[0] = 0; if (DebugActiveProcess(dwProcessID)) SetEvent(hAttachSucceeded); SetEvent(hDebugInit); DebugSetProcessKillOnExit(FALSE); while (TRUE) { if (WaitForSingleObject(hDebugEnd, 0) == WAIT_OBJECT_0) break; dwContinue = DBG_CONTINUE; if (WaitForDebugEvent(&evt, 10)) { switch (evt.dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: bDataRead = SetSoftwareBreakpoint(evt.u.CreateProcessInfo.hProcess, dwDataRead); hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, evt.dwProcessId); CloseHandle(evt.u.CreateProcessInfo.hFile); break; case CREATE_THREAD_DEBUG_EVENT: break; case LOAD_DLL_DEBUG_EVENT: CloseHandle(evt.u.LoadDll.hFile); break; case EXCEPTION_DEBUG_EVENT: if (evt.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { if (evt.u.Exception.ExceptionRecord.ExceptionAddress == (PVOID)dwBPAddress) { // if (bFlag) // { // MessageBeep(0); bAlpha = FALSE; hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, evt.dwThreadId); lcContext.ContextFlags = CONTEXT_ALL; GetThreadContext(hThread, &lcContext); ptr = (LPVOID)(lcContext.Eax + 0x08); ReadProcessMemory(hProcess, ptr, &pBMPData, 4, &dwRead); ReadProcessMemory(hProcess, (LPVOID)pBMPData, &width, 2, &dwRead); ReadProcessMemory(hProcess, (LPVOID)(pBMPData + 2), &height, 2, &dwRead); dwLength = width * height * 4; pData = (BYTE *)calloc(dwLength, sizeof(BYTE)); if (pData) { wsprintf(str, L"[%dx%d] %S", width, height, szName); if (SendMessage(hListLayer, LB_FINDSTRINGEXACT, -1, (LPARAM)str) == LB_ERR) { SendMessage(hListLayer, LB_INSERTSTRING, 0, (LPARAM)str); ReadProcessMemory(hProcess, (LPVOID)(pBMPData + 0x10), pData, dwLength, &dwRead); result = (Image *)calloc(1, sizeof(Image)); result->width = width; result->height = height; result->data = (PIXEL *)pData; //Is this bitmap has no alpha channel (all alpha channel == 0) for (int i = 0; i < width * height; i++) if (result->data[i].a != 0x00) { bAlpha = TRUE; break; } //Set alpha channel if (!bAlpha) for (int i = 0; i < width * height; i++) result->data[i].a = 0xFF; //Insert Decoded Image to List SendMessage(hListLayer, LB_SETITEMDATA, 0, (LPARAM)result); } } MoveEIPBack(hThread); bBPEnd = SetSoftwareBreakpoint(hProcess, dwBPEnd); ResetSoftwareBreakpoint(hProcess, dwBPAddress, bBPAddr); CloseHandle(hThread); // } // else bFlag = TRUE; } else if (evt.u.Exception.ExceptionRecord.ExceptionAddress == (PVOID)dwBPEnd) { // if (bFlag2) // { hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, evt.dwThreadId); MoveEIPBack(hThread); bDataRead = SetSoftwareBreakpoint(hProcess, dwDataRead); ResetSoftwareBreakpoint(hProcess, dwBPEnd, bBPEnd); CloseHandle(hThread); // } // else bFlag2 = TRUE; } else if (evt.u.Exception.ExceptionRecord.ExceptionAddress == (PVOID)dwDataRead) { hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, evt.dwThreadId); lcContext.ContextFlags = CONTEXT_ALL; GetThreadContext(hThread, &lcContext); ptr = (LPVOID)(lcContext.Esp + 0x10); ReadProcessMemory(hProcess, ptr, &dwDataLength, 4, &dwRead); MoveEIPBack(hThread); bDataSucceed = SetSoftwareBreakpoint(hProcess, dwDataSucceed); ResetSoftwareBreakpoint(hProcess, dwDataRead, bDataRead); CloseHandle(hThread); } else if (evt.u.Exception.ExceptionRecord.ExceptionAddress == (PVOID)dwDataSucceed) { hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, evt.dwThreadId); MoveEIPBack(hThread); if (dwDataLength) { lcContext.ContextFlags = CONTEXT_ALL; GetThreadContext(hThread, &lcContext); if (lcContext.Eax == dwDataLength) { ptr = (LPVOID)(lcContext.Esp + 0x08); ReadProcessMemory(hProcess, ptr, &ptr2, 4, &dwRead); ReadProcessMemory(hProcess, ptr2, &szHeader, 8, &dwRead); if (strncmp(szHeader, "BSE 1.0\0", 8) == 0) { //Read Succeed ptr = (LPVOID)(lcContext.Esp + 0x0C); ReadProcessMemory(hProcess, ptr, &ptr2, 4, &dwRead); ReadProcessMemory(hProcess, ptr2, &szName, 16, &dwRead); bBPAddr = SetSoftwareBreakpoint(hProcess, dwBPAddress); } else bDataRead = SetSoftwareBreakpoint(hProcess, dwDataRead); } else bDataRead = SetSoftwareBreakpoint(hProcess, dwDataRead); } else bDataRead = SetSoftwareBreakpoint(hProcess, dwDataRead); ResetSoftwareBreakpoint(hProcess, dwDataSucceed, bDataSucceed); CloseHandle(hThread); } } else if (evt.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) { } else dwContinue = DBG_EXCEPTION_NOT_HANDLED; break; case EXIT_PROCESS_DEBUG_EVENT: SetEvent(hDebugEnd); break; default: dwContinue = DBG_EXCEPTION_NOT_HANDLED; break; } ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, dwContinue); } } if (bDataRead) ResetSoftwareBreakpoint(hProcess, dwDataRead, bDataRead); if (bDataSucceed) ResetSoftwareBreakpoint(hProcess, dwDataSucceed, bDataSucceed); if (bBPAddr) ResetSoftwareBreakpoint(hProcess, dwBPAddress, bBPAddr); if (bBPEnd) ResetSoftwareBreakpoint(hProcess, dwBPEnd, bBPEnd); if (hProcess) CloseHandle(hProcess); DebugActiveProcessStop(dwProcessID); return 0; }
void WINAPI EnterDebugging(DWORD dwPid) { DWORD dwAction = DBG_CONTINUE; int ret; DWORD dwAddress,dwRead; BYTE bCode[16]; ::dwPid = dwPid; DebugSetProcessKillOnExit(0); hProcess = OpenProcess(PROCESS_ALL_ACCESS,0,dwPid); if (hProcess == 0) { Log("OpenProcess[CREATE_PROCESS_DEBUG_EVENT:Pid:%d] failed:%d",dwPid,GetLastError()); ExitProcess(0); } while (WaitForDebugEvent(&dbg_event,INFINITE)) { dwAction = DBG_CONTINUE; switch (dbg_event.dwDebugEventCode) { case CREATE_PROCESS_DEBUG_EVENT: Log("CREATE_PROCESS_DEBUG_EVENT:Base:%x OEP:%x",dbg_event.u.CreateProcessInfo.lpBaseOfImage,dbg_event.u.CreateProcessInfo.lpStartAddress); create_process_handler((DWORD) dbg_event.u.CreateProcessInfo.lpBaseOfImage,(DWORD)dbg_event.u.CreateProcessInfo.lpStartAddress); Load_Dll_Event(dbg_event.u.CreateProcessInfo.hFile,(DWORD)dbg_event.u.CreateProcessInfo.lpBaseOfImage); hProcess = OpenProcess(PROCESS_ALL_ACCESS,0,dwPid); if (hProcess == 0) { Log("OpenProcess[CREATE_PROCESS_DEBUG_EVENT:Pid:%d] failed:%d",dwPid,GetLastError()); ExitProcess(0); } break; case CREATE_THREAD_DEBUG_EVENT: Log("Thread starting... entry point:%x[ht:%x:id:%d] ",dbg_event.u.CreateThread.lpStartAddress,dbg_event.u.CreateThread.hThread,dbg_event.dwThreadId); createthread_handler((DWORD)dbg_event.u.CreateThread.lpStartAddress,(DWORD)dbg_event.dwThreadId); break; case EXCEPTION_DEBUG_EVENT: Log("EXCEPTION_DEBUG_EVENT(%x) fc:%x address:0x%x code:0x%x",EXCEPTION_DEBUG_EVENT,dbg_event.u.Exception.dwFirstChance,dbg_event.u.Exception.ExceptionRecord.ExceptionAddress,dbg_event.u.Exception.ExceptionRecord.ExceptionCode); dwAction = DBG_EXCEPTION_NOT_HANDLED; switch(dbg_event.u.Exception.ExceptionRecord.ExceptionCode) { case EXCEPTION_INVALID_HANDLE: Log("EXCEPTION_INVALID_HANDLE"); break; case EXCEPTION_BREAKPOINT: dwAddress = (DWORD)dbg_event.u.Exception.ExceptionRecord.ExceptionAddress; ret = breakpoint_handler(dwAddress,dbg_event.dwThreadId); Log("BP exception at:%x ret:%x",dwAddress,ret); dwAction = ret; break; case EXCEPTION_SINGLE_STEP: Log("EXCEPTION_SINGLE_STEP:%x ",dbg_event.u.Exception.ExceptionRecord.ExceptionAddress); ReadProcessMemory(hProcess,dbg_event.u.Exception.ExceptionRecord.ExceptionAddress,bCode,16,&dwRead); singlestep_handler((DWORD)dbg_event.u.Exception.ExceptionRecord.ExceptionAddress,bCode,dbg_event.dwThreadId); dwAction = DBG_CONTINUE; break; } break; case EXIT_PROCESS_DEBUG_EVENT: Log("EXIT_PROCESS_DEBUG_EVENT"); return; case EXIT_THREAD_DEBUG_EVENT: Log("Thread exiting... entry point:%x ",dbg_event.u.CreateThread.lpStartAddress); break; case LOAD_DLL_DEBUG_EVENT: Log("LOAD_DLL_DEBUG_EVENT:base:0x%x handle:0x%x",dbg_event.u.LoadDll.lpBaseOfDll,dbg_event.u.LoadDll.hFile); Load_Dll_Event(dbg_event.u.LoadDll.hFile,(DWORD)dbg_event.u.LoadDll.lpBaseOfDll); break; case OUTPUT_DEBUG_STRING_EVENT: Log("OUTPUT_DEBUG_STRING_EVENT"); break; case RIP_EVENT: Log("RIP_EVENT"); break; case UNLOAD_DLL_DEBUG_EVENT: Log("UNLOAD_DLL_DEBUG_EVENT:%x",dbg_event.u.UnloadDll.lpBaseOfDll); unload_dll_handler((DWORD)dbg_event.u.UnloadDll.lpBaseOfDll); break; } ContinueDebugEvent(dwPid,dbg_event.dwThreadId,dwAction); } return; }