【问题标题】:How to debug driver load error?如何调试驱动程序加载错误?
【发布时间】:2010-12-16 08:08:38
【问题描述】:

我已经为 Windows 制作了一个驱动程序,编译它并尝试通过 SC 管理器启动它,但我从 SC 管理器 API 收到系统错误:

ERROR_PROC_NOT_FOUND The specified procedure could not be found.

有没有办法获得有关驱动程序无法启动的确切原因的更多信息? WinDbg 什么的?如果我注释掉我的 DriverEntry 例程中的所有代码,驱动程序就会启动。

我唯一调用的是另一个源模块中的过程(不过在我自己的项目中)。我可以注释掉所有外部依赖项,但我仍然得到同样的错误。

编辑:
我也尝试过不同的 DDK,即 2003 DDK 和 Vista WDK(但不是 Win7 WDK)

编辑2: 这是我的驱动程序酸代码文件driver.cpp:

#ifdef __cplusplus
extern "C" {
#endif
#include <ntddk.h>
#include <ntstrsafe.h>
#ifdef __cplusplus
}; // extern "C"
#endif

#include "../distorm/src/distorm.h"

void DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
}

#define MAX_INSTRUCTIONS 20

#ifdef __cplusplus
extern "C" {
#endif
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
 UNICODE_STRING pFcnName;

 // Holds the result of the decoding.
 _DecodeResult res;
 // Decoded instruction information.
 _DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
 // next is used for instruction's offset synchronization.
 // decodedInstructionsCount holds the count of filled instructions' array by the decoder.
 unsigned int decodedInstructionsCount = 0, i, next;
 // Default decoding mode is 32 bits, could be set by command line.
 _DecodeType dt = Decode32Bits;

 // Default offset for buffer is 0, could be set in command line.
 _OffsetType offset = 0;
 char* errch = NULL;

 // Buffer to disassemble.
 char *buf;
 int len = 100;

 // Register unload routine
 DriverObject->DriverUnload = DriverUnload;

 DbgPrint("diStorm Loaded!\n");

 // Get address of KeBugCheck
 RtlInitUnicodeString(&pFcnName, L"KeBugCheck");
 buf = (char *)MmGetSystemRoutineAddress(&pFcnName);
 offset = (unsigned) (_OffsetType)buf;

 DbgPrint("Resolving KeBugCheck @ 0x%08x\n", buf);
 // Decode the buffer at given offset (virtual address).

 while (1) {
  res = distorm_decode(offset, (const unsigned char*)buf, len, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
  if (res == DECRES_INPUTERR) {
   DbgPrint(("NULL Buffer?!\n"));
   break;
  }

  for (i = 0; i < decodedInstructionsCount; i++) {
   // Note that we print the offset as a 64 bits variable!!!
   // It might be that you'll have to change it to %08X...
   DbgPrint("%08I64x (%02d) %s %s %s\n", decodedInstructions[i].offset, decodedInstructions[i].size, 
    (char*)decodedInstructions[i].instructionHex.p,
    (char*)decodedInstructions[i].mnemonic.p,
    (char*)decodedInstructions[i].operands.p);
  }

  if (res == DECRES_SUCCESS || decodedInstructionsCount == 0) {
   break; // All instructions were decoded.
  }

  // Synchronize:
  next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - offset);
  next += decodedInstructions[decodedInstructionsCount-1].size;

  // Advance ptr and recalc offset.
  buf += next;
  len -= next;
  offset += next;
 }

 DbgPrint(("Done!\n"));
 return STATUS_SUCCESS;
}

#ifdef __cplusplus
}; // extern "C"
#endif

我的目录结构是这样的:

base_dir\driver\driver.cpp
        \distorm\src\all_the_c_files
        \distorm\distorm.h
        \distorm\config.h

我的 SOURCES 文件:

# $Id$
TARGETNAME=driver
TARGETPATH=obj
TARGETTYPE=DRIVER

# Additional defines for the C/C++ preprocessor
C_DEFINES=$(C_DEFINES) -DSUPPORT_64BIT_OFFSET

SOURCES=driver.cpp \
     distorm_dummy.c \
        drvversion.rc

INCLUDES=..\distorm\src;

TARGETLIBS=$(DDK_LIB_PATH)\ntdll.lib \
        $(DDK_LIB_PATH)\ntstrsafe.lib

你可以从这里下载diStorm:http://ragestorm.net/distorm/dl.php?id=8

distorm_dummy 与 diStorm 库中的 dummy.c 相同。

【问题讨论】:

  • 能否请您发布源文件以及驱动程序的 .cpp 文件?
  • 我目前无法真正测试/构建驱动程序,所以......您能否尝试删除 DriverEntry 周围的 extern "C" 部分,因为它是多余的。
  • 如果我删除它们,我会得到构建错误:错误 LNK2019:无法解析的外部符号 _DriverEntry@8 在函数 _GsDriverEntry@8 1> 中引用>.....driver\bufferoverflowk.lib

标签: c windows kernel driver


【解决方案1】:

使用 6000 WDK/DDK 构建它(因为使用“实际”构建 7600...它链接到 wdfldr.sys,但在 Windows Vista 和 XP 系统下,此 sys 文件不可用)。 我不知道你在哪里可以正式下载它,但我确实使用了 torrent...

【讨论】:

    【解决方案2】:

    毫不奇怪,您拥有自己解决此问题所需的所有信息。

    ERROR_PROC_NOT_FOUND 找不到指定的过程。

    结合您的依赖项 Walker 输出,这几乎指向了一个损坏的 Import Table

    为什么您的 IT 出现故障?我不确定,可能是您的构建/链接器设置有问题,因为很明显,HAL.DLL 就在 %windir%\system32 中。

    加载订单中断的原因有很多,您必须自己找出原因。

    【讨论】:

    • 错误是因为我包含了 TARGETLIBS=$(DDK_LIB_PATH)\ntdll.lib 从 SOURCES 中删除后,驱动程序工作
    【解决方案3】:

    您是否尝试过在已编译的 .sys 上运行 Dependency Walker 并查看是否确实缺少一些函数导入?

    【讨论】:

    • Dependencie Walker 告诉我 4 个错误:“打开文件时出错。系统找不到指定的文件 (2)”用于文件 CI.DLL、CLFS.SYS、HAL.DLL 和 KDCOM.DLL
    【解决方案4】:

    使用 gflags 启用“显示加载程序快照”——在调试输出中,您应该找到有关加载程序无法解析的导入的信息。

    【讨论】:

    • 似乎不起作用。我这样使用它:!glaf +sls,但附加的 WinDbg 没有显示任何调试消息
    【解决方案5】:

    您可以在 WinDbg 中添加延迟断点。

    如果你指定一个断点,当驱动程序没有被加载(或使用 bu)时,它会在驱动程序被加载并进入函数时被触发。

    指定断点的命令是:

    bp <module_name>!<function_name>
    

    例如:

    bp my_driver!DriverEntry
    

    【讨论】:

    • 正如我所说,驱动程序根本没有加载。我需要知道为什么会这样
    • 为此,您可以在 DriverEntry 函数中指定断点,以便在执行该函数时触发断点,并且您可以单步执行代码。
    • bp 永远不会触发,因为驱动入口函数甚至不会被调用。驱动程序似乎在 操作系统正在加载它时失败 - 而不是在加载之后
    • 那么我的猜测是,您通过使用您的函数来更改 DriverEntry 函数的定义。 (STDCALL/CDECL/...)
    • 很遗憾没有,请参阅我上面发布的声明
    猜你喜欢
    • 1970-01-01
    • 2011-06-21
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 2018-08-13
    • 2018-08-23
    • 2012-09-14
    • 1970-01-01
    相关资源
    最近更新 更多