1. 程式人生 > >關於在Windows 8.1預覽版上OD無法啟動程式進行除錯的問題

關於在Windows 8.1預覽版上OD無法啟動程式進行除錯的問題

在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;
}