关于在Windows 8.1预览版上OD无法启动程序进行调试的问题

在Windows 8.1 Preview x64上,OllyDbg如果试图启动一个程序进行调试,会出现一个死在ntdll.RtlUserThreadStart的单步异常:

关于在Windows 8.1预览版上OD无法启动程序进行调试的问题_第1张图片

这个问题其实是由内核在创建进程时引发的,内核如何做的我没仔细看,就在创建进程后,内核把LdrInitializeThunk中执行ZwContinue的CONTEXT结构体的EFlags设置加上了TF(单步)标志,使得ZwContinue设置CONTEXT跑去执行RtlUserThreadStart的一条指令后就中断了,而又没有异常处理去Skip这个异常,就出现了无法调试的问题。
修复这个问题很简单,设置OD停在系统断点,然后把ZwContinue的CONTEXT中的EFlags改成202而不是默认的302即可,如下图:

关于在Windows 8.1预览版上OD无法启动程序进行调试的问题_第2张图片
这样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;
}

你可能感兴趣的:(关于在Windows 8.1预览版上OD无法启动程序进行调试的问题)