【问题标题】:Hooking a usercall function from ida pro从 ida pro 挂钩用户调用函数
【发布时间】:2014-02-02 19:12:43
【问题描述】:
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 附加到该进程时,它总是说在我上面的 add esp, 4 函数上崩溃了。

现在,在使用 edi 和 esi 的用户调用中,我是否必须在调用我的函数后将它们弹出和/或我是否也必须保留某些内容?

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

在这 3 场比赛之后,我开始出现致命错误。

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

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

【问题讨论】:

    标签: c++ c assembly hook calling-convention


    【解决方案1】:

    您需要保存和恢复EDIESI(x86 ABI 将它们定义为-易失性寄存器,这意味着您不能丢弃它们),它也可能是序言和尾声由导致问题的 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");
    

    并且是全局可访问的。

    【讨论】:

    • 在我添加 pop esi 或 pop edi 甚至 retn 的那一刻。它崩溃了致命错误。另外,我在课堂上没有它。所以,我在 __thiscall 上收到警告。它也不喜欢原型中的裸函数,因此我将其取下并进行编译。您的代码在到达的那一刻出现致命错误。
    • @Pepsi_1:__declspec(naked) 的存在是有原因的,如果您遇到编译器错误是因为您将其包含在前向原型中(或者您没有使用 MSVC,在这种情况下您有要应对的 ABI 问题)。至于它崩溃,您是否通过程序集级调试器运行它?只是说它崩溃没有任何意义。不过你是对的,不知道为什么我认为它是一个类成员函数,可能是因为你的程序集中的地址不匹配......
    • @Pepsi_1:在我的程序集中发现了两个小错误,已更正。
    • 我试一试,给我几分钟报告结果。
    • 它总是添加,尤其是 4...我在过去一周左右的时间里一直看到它。它真的让我...
    【解决方案2】:

    您提供的代码是正确的。目标函数本身是堆栈中立的,您可以在调用后清理 push 参数。

    您确定这是代码崩溃的正确行吗?你得到什么例外?我认为向寄存器添加常量甚至不会导致异常。

    您报告的崩溃间隔似乎是随机的。这可能是一个线程问题,例如您传递了一个无效的 CEntity 并且被调用的函数崩溃了。您可以通过挂钩通常调用此函数的线程并在该线程中调用它来防止这种情况发生。

    【讨论】:

    • 我如何挂钩游戏的主线程? Visual Studio 2012 说它实际上是我上面的函数,它出现了致命错误。该功能可以正常工作约 5 分钟,然后出现致命错误。有时它的 3 分钟就会出现致命错误。但是,如果没有致命错误,我将无法持续整个游戏。我尝试了不同的堆栈清理,但它似乎立即出现了致命错误。当我尝试了所有方法时,我不确定此时该做什么。此功能无法按预期工作。
    猜你喜欢
    • 2020-08-01
    • 2015-06-04
    • 1970-01-01
    • 2016-05-30
    • 2012-11-09
    • 1970-01-01
    • 2013-05-21
    • 2011-05-26
    • 2019-12-31
    相关资源
    最近更新 更多