Gre*_*edo 3 com assembly vba x86-64 shellcode
我有一些 VBA 代码,用于将 COM vtable 中的函数指针之一与汇编代码的 NO-OP 位交换。它在 twinBASIC 中工作,这是一个独立的 VBA 环境,所以我知道我已经非常接近了,但是在 Excel 中它崩溃了。
这是 minrepro,可以在 tB 中运行,理论上不能在 Excel VBA 中运行。
Class DummyThing
Sub DoNothing()
End Sub
End Class
Module VBA
Private Const MEM_COMMIT As Long = &H1000
Private Const MEM_RESERVE As Long = &H2000
Private Const PAGE_EXECUTE_READWRITE As Long = &H40
Declare PtrSafe Function VirtualAlloc Lib "kernel32" ( _
ByVal lpAddress As LongPtr, _
ByVal dwSize As Long, _
ByVal flAllocationType As Long, _
ByVal flProtect As Long) As LongPtr
Sub Main()
Dim code(1 To 4) As Byte
code(1) = CByte(&h48)
code(2) = CByte(&h31)
code(3) = CByte(&hC0) 'xor rax, rax to clear it - this is like setting the hresult to 0
code(4) = CByte(&hC3) 'ret
Dim buffer As LongPtr
buffer = VirtualAlloc(0&, UBound(code) - LBound(code) + 1, MEM_COMMIT Or MEM_RESERVE, PAGE_EXECUTE_READWRITE)
If buffer = 0 Then
Debug.Print "VirtualAlloc() failed (Err:" ; Err.LastDllError ; ")."
Exit Sub
End If
CopyMemory ByVal buffer, code(1), UBound(code) - LBound(code) + 1
Dim base As DummyThing
Set base = New DummyThing
Dim vtable As LongPtr
vtable = MemLongPtr(ObjPtr(base))
MemLongPtr(vtable + PTR_SIZE * 7) = buffer
base.DoNothing 'Excel VBA crashes here, tB prints the message below
Debug.Print vbNewLine ; "Done!"
End Sub
End Module
Run Code Online (Sandbox Code Playgroud)
内存 api 来自这里https://github.com/cristianbuse/VBA-MemoryTools/blob/master/src/LibMemory.bas
它是一个超级简单的 64 位汇编代码,通过交换 out 的 vtableSub DoNothing()并将其替换为指向一些可执行操作码的指针来运行。汇编代码无非就是
48 31 C0 xor rax, rax ; Set return value to 0
C3 ret ; Return
Run Code Online (Sandbox Code Playgroud)
可能是什么原因导致崩溃 - 也许 VBA 检查 vtable 完整性并且它指向预期地址范围内的内存?但我以前从未遇到过重载 vtable 的问题。
找到了答案
在VBA64中,对于VBA实现的类,[解释器]不直接使用vtable函数指针。相反,它检测到该对象是由 VBA(本身)实现的,并且是所请求成员的直接 pcode 实现的快捷方式,而不是使用必须跳回 pcode 虚拟机的本机函数指针。这是一种优化,虽然实际上是一种微观优化,但最终它会阻止简单的 vtable 修补工作。
情况并非总是如此。在 VBA64 的早期版本(没有服务包的 Office 2010)中,它们确实使用了本机 vtable 函数调用,当时您可以使用普通的 vtable 修补。
https://discord.com/channels/927638153546829845/1157647794484543589/1157660431545024553
因此,崩溃来自于 VBA 看到该类是一个 VBA 类,然后使用 vtable 中的指针作为指向 pcode 的快捷方式的路标作为优化。
除非我们覆盖了函数指针,否则它在同一位置没有相应的 pcode,因此查找失败或 VBA 开始尝试将随机内存解释为 pcode,从而导致崩溃。
解决方案是在不进行 vtable 修补的情况下调用 assem,以避免优化 - 例如使用 dispcallfunc,或通过使用 CoTaskMemAlloc 和手工制作的 vtable 手动实现整个 COM 对象。
| 归档时间: |
|
| 查看次数: |
202 次 |
| 最近记录: |