在x86程序集中构建COM对象vtable [英] Building a COM object vtable in x86 assembly

查看:220
本文介绍了在x86程序集中构建COM对象vtable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用NASM在x86程序集中构建一个COM对象。我理解COM很好,我理解x86大会很好,但让两个网格是让我挂... ...(顺便说一句,如果你想试图劝阻我使用x86程序集,请克制,我有非常特别的理由为什么我在x86程序集中构建这个)



我试图构建一个vtable在我的COM对象中使用,但我不断变得奇怪指针,而不是我的函数的实际指针。 (我认为我得到相对偏移,或者NASM正在嵌入临时值,并且在链接期间不会被真实值替代)



我想要构建的当前接口是 IClassFactory 接口,代码如下:

 %define S_OK 0x00000000 
%define E_NOINTERFACE 0x80004002

section .text

;所有这些都有非常简单的shell而不是实现,但是只是直到我可以得到vtable编制

ClassFactory_QueryInterface:
mov eax,E_NOINTERFACE
retn 12

ClassFactory_AddRef:
mov eax,1
retn 4

ClassFactory_Release:
mov eax,1
retn 4
b $ b ClassFactory_CreateInstance:
mov eax,E_NOINTERFACE
retn 16

ClassFactory_LockServer:
mov eax,S_OK
retn 8
$ b b全局ClassFactory_vtable
ClassFactory_vtable dd ClassFactory_QueryInterface,ClassFactory_AddRef,ClassFactory_Release,ClassFactory_CreateInstance,ClassFactory_LockServer

全局ClassFactory_object
ClassFactory_object dd ClassFactory_vtable

注意:这不是所有的代码,我有一个不同的文件中的DllGetClassObject,DllMain等。 >



但是当我组装(使用NASM: nasm -f win32 comobject.asm )和链接链接: link / dll / subsystem:windows /out:comobject.dll comobject.obj ),并使用OllyDbg检查可执行文件,vtable出来的奇怪的值。例如,在我的最后一个版本中,函数的实际地址如下:




  • QueryInterface - 0x00381012

  • AddRef - 0x0038101A

  • 发布 - 0x00381020

  • CreateInstance - 0x00381026

  • LockServer - 0x0038102E



但是vtable提供了这些值:




  • QueryInterface - 0x00F51012

  • AddRef - 0x00F5101A

  • 发布 - 0x00F51020

  • CreateInstance - 0x00F51026

  • LockServer - 0x00F5102E



这些值看起来非常可疑...几乎像重定位采取。此外,vtable出现0x00F5104A,所有这些都是不可访问的内存地址。 (为信息目的,这些值每次出来不同



我试着在C ++使用Visual Studio 2010 Express和一切出来好。所以我假设这是我在我的程序集中缺少的东西...





任何人都可以指出我为什么这些值不会正确出现?

解决方案

我必须道歉,问题是我自己的错误...在所有的乱序搭建的东西,我已经从链接器调用中删除了 / dll ,导致它被构建为一个EXE,而不是一个DLL ...



让我为下一个经历这个问题的人解释一下。



所有Windows可执行文件都有基本地址,假设它是可执行文件的虚拟地址将加载到。在大多数情况下加载到正在运行的进程中的可执行文件将不会加载到首选基地址< a>,因为另一个DLL(或应用程序本身)可能已经占用了地址。因此,Windows PE可执行文件使用所谓的重定位表重新定位表告诉Windows可执行文件中的哪些位置需要重新写入,以便重新定位到新的基本地址



但是,随着虚拟内存的出现,大多数链接器将忽略EXE中的重定位表,如优化,因为可执行文件将总是在它的基地址加载(除非它与保留的内核地址冲突,在这种情况下它将无法全部加载)。因此,因为我停止了编译为DLL,我的可执行文件没有被给予一个重定位表

更新:

/ p>

默认情况下,MSVC只包括DLL项目中的重定位表,如在MSDN上

  ,/ FIXED:NO是构建DLL时的默认值,而/ FIXED是任何其他项目类型的默认值。 

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


I am building a COM object in x86 assembly using NASM. I understand COM quite well and I understand x86 assembly pretty well, but getting the two to mesh is getting me hung up... (by the way, if you're thinking of attempting to dissuade me from using x86 assembly, please refrain, I have very particular reasons why I'm building this in x86 assembly!)

I am trying to build a vtable to use in my COM object, but I keep getting strange pointers, rather than actual pointers to my functions. (I'm thinking that I'm getting relative offsets or that NASM is embedding temporary values in there and they're not being replaced with the real values during linking)

The current interface I'm trying to build is the IClassFactory interface, with code as follows:

%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

Note: This is not all of the code, I have DllGetClassObject, DllMain, etc. in a different file.

But when I assemble (using NASM: nasm -f win32 comobject.asm) and link (using MS Link: link /dll /subsystem:windows /out:comobject.dll comobject.obj), and examine the executable using OllyDbg, the vtable comes out with strange values. For example, in my last build, the actual addresses for the functions are as follows:

  • QueryInterface - 0x00381012
  • AddRef - 0x0038101A
  • Release - 0x00381020
  • CreateInstance - 0x00381026
  • LockServer - 0x0038102E

But the vtable came out with these values:

  • QueryInterface - 0x00F51012
  • AddRef - 0x00F5101A
  • Release - 0x00F51020
  • CreateInstance - 0x00F51026
  • LockServer - 0x00F5102E

These values look awfully suspicious... almost like the relocation didn't take. Also, the vtable comes out as 0x00F5104A, all of which are inaccessible memory addresses. (for informational purposes, these values come out different every time)

I tried doing the same thing in C++ using Visual Studio 2010 Express and everything comes out fine. So I'm assuming that it's just something that I'm missing in my assembly...


Can anyone point out to me why these values aren't coming out properly?

解决方案

I must apologize, the problem turned out to be my own fault... In all of the scuffle building the thing, I had removed the /dll from the linker invocation, causing it to be built as an EXE, not a DLL...


Let me explain this a little better for the next person who runs across this.

All Windows executables have a base address which is assumed to be the virtual address that the executable will be loaded into. Executables that are loaded into a running process in most cases will not be loaded at the "preferred" base address, because another DLL (or the application itself) is probably already occupying the address. For this reason, Windows PE executables use what is called a Relocation Table. The Relocation Table tells Windows which locations in the executable need to be rewritten in case of a relocation to a new base address.

However, with the advent of Virtual Memory, most linkers will omit the relocation table from EXEs as an optimization, because the executable will always be loaded at it's base address (unless it conflicts with the reserved kernel addresses, in which case it will fail to load all-together). So because I stopped compiling as a DLL, my executable was not being given a Relocation Table and as a result, would not load properly into running process' address space.


Update:

By default, MSVC only includes relocation tables in DLL projects, as described on MSDN:

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

This behavior can be changed by supplying the /FIXED:NO switch to the linker. The default for non-DLL projects is /FIXED which tells the linker that the target has a fixed base address and does not require a relocation table.

这篇关于在x86程序集中构建COM对象vtable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆