记一次符号类型不一致导致的链接错误

记一次符号类型不一致导致的链接错误

两个头文件

在WDK中,有两个头文件:

  • ntddk.h:包含 wdm.h,传统的 NT 架构驱动(非即插即用)
  • ntifs.h:包含 ntddk.h 和 wdm.h,文件系统驱动、文件系统过滤驱动

由于 ntifs.h 已经包含了 ntddk.h,只需包含 ntifs.h 即可。同时包含两者可能导致类型重定义等编译错误。

报错信息

IoCtlHandler.obj : error LNK2019: 无法解析的外部符号 "public: static long __cdecl HelpTool::GetEprocess(void *,struct _EPROCESS * *)" (?GetEprocess@HelpTool@@SAJPEAXPEAPEAU_EPROCESS@@@Z),函数 "long __cdecl ProtectProcess(void *)" (?ProtectProcess@@YAJPEAX@Z) 中引用了该符号

符号类型不一致

我的源代码中,分别引用了上面的两个头文件。Windows WDK 头文件(如 wdm.h / ntifs.h)中的 PEPROCESS 定义,会根据预处理器宏(尤其是 NT_KERNEL 或 _KERNEL_MODE)来决定到底是引用 _EPROCESS 还是 _KPROCESS。

检查HelpTool.obj中导出的符号,发现:

txt 复制代码
dumpbin /SYMBOLS ".\HelpTool.obj"
Microsoft (R) COFF/PE Dumper Version 14.51.36252.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file .\HelpTool.obj

File Type: COFF OBJECT

COFF SYMBOL TABLE
000 01058D9C ABS    notype       Static       | @comp.id
001 C0010990 ABS    notype       Static       | @feat.00
002 00000000 SECT1  notype       Static       | .drectve
    Section length   2F, #relocs    0, #linenums    0, checksum        0
004 00000000 SECT2  notype       Static       | .debug$S
    Section length 2028, #relocs    0, #linenums    0, checksum        0
006 00000000 SECT3  notype       Static       | .bss
    Section length    1, #relocs    0, #linenums    0, checksum        0, selection    2 (pick any)
008 00000000 SECT3  notype       External     | ExPoolZeroingNativelySupported
009 00000000 SECT4  notype       Static       | .text$mn
    Section length   62, #relocs    3, #linenums    0, checksum 4519E64B, selection    1 (pick no duplicates)
00B 00000000 SECT5  notype       Static       | .debug$S
    Section length  144, #relocs    8, #linenums    0, checksum        0, selection    5 (pick associative Section 0x4)
00D 00000000 UNDEF  notype       External     | __imp_DbgPrintEx
00E 00000000 UNDEF  notype       External     | __imp_PsLookupProcessByProcessId
00F 00000000 SECT4  notype ()    External     | ?GetEprocess@HelpTool@@SAJPEAXPEAPEAU_KPROCESS@@@Z (public: static long __cdecl HelpTool::GetEprocess(void *,struct _KPROCESS * *))
010 00000000 SECT4  notype       Label        | $LN6
011 00000000 SECT6  notype       Static       | .xdata
    Section length    C, #relocs    0, #linenums    0, checksum B9123A2D, selection    5 (pick associative Section 0x4)
013 00000000 SECT6  notype       Static       | $unwind$?GetEprocess@HelpTool@@SAJPEAXPEAPEAU_KPROCESS@@@Z
014 00000000 SECT7  notype       Static       | .pdata
    Section length    C, #relocs    3, #linenums    0, checksum 92CEA7C6, selection    5 (pick associative Section 0x4)
016 00000000 SECT7  notype       Static       | $pdata$?GetEprocess@HelpTool@@SAJPEAXPEAPEAU_KPROCESS@@@Z
017 00000000 SECT8  notype       Static       | .text$s
    Section length   39, #relocs    0, #linenums    0, checksum 81C4C899, selection    2 (pick any)
019 00000000 SECT8  notype       External     | ??_C@_0DJ@KDOKOJHK@?$FLProtectMyProcess?3?3HelpTool?$FN?3?5Ge@FNODOBFM@ ( ?? ?? ::FNODOBFM::`string')
01A 00000000 SECT9  notype       Static       | .debug$S
    Section length   3C, #relocs    2, #linenums    0, checksum        0, selection    5 (pick associative Section 0x3)
01C 00000000 SECTA  notype       Static       | .debug$T
    Section length   7C, #relocs    0, #linenums    0, checksum        0
01E 00000000 SECTB  notype       Static       | .chks64
    Section length   58, #relocs    0, #linenums    0, checksum        0

String Table Size = 0x145 bytes

  Summary

           1 .bss
          58 .chks64
        21A8 .debug$S
          7C .debug$T
          2F .drectve
           C .pdata
          62 .text$mn
          39 .text$s
           C .xdata

对比两个编译单元看到的函数签名:

  • IoCtlHandler.cpp(报错方) 期望的符号是:?GetEprocess@HelpTool@@SAJPEAXPEAPEAU**_EPROCESS**@@@Z

    (参数为 struct _EPROCESS **)

  • HelpTool.obj导出的符号是:?GetEprocess@HelpTool@@SAJPEAXPEAPEAU**_KPROCESS**@@@Z

    (参数为 struct _KPROCESS **)

在编译 HelpTool.cpp 时,编译器认为 PEPROCESS 是 struct _KPROCESS *;而在编译 IoCtlHandler.cpp 时,PEPROCESS 被解析为 struct _EPROCESS *。

解决方案

我把参数中的peprocess改为了pvoid类型,反正eprocess在内核驱动开发中就是一个不透明的数据结构,最终都是要使用基址+偏移的方式访问其中的字段,索性让它直接为pvoid类型。

相关推荐
阿昭L8 天前
Windows对象句柄回调 (Object Handle Callbacks)
windows内核
阿昭L2 个月前
Windows内核事件通知机制
windows·windows内核
阿昭L2 个月前
通过KiSystemServiceUser获取SSDT基址
逆向工程·windows内核·ssdt
阿昭L2 个月前
Windows键盘过滤
windows·驱动开发·windows内核·过滤驱动
阿昭L2 个月前
通过cr3读写进程内存
保护模式·windows内核
阿昭L2 个月前
调试CreateProcess
windows·进程·逆向工程·windows内核
阿昭L3 个月前
调试Windows11启动过程
windows·uefi·windows内核
LittleFishC4 个月前
08_长调用与短调用
c语言·汇编·逆向·windows内核
阿昭L4 个月前
NT驱动程序和WDM驱动程序
驱动开发·windows内核