我有一个第三方内核模式驱动程序,由我用C ++编写的Windows服务控制。服务初始化代码似乎运行得很好,但是当运行服务线程时,它会遇到一个异常,表明堆栈或堆损坏(根据调试的情况而有所不同)。例外情况发生在“不在任何已加载模块中”的地址中,因此几乎不可能分辨出发生了什么。使用应用程序验证程序作为管理员在windbg中运行,在分析-v:
之后给出Breakpoint 0 hit
eax=001ffb04 ebx=7ffda000 ecx=001ffb04 edx=002e1b34 esi=00000000 edi=001ff8a4
eip=00282051 esp=001ff76c ebp=001ff8b4 iopl=0 nv up ei ng nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000282
MyService!CServiceBase::Run+0x71:
00282051 8bf4 mov esi,esp
0:000> g
Detected memory leaks!
Dumping objects ->
{53} normal block at 0x058BFFF0, 8 bytes long.
Data: < ( > C0 15 28 00 04 FB 1F 00
Object dump complete.
(4e6c.4e9c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=7ffda000 ecx=bffefce9 edx=002f8950 esi=00000000 edi=001ff8a4
eip=bfe1045d esp=001ff778 ebp=001ff8b4 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246
bfe1045d ?? ???
_crtdbg“内存泄漏”我认为是在服务初始化期间分配的对象,在服务停止之前不会被释放。
0:000> !analyze -v
*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************
Current verifier stop:
APPLICATION_VERIFIER_LUAPRIV_OK_OBJECT_DUMP (3317)
The application was able to access the object's security descriptor.
The application was granted the requested access to this object. A standard user should also be able to access this object.
Arguments:
Arg1: 6d101d5c, Object Name
Arg2: 0012019f, Access Requested
Arg3: 05156f60, Security Descriptor
Arg4: 05986fa0, String Security Descriptor
Previous verifier stop:
APPLICATION_VERIFIER_LUAPRIV_OK_OBJECT_GRANT (331e)
Safe Object.
The application opened an object (such as a file or registry key) and requested access that is granted to at least one non-privileged entity (listed). This suggests that the same operation will work when attempted by non-privileged/standard users.
Arguments:
Arg1: 6d101d5c, Object Type
Arg2: 05148fd8, Object Name
Arg3: 05156f8c, Access Control Entry
Arg4: 00000000, N/A
*** WARNING: Unable to verify checksum for ...nfapi.dll
FAULTING_IP:
+0
bfe1045d ?? ???
EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: bfe1045d
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000000
Parameter[1]: bfe1045d
Attempt to read from address bfe1045d
FAULTING_THREAD: 00004e9c
DEFAULT_BUCKET_ID: BAD_INSTRUCTION_PTR
PROCESS_NAME: MyService.exe
ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.
EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.
EXCEPTION_PARAMETER1: 00000000
EXCEPTION_PARAMETER2: bfe1045d
READ_ADDRESS: bfe1045d
FOLLOWUP_IP:
MyService!main+71 [.....svc.cpp @ 51]
00282d81 83c404 add esp,4
FAILED_INSTRUCTION_ADDRESS:
+9
bfe1045d ?? ???
NTGLOBALFLAG: 2000100
APPLICATION_VERIFIER_FLAGS: 80c43267
APP: myservice.exe
IP_ON_HEAP: 7ffda000
The fault address in not in any loaded module, please check your build's rebase
log at <releasedir>\bin\build_logs\timebuild\ntrebase.log for module which may
contain the address if it were loaded.
PRIMARY_PROBLEM_CLASS: BAD_INSTRUCTION_PTR
BUGCHECK_STR: APPLICATION_FAULT_BAD_INSTRUCTION_PTR_INVALID_POINTER_READ
FRAME_ONE_INVALID: 1
LAST_CONTROL_TRANSFER: from 7ffda000 to bfe1045d
STACK_TEXT:
WARNING: Frame IP not in any known module. Following frames may be wrong.
001ff774 7ffda000 cccccccc cccccccc cccccccc 0xbfe1045d
001ff8b4 00282d81 001ffb04 bfe107a5 00000000 0x7ffda000
001ffb4c 002aac69 00000001 05868fa8 0586af60 MyService!main+0x71
001ffb98 002aab2f 001ffbac 75fbd2e9 7ffda000 MyService!__tmainCRTStartup+0x129
001ffba0 75fbd2e9 7ffda000 001ffbec 77691603 MyService!mainCRTStartup+0xf
001ffbac 77691603 7ffda000 762ef334 00000000 KERNEL32!BaseThreadInitThunk+0xe
001ffbec 776915d6 002aab20 7ffda000 00000000 ntdll!__RtlUserThreadStart+0x23
001ffc04 00000000 002aab20 7ffda000 00000000 ntdll!_RtlUserThreadStart+0x1b
FAULTING_SOURCE_LINE: .....svc.cpp
FAULTING_SOURCE_FILE: .....svc.cpp
FAULTING_SOURCE_LINE_NUMBER: 51
FAULTING_SOURCE_CODE:
47: {
48: try
49: {
50: CSampleService service(SVCNAME, TRUE, TRUE, TRUE);
> 51: if (!CServiceBase::Run(service))
52: {
53: printf("Service failed to run w/err 0x%08lx\n", GetLastError());
54: }
55: return 0;
56: } catch (char *str )
SYMBOL_STACK_INDEX: 2
SYMBOL_NAME: myservice!main+71
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: MyService
IMAGE_NAME: MyService.exe
DEBUG_FLR_IMAGE_TIMESTAMP: 530b8caa
STACK_COMMAND: ~0s ; kb
FAILURE_BUCKET_ID: BAD_INSTRUCTION_PTR_c0000005_MyService.exe!main
BUCKET_ID: APPLICATION_FAULT_BAD_INSTRUCTION_PTR_INVALID_POINTER_READ_BAD_IP_myservice!main+71
Followup: MachineOwner
---------
这里的困难是Windows服务启动代码无法直接调试,您必须跳过服务启动代码并进入初始化代码。服务启动后,您可以附加到要调试的进程,但是在服务成功启动之后但在初始化代码完成之后抛出此异常。如果我超过初始化代码的结尾,调用堆栈只是十六进制地址,代码是在ntdll.dll中汇编。我可以看到内存中的某些内容已被破坏,后来在服务运行中使用但我无法检测到这是什么,所有本地和全局变量在初始化代码中看起来都是正确的。第三方代码作为exe成功运行,如果我不调用第三方代码,服务将成功启动。 从命令行运行时,服务启动超时,如果发生异常,则可能会发生。
int main(int argc, char *argv[])
{
try
{
CSampleService service(SVCNAME, TRUE, TRUE, TRUE);
if (!CServiceBase::Run(service))
{
printf("Service failed to run w/err 0x%08lx\n", GetLastError());
}
return;
} catch (char *str )
{
char sMessage[MAX_PATH];
sprintf_s(sMessage,"Service failed to run, exception=%s", str);
SvcReportEvent(sMessage, 0);
}
catch (...)
{
char sMessage[MAX_PATH];
sprintf_s(sMessage,"Service failed to run, exception occured");
SvcReportEvent(sMessage, 0);
}
}
编辑:我现在已经解决了这个问题。我在postportem模式下使用Windbg(HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Image File Execution Options \ servicename.exe
调试器(字符串)设置为“C:\ Program Files \ Debugging Tools for Windows(x86)\ windbg.exe”),通过ORING SERVICE_INTERACTIVE_PROCESS将服务类型设置为交互式。我使用__debugbreak()语句进入ServiceMain中的调试器,这会调出一个奇怪的全屏模式窗口,只有在“交互模式提示”对话框后运行windbg。在那里,我能够在启动后立即调试正在运行的服务。原来,服务确实有一个错误导致堆栈溢出,我能够看到并纠正。谢谢大家!