# Anti-debug.Object handles & exception (p2) Kiểm tra kernel objects handles để phát hiện. ## 1. OpenProcess/ntdll!NtOpenProcess Một process mặc định không bị debug sẽ không có quyền `SeDebugPrivilege` trong access token của nó. Tuy nhiên, quyền `SeDebugPrivilege` sẽ được bật bởi trình debugger như OllyDbg hay WinDbg. Do đó, nếu process có thể mở tiến trình **csrss.exe**, cũng tức là có quyền `SeDebugPrivilege` trong access token, hay prcess đó đang bị debug. Với tham số là PID của tiến trình **csrss.exe**. > NOTE: Chỉ thành công khi chạy dưới quyền của nhóm administrators và debug privileges. > ```cpp= HMODULE hNtDll = LoadLibrary(TEXT("ntdll.dll")); if (hNtDll) { typedef DWORD(WINAPI* TCsrGetProcessId)(VOID); // get PID of csrss.exe TCsrGetProcessId pfnCsrGetProcessId = (TCsrGetProcessId) GetProcAddress(hNtDll, "CsrGetProcessId"); if (pfnCsrGetProcessId) { HANDLE hCsr = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pfnCsrGetProcessId()); if (hCsr != NULL) { CloseHandle(hCsr); return true; } else return false; } } ``` ## 2. CloseHandle Gọi NtClose hay CloseHandle với một handle không hợp lệ để tạo một exception EXCEPTION_INVALID_HANDLE (0xC0000008). Nếu luồng được truyền cho exception handler, chứng tỏ rằng tiến trình đang bị debug. ```cpp= __try { CloseHandle((HANDLE)0xDEADBEEF); return false; } __except(GetExceptionCode() == 0xC0000008 ? 1 : 0) { // exception handler return true; } ``` ```yaml # yara strings: $1 = "NtClose" fullword ascii $2 = "CloseHandle" fullword ascii ``` ## 3. LoadLibrary tương tự như OpenFile. Khi một file được load sử dụng kernel32!LoadLibrary (ntdll!LdrLoadDll). Handle của loaded file sẽ được mở và lưu trong [LOAD_DLL_DEBUG_INFO](https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-load_dll_debug_info) struct. Nếu handle này không được close bởi debbuger, file này sẽ không thể open. Ta sẽ load file bất kỳ sử dụng LoadLibrary và cố găng mở file sử dụng CreateFile. Nếu CreateFile lỗi -> có sự hiện diện của debugger. ```cpp= TCHAR filePath[] = L"C:\\Windows\\System32\\calc.exe"; LoadLibrary(filePath); return INVALID_HANDLE_VALUE == CreateFile(filePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); ``` ## 4. NtQueryObject Khi debugging session bắt đầu, một kernel object được gọi là "debug object" được tạo ra, và một handle tương ứng với object đó. Sử dụng ntdll!NtQueryObject để truy vấn đến list các objects tồn tại, và kiểm tra số lượng handles tương ứng với debug object tồn tại. ``` 1. Lấy list chứa thông tin các objects tồn tại 2. Sử dụng loop đẻ tìm `DebugObject`. kiểm tra số lượng handle > 0 -> đang bị debug. ``` ## Bypass: - Trace đến hàm check: - skip bằng cách set IP register. - patch thành NOPS. - Thay đổi flag check. - Hook các hàm và thay đổi giá trị trả về: - ntdll!OpenProcess: trả về NULL nếu tham số thứ 3 là csrss.exe. - ntdll!NtQueryObject: Nếu tham số thứ 2 là ObjectAllTypesInformation (3). - LoadLibrary quite hard to bypass :< # Exceptions: ## 1. UnhandledExceptionFilter: Khi xảy ra exception và không có Exception Handlers (cả Structured lẫn Vectored). Hàm UnhandledExceptionFilter sẽ được gọi. Có thể đăng ký một custom unhandled exception filter dùng kernel32!SetUnhandledExceptionFilter(). Nhưng nếu chương trình chạy dưởi một debugger, **custom filter sẽ không được gọi và exception được truyền tiếp cho debugger**. ```cpp= LONG unhandle_exception_filter(PEXCEPTION_POINTERS pExceptionInfo) { PCONTEXT ctx = pExceptionInfo->ContextRecord; ctx->Eip += 3; // Skip \xCC\xEB\x?? return EXCEPTION_CONTINUE_EXECUTION; } bool check_UnhandledExceptionFilter() { bool bDebugged = true; SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)unhandle_exception_filter); __asm { int 3 // CC jmp near being_debugged // EB ?? } bDebugged = false; being_debugged: return bDebugged; } ``` ## 2. RaiseException/ ntdll!RtlRaiseException Các exception như **DBC_CONTROL_C** (0x40010005) hay **DBG_RIPEVENT** (0x40010007) không được chuyển tiếp đến exception handlers của tiến trình hiện tại mà được xử lí bởi debugger. Sử dụng kernel32!RaiseException để ép xảy ra một exception cụ thể. Nếu exception handle không được gội -> có sự tồn tại của debugger. ## 3. Ẩn luồng chương trình với Exception Handlers Tạo một exception handler (structured hay vectored), raise exception và handler tương ứng sẽ tới gọi tới khác. ###### tags: `windows-internal` `rev` `anti-debug`