【问题标题】:How to solve LNK2019 unresolved external symbol DriverEntry referenced in function GsDriverEntry?如何解决函数 GsDriverEntry 中引用的 LNK2019 未解析的外部符号 DriverEntry?
【发布时间】:2019-02-15 12:05:40
【问题描述】:

当我编译这个项目时https://github.com/namazso/hdd_serial_spoofer

我收到了上面的错误信息,我该如何解决这个问题? 我正在使用 vs 2017 和 wdk 10 。

(必须在release编译,不支持debug模式。本项目没有DriverEntry函数,hwid.cpp中的EntryPoint(void* ntoskrn, void* image, void* alloc)函数才是真正的入口点。 )

我做了很多研究,但还是没能成功。我是内核模式驱动程序开发的菜鸟。

【问题讨论】:

  • 你试过在发布模式下编译吗?

标签: windows visual-studio driver kmdf


【解决方案1】:

不要使用.cpp 源文件来编写您的驱动程序。将它们更改为.c,它应该可以工作。对我来说就是这样。

我知道这看起来微不足道,或者不太可能,但请记住 Windows 内核代码是 C 代码,Visual Studio 会根据源文件的文件扩展名做出各种假设。

【讨论】:

    【解决方案2】:

    这不是普通的驱动,WDF直接支持的那种。它是一个“无人驾驶驱动程序”,它使用了一种未记录的黑客技术,吸引了那些为了乐趣和利润而编写 rootkit 的程序员。 DriverEntry() 函数实际上不是驱动程序的入口点,它是回调。很像 WinMain() 函数实际上并不是本机 Win32 程序的入口点。项目源代码中的 EntryPoint() 函数是本机驱动程序入口点的替代品。请注意,该项目似乎具有类似 rootkitty 的行为,旨在欺骗检查驱动器序列号的简单复制保护方案。

    GsDriverEntry() 函数是普通 KMDF 驱动程序中的真正入口点。它执行必要的初始化以支持/GS compiler option,旨在检测缓冲区溢出。完成后,它调用 DriverEntry()。项目将这个入口点替换为 EntryPoint()。

    此项目是使用旧版本的 Visual Studio 项目模板编写的。需要进行一些更改才能使其正确构建:

    • C/C++ > 代码生成 > 安全检查。必须是“禁用安全检查(/GS-)”,原来的项目文件是正确的。
    • 相同的属性页 > 控制流防护。必须设置为“否”以防止链接器错误。此选项会添加无法运行且必须禁用的额外安全检查。
    • C/C++ > 常规 > SDL 检查。使用下拉箭头覆盖为“从父级继承”,因此该选项显示为空白。更多需要禁用的安全检查,抑制 sdl- 与 /gs- 不兼容的警告。
    • 相同的属性页 > 警告级别。覆盖到“Level3 (/W3)”,抑制有关未使用函数参数的警告。
    • 链接器 > 输入 > 附加依赖项。单击下拉箭头 > 编辑。取消选中“从父级继承”复选框并更改为 $(DDK_LIB_PATH)ntoskrnl.lib。请注意继承值列表框中的 $(KernelBufferOverflowLib) 条目解析为 bufferoverflowfastfailk.lib,即包含 GsDriverEntry() 并产生链接器错误的条目。
    • 链接器 > 高级 > 入口点。必须是“EntryPoint”,原来的项目模板是正确的。

    在此之后它构建干净。我没有测试生成的 hwid.sys,看起来有点太邪恶了,无法将我的机器暴露给它。

    【讨论】:

      【解决方案3】:

      项目使用(一个明显被忽略的)选项

      <EntryPointSymbol>EntryPoint 定义为条目。

      这已记录在 here,但当前的文档似乎意味着这实际上仅适用于 .exe 和 .dll 项目。

      Windows驱动系统调用的消息形式

      NTSTATUS DriverInitialize(
        _DRIVER_OBJECT *DriverObject,
        PUNICODE_STRING RegistryPath
      )
      

      与项目中的EntryPoint不兼容

      EntryPoint(void* ntoskrn, void* image, void* alloc)
      

      这还不错,因为没有使用为 EntryPoint 调用的参数。

      所以最简单的实现是

      extern "C"
      {
          DRIVER_INITIALIZE DriverEntry;
          _Use_decl_annotations_
              NTSTATUS
              DriverEntry(
                  struct _DRIVER_OBJECT  *DriverObject,
                  PUNICODE_STRING  RegistryPath
              )
          {
              EntryPoint(NULL, NULL, NULL);
              return STATUS_SUCCESS;
          }
      }
      

      内核开发不适合胆小的人,在您的计算机上运行无效的内核代码可能会使其难以启动,或者在极端情况下会损坏计算机。我没有检查项目中的任何代码是否正确。

      请在虚拟机(vmware、virtualbox、hyper-v)中运行代码以限制它可能造成的损害

      【讨论】:

      • 对不起我的愚蠢问题,我现在想通了。
      猜你喜欢
      • 2019-01-22
      • 1970-01-01
      • 2013-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-30
      • 2014-11-07
      • 2013-06-01
      相关资源
      最近更新 更多