關於在Windows 8.1預覽版上OD無法啟動程式進行除錯的問題
阿新 • • 發佈:2019-02-15
在Windows 8.1 Preview x64上,OllyDbg如果試圖啟動一個程式進行除錯,會出現一個死在ntdll.RtlUserThreadStart的單步異常:
這個問題其實是由核心在建立程序時引發的,核心如何做的我沒仔細看,就在建立程序後,核心把LdrInitializeThunk中執行ZwContinue的CONTEXT結構體的EFlags設定加上了TF(單步)標誌,使得ZwContinue設定CONTEXT跑去執行RtlUserThreadStart的一條指令後就中斷了,而又沒有異常處理去Skip這個異常,就出現了無法除錯的問題。
修復這個問題很簡單,設定OD停在系統斷點,然後把ZwContinue的CONTEXT中的EFlags改成202而不是預設的302即可,如下圖:
這樣F9後就能停在入口點了。還是希望8.1的RTM能修復這個問題。
還有大家需要注意下目前x64上32位程式在切核心時跟x86的異同。
x86:
x64的32位程式:
把下面這份程式碼編譯成Dll放到OD的外掛目錄讓OD載入可以修復這個問題。
#include <Windows.h> typedef BOOL (WINAPI* fnWaitForDebugEvent)(LPDEBUG_EVENT,DWORD); typedef HWND (WINAPI *fnCreateWindowExA)(DWORD,LPCSTR,LPCSTR,DWORD,INT,INT,INT,INT,HWND,HMENU,HINSTANCE,LPVOID); PVOID pfnWaitForDebugEvent; PVOID pfnCreateWindowExA; HWND WINAPI _CreateWindowExA(DWORD dwExStyle,LPCSTR lpClassName,LPCSTR lpWindowName,DWORD dwStyle,INT x,INT y,INT nWidth,INT nHeight,HWND hWndParent,HMENU hMenu,HINSTANCE hInstance,LPVOID lpParam) { register HWND hWnd = ((fnCreateWindowExA)pfnCreateWindowExA)(dwExStyle,lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam); if (IsWindow(hWnd)) { ChangeWindowMessageFilterEx(hWnd,WM_DROPFILES,MSGFLT_ALLOW,NULL); ChangeWindowMessageFilterEx(hWnd,WM_COPYDATA,MSGFLT_ALLOW,NULL); ChangeWindowMessageFilterEx(hWnd,WM_USER,MSGFLT_ALLOW,NULL); } return hWnd; } BOOL WINAPI _WaitForDebugEvent(LPDEBUG_EVENT lpDebugEvent,DWORD dwMilliseconds) { register BOOL bResult = ((fnWaitForDebugEvent)pfnWaitForDebugEvent)(lpDebugEvent,dwMilliseconds); if (lpDebugEvent->dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { if (lpDebugEvent->u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP && lpDebugEvent->u.Exception.dwFirstChance == 0 && lpDebugEvent->u.Exception.ExceptionRecord.ExceptionAddress == (PVOID)((DWORD)GetProcAddress(GetModuleHandle("ntdll.dll"),"RtlUserThreadStart") + 4)) { ContinueDebugEvent(lpDebugEvent->dwProcessId,lpDebugEvent->dwThreadId,DBG_CONTINUE); bResult = FALSE; } } return bResult; } BOOL WINAPI DllMain(HINSTANCE hDllInst,DWORD dwReason,LPVOID pvReserved) { if (dwReason == DLL_PROCESS_ATTACH) { typedef NTSTATUS (NTAPI* fnLdrAddRefDll)(ULONG,PVOID); ((fnLdrAddRefDll)GetProcAddress(GetModuleHandle("ntdll.dll"),"LdrAddRefDll"))(0,hDllInst); DisableThreadLibraryCalls(hDllInst); BOOL bWow64 = FALSE; IsWow64Process((HANDLE)-1,&bWow64); register DWORD dwWaitForDebugEvent = (UINT_PTR)GetModuleHandle(NULL) + 0x3961E; register DWORD dwCreateWindowExA = (UINT_PTR)GetModuleHandle(NULL) + 0xAF39E; DWORD dwOldProtect; VirtualProtect((PVOID)dwWaitForDebugEvent,4,PAGE_EXECUTE_READWRITE,&dwOldProtect); pfnWaitForDebugEvent = (PVOID)(*(PDWORD)dwWaitForDebugEvent + dwWaitForDebugEvent + sizeof(DWORD)); if (bWow64) *(PDWORD)dwWaitForDebugEvent = (DWORD)&_WaitForDebugEvent - dwWaitForDebugEvent - sizeof(DWORD); VirtualProtect((PVOID)dwWaitForDebugEvent,4,dwOldProtect,&dwOldProtect); pfnCreateWindowExA = (PVOID)(*(PDWORD)(*(PDWORD)dwCreateWindowExA)); VirtualProtect((PVOID)(*(PDWORD)dwCreateWindowExA),4,PAGE_READWRITE,&dwOldProtect); *(PDWORD)(*(PDWORD)dwCreateWindowExA) = (DWORD)&_CreateWindowExA; VirtualProtect((PVOID)(*(PDWORD)dwCreateWindowExA),4,dwOldProtect,&dwOldProtect); ChangeWindowMessageFilterEx(*(HWND*)0x4D3B7C,WM_DROPFILES,MSGFLT_ALLOW,NULL); ChangeWindowMessageFilterEx(*(HWND*)0x4D3B7C,WM_COPYDATA,MSGFLT_ALLOW,NULL); ChangeWindowMessageFilterEx(*(HWND*)0x4D3B80,WM_DROPFILES,MSGFLT_ALLOW,NULL); ChangeWindowMessageFilterEx(*(HWND*)0x4D3B80,WM_COPYDATA,MSGFLT_ALLOW,NULL); ChangeWindowMessageFilterEx(*(HWND*)0x4CD6A0,WM_DROPFILES,MSGFLT_ALLOW,NULL); ChangeWindowMessageFilterEx(*(HWND*)0x4CD6A0,WM_COPYDATA,MSGFLT_ALLOW,NULL); } return TRUE; }