所以我正在为一个程序(确切地说是游戏)编写一个“扩展”。这更像是一种黑客行为。无论如何,我正在反转一些类,比如角色、项目等。我想做好的方法。
所以我做了这样的事情:
字符.hpp
class CHARACTER
{
public:
int hp;
int level;
//....
int GetLevel(void);
void SetLevel(int lv);
};
字符.cpp
#include "character.hpp"
int CHARACTER::GetLevel(void)
{
return ((int(*)(CHARACTER*))0xADDR)(this);
}
void CHARACTER::SetLevel(int lv)
{
((void(*)(CHARACTER*,int))0xADDR)(this,lv);
}
主文件
void hook1(CHARACTER* pc)
{
pc->SetLevel(99);
}
问题是,代码执行了两次。您在 hook1 中推送参数,然后在 CHARACTER::SetLevel 中再次推送它们(下面的伪 asm):////////////
hook1:
push 99
call CHARACTER__SetLevel
CHARACTER__SetLevel:
push arg
call 0xADDR
所以我试着做一个跳转,因为你已经在堆栈上有了所有的参数,你可以直接跳转到函数。问题是,“asm”添加了
push ebp
mov ebp, esp
void CHARACTER::SetLevel(int lv)
{
asm(".intel_syntax\n"
"mov eax, 0xADDR\n"
"jmp eax\n"
);
}
at the beginning. So I have to execute this code at address + 3
(If I'm making hook in only asm, I do something like this)
void hook_asm(void)
{
asm(".intel_syntax noprefix\n"
".whatever\n"
);
}
void MAIN_HOOK(void)
{
JmpPatch(0xADDR, &hook_asm+3); // Skip push ebp and mov ebp, esp
}
///////////////////
所以,我看到的唯一解决方案就是让它像
void asm_SetLevel(void)
{
asm(".intel_syntax noprefix\n"
"mov eax, 0xADDR\n"
"jmp eax\n"
);
}
CHARACTER::SetLevel(int lv)
{
((void(*)(void))&asm_SetLevel+3)();
}
但这不是我想做的,除了每种方法我都有 2x 函数。
有没有办法让它变得更好?
对不起我的英语和混乱,我已尽力解释我的问题。希望你能明白我的意思。