c++ - 从 ida pro Hook 用户调用函数

标签 c++ c assembly hook calling-convention

int CachedTag_NoCache_GetTagPos( CEntity* centity, int tag, Vector* worldpos )
    {
        void* funccall = (void*)0x7D5BD0;
        __asm {
            mov edi, worldpos
            mov esi, centity
            push tag
            call funccall
            add esp, 4
        }
    }

函数在 add esp, 4.... 时崩溃

我知道它会因清理此内联程序集而崩溃。我只是不知道如何解决它。

这是ida pro里面的内容:

int __usercall sub_7A7D20<eax>(int a1<ecx>, int a2<edi>, int a3<esi>, int a4)
{
  int v4; // eax@2
  int result; // eax@2
  char *v6; // eax@3
  char v7; // al@5
  int v8; // [sp+0h] [bp-4h]@1

  v8 = a1;
  if ( *(_WORD *)(a3 + 678) == 1 )
  {
    LOBYTE(v8) = sub_5BB6F0(*(_BYTE *)(a3 + 4), *(_DWORD *)(a3 + 0x1E8));
    v4 = sub_7A7C40();
    result = sub_4DA2F0(a3, a2, a4, v4, v8);
  }
  else
  {
    v6 = sub_615EA0(*(_DWORD *)(a3 + 0x1E8), *(_BYTE *)(a3 + 4));
    result = sub_4B2F50(a3, v6, a2, a4);
  }
  if ( !result )
  {
    v7 = sub_624C70(a2, 0);
    result = sub_627380(1, "AimTarget_GetTagPos: Cannot find tag [%s] on entity\n", v7);
  }
  return result;
}

此函数的程序集来自 ida pro 的文本:

.text:007D5BD0 sub_7D5BD0      proc near               ; CODE XREF: sub_4DA2F0+76p
.text:007D5BD0                                         ; sub_62AE20+18p
.text:007D5BD0
.text:007D5BD0 arg_0           = dword ptr  4
.text:007D5BD0
.text:007D5BD0                 movzx   eax, byte ptr [esi+4]
.text:007D5BD4                 mov     ecx, [esi+1E8h]
.text:007D5BDA                 push    ebx
.text:007D5BDB                 mov     ebx, [esp+4+arg_0]
.text:007D5BDF                 push    eax
.text:007D5BE0                 push    ecx
.text:007D5BE1                 call    sub_615EA0
.text:007D5BE6                 add     esp, 8
.text:007D5BE9                 test    eax, eax
.text:007D5BEB                 jnz     short loc_7D5C00
.text:007D5BED                 fld     dword ptr [esi+30h]
.text:007D5BF0                 pop     ebx
.text:007D5BF1                 fstp    dword ptr [edi]
.text:007D5BF3                 fld     dword ptr [esi+34h]
.text:007D5BF6                 fstp    dword ptr [edi+4]
.text:007D5BF9                 fld     dword ptr [esi+38h]
.text:007D5BFC                 fstp    dword ptr [edi+8]
.text:007D5BFF                 retn
.text:007D5C00 ; ---------------------------------------------------------------------------
.text:007D5C00
.text:007D5C00 loc_7D5C00:                             ; CODE XREF: sub_7D5BD0+1Bj
.text:007D5C00                 push    edi
.text:007D5C01                 push    ebx
.text:007D5C02                 push    eax
.text:007D5C03                 push    esi
.text:007D5C04                 call    sub_4B2F50
.text:007D5C09                 add     esp, 10h
.text:007D5C0C                 test    eax, eax
.text:007D5C0E                 jnz     short loc_7D5C2B
.text:007D5C10                 push    eax
.text:007D5C11                 push    ebx
.text:007D5C12                 call    sub_624C70
.text:007D5C17                 push    eax             ; char
.text:007D5C18                 push    offset aCachedtag_noca ; "CachedTag_NoCache_GetTagPos: Cannot fin"...
.text:007D5C1D                 push    1               ; int
.text:007D5C1F                 call    sub_627380
.text:007D5C24                 add     esp, 14h
.text:007D5C27                 xor     eax, eax
.text:007D5C29                 pop     ebx
.text:007D5C2A                 retn
.text:007D5C2B ; ---------------------------------------------------------------------------
.text:007D5C2B
.text:007D5C2B loc_7D5C2B:                             ; CODE XREF: sub_7D5BD0+3Ej
.text:007D5C2B                 mov     edx, dword_D4F178
.text:007D5C31                 mov     eax, [edx+40688h]
.text:007D5C37                 pop     ebx
.text:007D5C38                 retn
.text:007D5C38 sub_7D5BD0      endp
.text:007D5C38
.text:007D5C38 ; ---------------------------------------------------------------------------
.text:007D5C39                 align 10h
.text:007D5C40

我的组件正在运行。我进入游戏,它显示了我想要的大约 3 分钟。然后它崩溃了。在将 visual studio 附加到进程时,它总是在添加 esp,4 时在我上面的函数上崩溃。

现在在使用 edi 和 esi 的用户调用上,我是否必须在调用我的函数后将它们弹出和/或我是否还必须返回一些东西?

它显然不适合我的方式,因为它只能工作大约 3 分钟。我使用代码最长的时间是大约 3 场比赛。时长约 10 分钟。

然后在那 3 场比赛之后,它开始对我造成 fatal error 。

感谢任何有知识回答这个问题的人。

我知道在内联程序集中调用该函数后进行清理有些愚蠢。

最佳答案

您需要保存和恢复EDIESI(x86 ABI 将它们定义为-volatile 寄存器,这意味着您不能丢弃它们),也可能是 MSVC 生成的序言和结尾导致了问题,IMO,最好将其写成纯 naked function ,这使您可以更好地控制生成的程序集,并确保您可以正确模拟非标准(优化)调用约定:

__declspec(naked) int __fastcall CachedTag_NoCache_GetTagPos(CEntity* centity, int tag, Vector* worldpos)
{
    __asm {
        push edi
        push esi
        mov edi,worldpos
        mov esi,centity
        push tag
        mov eax,0x7D5BD0
        call eax
        add esp,4
        pop esi
        pop edi
        retn 4
    }
}

就您遇到的异常而言,听起来您没有得到正确的行,像 ollydbg 这样的汇编级调试器可以帮助您查明确切的原因和正确的位置。


另外,请注意,永远不要使用固定地址,使用重定位安全变体,即:基地址 + RVA;在我上面的代码中,您只需更改两行即可实现:

mov eax,[base_address]
add eax,rva

其中 base_address 是沿着:

UINT_PTR base_address = (UINT_PTR)GetModuleHandle("some_module");

并且是全局可访问的。

关于c++ - 从 ida pro Hook 用户调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21514948/

相关文章:

c++ - std::istream 类型是 EqualityComparable 吗?

android - 为什么IDE显示: parameter type mismatch: array is not assignable

c - 使用 strtok,适用于一个文件,但不适用于另一个文件

c - 将不正确的字符写入帧缓冲区

assembly - 引导加载程序帮助...为什么 USB 驱动器即使没有引导签名也能引导?

assembly - 尝试组装反汇编器的输出(例如 objdump)

c++ - 增加位图亮度的公式是什么?

c++ - 如何修改类中的值? (C++)

c++ - Boost 和 Windows 套接字 - 正确处理 TCP 客户端断开连接的情况

c - 是否可以从 OCaml 调用 C 函数并有效地传递一个巨大的数组?