调试程序集以调用 IUnknown::Release - 阴影空间正确吗?

问题描述 投票:0回答:1

我遇到一个错误,有时此代码可以工作,有时则不能:

48 8B 41 08            ; MOV RAX, [RCX + 0x08] gets the refcount
48 FF C8               ; DEC RAX               ; decrement refCount
48 89 41 08            ; MOV [RCX + 0x08], RAX ; update refCount in obj
48 83 F8 00            ; CMP RAX, 0
74 01                  ; JE +1                 ; (skips early return if RAX is zero)
C3                     ; RET                   ; (return from function)
51                     ; PUSH RCX              ; to cache it
48 8B 49 10            ; MOV RCX, [RCX + 0x10] ; Read the child object into RCX
48 83 F9 00            ; CMP RCX, 0            ; ensure the child object hasn't been set to Nothing
74 11                  ; JE 0x11               ; jump the next 17 bytes to avoid calling release
48 8B 01               ; MOV RAX, [RCX]        ; Get vtable pointer from [RCX] into RAX
48 8B 40 10            ; MOV RAX, [RAX + 0x10] ; Get IUnknown::Release function pointer from [RAX + 0x10] into RAX (QI + hex(ptr_size * 2) for Release)
48 83 EC 28            ; SUB RSP, 0x28         ; Allocate shadow space
FF D0                  ; CALL RAX              ; Call the function pointed to by RAX
48 83 C4 28            ; ADD RSP, 0x28         ; Deallocate shadow space
59                     ; POP RCX               ; to restore it to the parent object
48 B8 {addrCoTaskMemFree} ; MOV RAX, addrCoTaskMemFree
48 83 EC 28            ; SUB RSP, 0x28
FF D0                  ; CALL RAX
48 83 C4 28            ; ADD RSP, 0x28
48 31 C0               ; XOR RAX, RAX
C3                     ; RET

此代码的目的是对象的 IUnknown::Release 方法的 64 位 Windows Intel 实现。这里我有一个父对象和一个子对象,这是父对象的release方法。

IUnknown::发布应该:

  • 减少引用计数
  • 如果引用计数为 0,则对任何成员对象调用 IUnknown::Release
  • 在父对象实例上调用 CoTaskMemFree
  • 释放后返回refcount

作为参考,父对象的内存布局是这样的

偏移 价值 尺寸
0x00 虚函数表指针 0x08 - 64 位
0x08 引用计数 0x08 - 64 位
0x10 **孩子VTable 0x08 - 64 位

我正在尝试追踪一个复杂的错误 - 当我让父对象将其自身的第二个实例作为子对象保存,并且该对象作为子对象不保存任何内容时,此代码工作正常。所以父->子->nullptr

但是,如果我让父级保存其他一些 COM 对象(例如 VBA.Collection)的实例,那么我会崩溃。


我尝试过的事情

我尝试制作代码的每个步骤的图表,并记下寄存器,以确保流程正确,请参阅此处或下图。但我无法弄清楚。我认为这可能是影子堆栈空间的问题,因为有时我在函数调用之前使用堆栈,但我感觉我正在用头撞砖墙。调试这个非常繁琐,汇编代码是在运行时注入内存的VBA中的thunk,所以我必须使用x64dbg附加到Excel.exe,在为函数代码分配的内存处创建一个断点,注入它并等待要命的断点。 VBA 被解释,因此调用堆栈非常混乱。 我希望有人可以查看我的程序集并立即发现问题,我是一个汇编新手,尤其是我只为这个项目学习的 64 位。

enter image description here

assembly com x86-64 code-injection
1个回答
0
投票
PUSH ECX

和分配影子空间的方式的组合,您的堆栈未对齐。您也可以去掉相互抵消的

ADD
/
SUB
对。从
JE 0x11
开始的代码可能是:
SUB RSP, 0x20         ; Allocate shadow space
CALL RAX              ; Call the function pointed to by RAX
MOV RCX, [RSP + 0x20] ; to restore it to the parent object
MOV RAX, addrCoTaskMemFree
CALL RAX
ADD RSP, 0x28         ; free shadow space and discard saved RCX
XOR EAX, EAX          ; 32 bit ops zero extend no need for REX
RET

	
© www.soinside.com 2019 - 2024. All rights reserved.