NTSTATUS NTAPI DbgUiConnectToDbg(VOID) { OBJECT_ATTRIBUTES ObjectAttributes; /* Don't connect twice */ if (NtCurrentTeb()->DbgSsReserved[1]) return STATUS_SUCCESS; /* Setup the Attributes */ InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, 0); /* Create the object */ return ZwCreateDebugObject(&NtCurrentTeb()->DbgSsReserved[1], DEBUG_OBJECT_ALL_ACCESS, &ObjectAttributes, TRUE); }
NTSTATUS NTAPI DbgUiDebugActiveProcess(IN HANDLE Process) { NTSTATUS Status; /* Tell the kernel to start debugging */ Status = NtDebugActiveProcess(Process, NtCurrentTeb()->DbgSsReserved[1]); if (NT_SUCCESS(Status)) { /* Now break-in the process */ Status = DbgUiIssueRemoteBreakin(Process); if (!NT_SUCCESS(Status)) { /* We couldn't break-in, cancel debugging */ DbgUiStopDebugging(Process); } } /* Return status */ return Status; } NTSTATUS NTAPI DbgUiStopDebugging(IN HANDLE Process) { /* Call the kernel to remove the debug object */ return NtRemoveProcessDebug(Process, NtCurrentTeb()->DbgSsReserved[1]); }
NTSTATUS NTAPI DbgUiIssueRemoteBreakin(IN HANDLE Process) { HANDLE hThread; CLIENT_ID ClientId; NTSTATUS Status; /* Create the thread that will do the breakin */ Status = RtlCreateUserThread(Process, NULL, FALSE, 0, 0, PAGE_SIZE, (PVOID)DbgUiRemoteBreakin, NULL, &hThread, &ClientId); /* Close the handle on success */ if(NT_SUCCESS(Status)) NtClose(hThread); /* Return status */ return Status; }
VOID NTAPI DbgUiRemoteBreakin(VOID) { /* Make sure a debugger is enabled; if so, breakpoint */ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint(); /* Exit the thread */ RtlExitUserThread(STATUS_SUCCESS); }
HANDLE NTAPI DbgUiGetThreadDebugObject(VOID) { /* Just return the handle from the TEB */ return NtCurrentTeb()->DbgSsReserved[1]; } VOID NTAPI DbgUiSetThreadDebugObject(HANDLE DebugObject) { /* Just set the handle in the TEB */ NtCurrentTeb()->DbgSsReserved[1] = DebugObject; }
NTSTATUS NTAPI DbgUiContinue(IN PCLIENT_ID ClientId, IN NTSTATUS ContinueStatus) { /* Tell the kernel object to continue */ return ZwDebugContinue(NtCurrentTeb()->DbgSsReserved[1], ClientId, ContinueStatus); } NTSTATUS NTAPI DbgUiWaitStateChange(OUT PDBGUI_WAIT_STATE_CHANGE DbgUiWaitStateCange, IN PLARGE_INTEGER TimeOut OPTIONAL) { /* Tell the kernel to wait */ return NtWaitForDebugEvent(NtCurrentTeb()->DbgSsReserved[1], TRUE, TimeOut, DbgUiWaitStateCange); }
// // User-Mode Debug State Change Structure // typedef struct _DBGUI_WAIT_STATE_CHANGE { DBG_STATE NewState; CLIENT_ID AppClientId; union { struct { HANDLE HandleToThread; DBGKM_CREATE_THREAD NewThread; } CreateThread; struct { HANDLE HandleToProcess; HANDLE HandleToThread; DBGKM_CREATE_PROCESS NewProcess; } CreateProcessInfo; DBGKM_EXIT_THREAD ExitThread; DBGKM_EXIT_PROCESS ExitProcess; DBGKM_EXCEPTION Exception; DBGKM_LOAD_DLL LoadDll; DBGKM_UNLOAD_DLL UnloadDll; } StateInfo; } DBGUI_WAIT_STATE_CHANGE, *PDBGUI_WAIT_STATE_CHANGE;
// // Debug States // typedef enum _DBG_STATE { DbgIdle, DbgReplyPending, DbgCreateThreadStateChange, DbgCreateProcessStateChange, DbgExitThreadStateChange, DbgExitProcessStateChange, DbgExceptionStateChange, DbgBreakpointStateChange, DbgSingleStepStateChange, DbgLoadDllStateChange, DbgUnloadDllStateChange } DBG_STATE, *PDBG_STATE;
// // Debug Message Structures // typedef struct _DBGKM_EXCEPTION { EXCEPTION_RECORD ExceptionRecord; ULONG FirstChance; } DBGKM_EXCEPTION, *PDBGKM_EXCEPTION; typedef struct _DBGKM_CREATE_THREAD { ULONG SubSystemKey; PVOID StartAddress; } DBGKM_CREATE_THREAD, *PDBGKM_CREATE_THREAD; typedef struct _DBGKM_CREATE_PROCESS { ULONG SubSystemKey; HANDLE FileHandle; PVOID BaseOfImage; ULONG DebugInfoFileOffset; ULONG DebugInfoSize; DBGKM_CREATE_THREAD InitialThread; } DBGKM_CREATE_PROCESS, *PDBGKM_CREATE_PROCESS; typedef struct _DBGKM_EXIT_THREAD { NTSTATUS ExitStatus; } DBGKM_EXIT_THREAD, *PDBGKM_EXIT_THREAD; typedef struct _DBGKM_EXIT_PROCESS { NTSTATUS ExitStatus; } DBGKM_EXIT_PROCESS, *PDBGKM_EXIT_PROCESS; typedef struct _DBGKM_LOAD_DLL { HANDLE FileHandle; PVOID BaseOfDll; ULONG DebugInfoFileOffset; ULONG DebugInfoSize; PVOID NamePointer; } DBGKM_LOAD_DLL, *PDBGKM_LOAD_DLL; typedef struct _DBGKM_UNLOAD_DLL { PVOID BaseAddress; } DBGKM_UNLOAD_DLL, *PDBGKM_UNLOAD_DLL;
NTSTATUS NTAPI DbgUiConvertStateChangeStructure(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange, OUT PVOID Win32DebugEvent) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; THREAD_BASIC_INFORMATION ThreadBasicInfo; LPDEBUG_EVENT DebugEvent = Win32DebugEvent; HANDLE ThreadHandle; /* Write common data */ DebugEvent->dwProcessId = (DWORD)WaitStateChange-> AppClientId.UniqueProcess; DebugEvent->dwThreadId = (DWORD)WaitStateChange->AppClientId.UniqueThread; /* Check what kind of even this is */ switch (WaitStateChange->NewState) { /* New thread */ case DbgCreateThreadStateChange: /* Setup Win32 code */ DebugEvent->dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT; /* Copy data over */ DebugEvent->u.CreateThread.hThread = WaitStateChange->StateInfo.CreateThread.HandleToThread; DebugEvent->u.CreateThread.lpStartAddress = WaitStateChange->StateInfo.CreateThread.NewThread.StartAddress; /* Query the TEB */ Status = NtQueryInformationThread(WaitStateChange->StateInfo. CreateThread.HandleToThread, ThreadBasicInformation, &ThreadBasicInfo, sizeof(ThreadBasicInfo), NULL); if (!NT_SUCCESS(Status)) { /* Failed to get PEB address */ DebugEvent->u.CreateThread.lpThreadLocalBase = NULL; } else { /* Write PEB Address */ DebugEvent->u.CreateThread.lpThreadLocalBase = ThreadBasicInfo.TebBaseAddress; } break; /* New process */ case DbgCreateProcessStateChange: /* Write Win32 debug code */ DebugEvent->dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT; /* Copy data over */ DebugEvent->u.CreateProcessInfo.hProcess = WaitStateChange->StateInfo.CreateProcessInfo.HandleToProcess; DebugEvent->u.CreateProcessInfo.hThread = WaitStateChange->StateInfo.CreateProcessInfo.HandleToThread; DebugEvent->u.CreateProcessInfo.hFile = WaitStateChange->StateInfo.CreateProcessInfo.NewProcess. FileHandle; DebugEvent->u.CreateProcessInfo.lpBaseOfImage = WaitStateChange->StateInfo.CreateProcessInfo.NewProcess. BaseOfImage; DebugEvent->u.CreateProcessInfo.dwDebugInfoFileOffset = WaitStateChange->StateInfo.CreateProcessInfo.NewProcess. DebugInfoFileOffset; DebugEvent->u.CreateProcessInfo.nDebugInfoSize = WaitStateChange->StateInfo.CreateProcessInfo.NewProcess. DebugInfoSize; DebugEvent->u.CreateProcessInfo.lpStartAddress = WaitStateChange->StateInfo.CreateProcessInfo.NewProcess. InitialThread.StartAddress; /* Query TEB address */ Status = NtQueryInformationThread(WaitStateChange->StateInfo. CreateProcessInfo.HandleToThread, ThreadBasicInformation, &ThreadBasicInfo, sizeof(ThreadBasicInfo), NULL); if (!NT_SUCCESS(Status)) { /* Failed to get PEB address */ DebugEvent->u.CreateThread.lpThreadLocalBase = NULL; } else { /* Write PEB Address */ DebugEvent->u.CreateThread.lpThreadLocalBase = ThreadBasicInfo.TebBaseAddress; } /* Clear image name */ DebugEvent->u.CreateProcessInfo.lpImageName = NULL; DebugEvent->u.CreateProcessInfo.fUnicode = TRUE; break; /* Thread exited */ case DbgExitThreadStateChange: /* Write the Win32 debug code and the exit status */ DebugEvent->dwDebugEventCode = EXIT_THREAD_DEBUG_EVENT; DebugEvent->u.ExitThread.dwExitCode = WaitStateChange->StateInfo.ExitThread.ExitStatus; break; /* Process exited */ case DbgExitProcessStateChange: /* Write the Win32 debug code and the exit status */ DebugEvent->dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT; DebugEvent->u.ExitProcess.dwExitCode = WaitStateChange->StateInfo.ExitProcess.ExitStatus; break; /* Any sort of exception */ case DbgExceptionStateChange: case DbgBreakpointStateChange: case DbgSingleStepStateChange: /* Check if this was a debug print */ if (WaitStateChange->StateInfo.Exception.ExceptionRecord. ExceptionCode == DBG_PRINTEXCEPTION_C) { /* Set the Win32 code */ DebugEvent->dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT; /* Copy debug string information */ DebugEvent->u.DebugString.lpDebugStringData = (PVOID)WaitStateChange-> StateInfo.Exception.ExceptionRecord. ExceptionInformation[1]; DebugEvent->u.DebugString.nDebugStringLength = WaitStateChange->StateInfo.Exception.ExceptionRecord. ExceptionInformation[0]; DebugEvent->u.DebugString.fUnicode = FALSE; } else if (WaitStateChange->StateInfo.Exception.ExceptionRecord. ExceptionCode == DBG_RIPEXCEPTION) { /* Set the Win32 code */ DebugEvent->dwDebugEventCode = RIP_EVENT; /* Set exception information */ DebugEvent->u.RipInfo.dwType = WaitStateChange->StateInfo.Exception.ExceptionRecord. ExceptionInformation[1]; DebugEvent->u.RipInfo.dwError = WaitStateChange->StateInfo.Exception.ExceptionRecord. ExceptionInformation[0]; } else { /* Otherwise, this is a debug event, copy info over */ DebugEvent->dwDebugEventCode = EXCEPTION_DEBUG_EVENT; DebugEvent->u.Exception.ExceptionRecord = WaitStateChange->StateInfo.Exception.ExceptionRecord; DebugEvent->u.Exception.dwFirstChance = WaitStateChange->StateInfo.Exception.FirstChance; } break; /* DLL Load */ case DbgLoadDllStateChange : /* Set the Win32 debug code */ DebugEvent->dwDebugEventCode = LOAD_DLL_DEBUG_EVENT; /* Copy the rest of the data */ DebugEvent->u.LoadDll.lpBaseOfDll = WaitStateChange->StateInfo.LoadDll.BaseOfDll; DebugEvent->u.LoadDll.hFile = WaitStateChange->StateInfo.LoadDll.FileHandle; DebugEvent->u.LoadDll.dwDebugInfoFileOffset = WaitStateChange->StateInfo.LoadDll.DebugInfoFileOffset; DebugEvent->u.LoadDll.nDebugInfoSize = WaitStateChange->StateInfo.LoadDll.DebugInfoSize; /* Open the thread */ InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); Status = NtOpenThread(&ThreadHandle, THREAD_QUERY_INFORMATION, &ObjectAttributes, &WaitStateChange->AppClientId); if (NT_SUCCESS(Status)) { /* Query thread information */ Status = NtQueryInformationThread(ThreadHandle, ThreadBasicInformation, &ThreadBasicInfo, sizeof(ThreadBasicInfo), NULL); NtClose(ThreadHandle); } /* Check if we got thread information */ if (NT_SUCCESS(Status)) { /* Save the image name from the TIB */ DebugEvent->u.LoadDll.lpImageName = &((PTEB)ThreadBasicInfo.TebBaseAddress)-> Tib.ArbitraryUserPointer; } else { /* Otherwise, no name */ DebugEvent->u.LoadDll.lpImageName = NULL; } /* It's Unicode */ DebugEvent->u.LoadDll.fUnicode = TRUE; break; /* DLL Unload */ case DbgUnloadDllStateChange: /* Set Win32 code and DLL Base */ DebugEvent->dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT; DebugEvent->u.UnloadDll.lpBaseOfDll = WaitStateChange->StateInfo.UnloadDll.BaseAddress; break; /* Anything else, fail */ default: return STATUS_UNSUCCESSFUL; } /* Return success */ return STATUS_SUCCESS; }
There are 31,320 total registered users.
[+] expand