gpt4 book ai didi

com - 在 x86 程序集中构建 COM 对象 vtable

转载 作者:行者123 更新时间:2023-12-04 14:25:40 24 4
gpt4 key购买 nike

我正在使用 NASM 在 x86 程序集中构建一个 COM 对象。我非常了解 COM,我也非常了解 x86 程序集,但是让两者相互融合让我挂断了……(顺便说一句,如果你想劝阻我不要使用 x86 程序集,请不要,我有非常特殊的原因为什么要在 x86 程序集中构建它!)

我正在尝试构建一个 vtable 以在我的 COM 对象中使用,但我不断收到奇怪的指针,而不是指向我的函数的实际指针。 (我在想我得到了相对偏移量,或者 NASM 在其中嵌入了临时值,并且在链接期间它们没有被实际值替换)

我正在尝试构建的当前界面是IClassFactory接口(interface),代码如下:

%define S_OK 0x00000000
%define E_NOINTERFACE 0x80004002

section .text

; All of these have very simple shells rather than implementations, but that is just until I can get the vtable worked out

ClassFactory_QueryInterface:
mov eax, E_NOINTERFACE
retn 12

ClassFactory_AddRef:
mov eax, 1
retn 4

ClassFactory_Release:
mov eax, 1
retn 4

ClassFactory_CreateInstance:
mov eax, E_NOINTERFACE
retn 16

ClassFactory_LockServer:
mov eax, S_OK
retn 8

global ClassFactory_vtable
ClassFactory_vtable dd ClassFactory_QueryInterface, ClassFactory_AddRef, ClassFactory_Release, ClassFactory_CreateInstance, ClassFactory_LockServer

global ClassFactory_object
ClassFactory_object dd ClassFactory_vtable

注:这不是所有代码,我在不同的文件中有 DllGetClassObject、DllMain 等。

但是当我组装(使用 NASM: nasm -f win32 comobject.asm)和链接(使用 MS 链接: link /dll /subsystem:windows /out:comobject.dll comobject.obj),并使用 OllyDbg 检查可执行文件时,vtable 会出现奇怪的值。例如,在我上次构建中,函数的实际地址如下:
  • 查询接口(interface) - 0x00381012
  • AddRef - 0x0038101A
  • 发布 - 0x00381020
  • 创建实例 - 0x00381026
  • LockServer - 0x0038102E

  • 但是 vtable 有这些值:
  • 查询接口(interface) - 0x00F51012
  • AddRef - 0x00F5101A
  • 发布 - 0x00F51020
  • 创建实例 - 0x00F51026
  • LockServer - 0x00F5102E

  • 这些值看起来非常可疑......几乎就像搬迁没有采取一样。此外,vtable 显示为 0x00F5104A,所有这些都是不可访问的内存地址。 (出于信息目的,这些值每次都不同)

    我尝试使用 Visual Studio 2010 Express 在 C++ 中做同样的事情,一切都很好。所以我假设这只是我在 assembly 中缺少的东西......

    谁能向我指出为什么这些值没有正确显示?

    最佳答案

    我必须道歉,问题原来是我自己的错......在所有的混战中,我已经删除了 /dll从链接器调用,导致它被构建为 EXE,而不是 DLL...

    让我为下一个遇到此问题的人更好地解释一下。

    所有 Windows 可执行文件都有 base address这被假定为可执行文件将被加载到的虚拟地址。在大多数情况下加载到正在运行的进程中的可执行文件不会在“首选”位置加载 base address ,因为另一个 DLL(或应用程序本身)可能已经占用了该地址。因此,Windows PE 可执行文件使用所谓的 Relocation Table . Relocation Table告诉 Windows 在重定位到新的 base address 时需要重写可执行文件中的哪些位置.

    然而,随着 Virtual Memory 的出现,大多数链接器将忽略 EXE 中的重定位表作为优化,因为可执行文件将始终在其基地址加载(除非它与保留的内核地址冲突,在这种情况下它将无法一起加载)。所以因为我停止编译为 DLL,我的可执行文件没有被赋予 Relocation Table结果,不会正确加载到正在运行的进程的地址空间中。

    更新:

    默认情况下,MSVC 仅在 DLL 项目中包含重定位表,如 on MSDN 所述。 :

    By default, /FIXED:NO is the default when building a DLL, and /FIXED is the default for any other project type.

    可以通过提供 /FIXED:NO 来更改此行为。切换到链接器。非 DLL 项目的默认值为 /FIXED它告诉链接器目标具有固定的基地址并且不需要重定位表。

    关于com - 在 x86 程序集中构建 COM 对象 vtable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3331601/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com