- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
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 。
感谢任何有知识回答这个问题的人。
我知道在内联程序集中调用该函数后进行清理有些愚蠢。
最佳答案
您需要保存和恢复EDI
和ESI
(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语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!