C++ 函数挂钩(仅内存地址)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13026220/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ Function Hook (memory address only)
提问by User
I have a memory address, its the memory address of a function in another program (one of its dlls). I am already loaded into the program via DLL injection. I already have the bass address, and the actual location of the function each time the program loads. So, this is not an issue.
我有一个内存地址,它是另一个程序(其中一个 dll)中某个函数的内存地址。我已经通过 DLL 注入加载到程序中。我已经有了低音地址,以及每次程序加载时函数的实际位置。所以,这不是问题。
I want to just simply hook that location, and grab the variables. I know the function's pseudocode. So this is not an issue. OR another approach that would be great is doing a break point at that memory location and grab the debug registers.
我只想简单地钩住那个位置,然后抓住变量。我知道函数的伪代码。所以这不是问题。或者另一种很棒的方法是在该内存位置设置断点并获取调试寄存器。
I can not find any clear-cut examples of this. I also do not have the "name" of the function, I just have the memory address. Is there any way to work with just a memory address? Most, if not all the examples have you use the name of the function, which I do not have.
我找不到任何明确的例子。我也没有函数的“名称”,我只有内存地址。有没有办法只使用内存地址?大多数(如果不是所有)示例都让您使用函数的名称,而我没有。
If anyone could point me into the right direction so I can accomplish this task, I would greatly appreciate it. It also might help a lot of other people who may have the same question.
如果有人能指出我正确的方向,以便我完成这项任务,我将不胜感激。它也可能会帮助很多其他可能有同样问题的人。
Edit: I should also mention that Id rather not overload my program with someone else code, I really just want the barebones, much like a basic car with roll-up windows. No luxury packages for me please.
编辑:我还应该提到,我不想用其他人的代码重载我的程序,我真的只想要准系统,就像一辆带有卷帘窗的基本汽车。请不要给我豪华套餐。
采纳答案by Necrolis
You missed the most important part, is this for 32 or 64 bit code? In any case, the code project has a good run-down and lib herethat covers both.
你错过了最重要的部分,这是 32 位还是 64 位代码?在任何情况下,代码项目都有一个很好的破败和 lib在这里涵盖了两者。
If you want to do this "old-school", then it can be done quite simply:
如果你想做这个“老派”,那么它可以很简单地完成:
firstly, you need to find the virtual address of the function you want to hook (due to ASLR, you should never rely on it being in the same place), this is generally done with RVA + module base load address for function that are not exported, for exported functions, you can use GetProcAddress
.
首先,你需要找到你想要hook的函数的虚拟地址(由于ASLR,你永远不应该依赖它在同一个地方),这通常是用RVA+模块基加载地址来完成的导出,对于导出的函数,您可以使用GetProcAddress
.
From there, the type hook depends on what you want to accomplish, in your case, there are two methods:
从那里,类型挂钩取决于您要完成的任务,在您的情况下,有两种方法:
- patch a jump/call out to your function in the target function' prologue
- patch all call sites to the function you want to hook, redirecting to your function
- 在目标函数的序言中修补跳转/调用您的函数
- 将所有调用站点修补到您要挂钩的函数,重定向到您的函数
the first is simpler, but messy as it generally involves some inline assembly (unless you are hooking a /HOTPATCH
binary or you just want to stub it), the second is much cleaner, but requires a bit of work with a debugger.
第一个更简单,但很麻烦,因为它通常涉及一些内联汇编(除非您正在挂钩一个/HOTPATCH
二进制文件或您只想存根它),第二个更简洁,但需要使用调试器进行一些工作。
The function you'll jump out to should have the same parameters and calling convention (ABI) as the function you are hooking, this function is where you can capture the passed parameters, manipulate them, filter calls or whatever you are after.
您将跳转到的函数应该与您正在挂钩的函数具有相同的参数和调用约定 (ABI),您可以在此函数中捕获传递的参数、操作它们、过滤调用或您所追求的任何内容。
for both, you need a way to write some assembly to do the patching, under windows, WriteProcessMemory
is your first port of call (note: you require RWX permissions to do this, hence the calls to VirtualProtect
), this is a little utility function that creates a 32bit relative call or jump (depending on the opcode passed as eType
)
对于两者,您都需要一种编写一些程序集来进行修补的方法,在 Windows 下,这WriteProcessMemory
是您的第一个调用端口(注意:您需要 RWX 权限才能执行此操作,因此调用VirtualProtect
),这是一个创建32 位相对调用或跳转(取决于作为 传递的操作码eType
)
#pragma pack(1)
struct patch_t
{
BYTE nPatchType;
DWORD dwAddress;
};
#pragma pack()
BOOL ApplyPatch(BYTE eType, DWORD dwAddress, const void* pTarget)
{
DWORD dwOldValue, dwTemp;
patch_t pWrite =
{
eType,
(DWORD)pTarget - (dwAddress + sizeof(DWORD) + sizeof(BYTE))
};
VirtualProtect((LPVOID)dwAddress,sizeof(DWORD),PAGE_EXECUTE_READWRITE,&dwOldValue);
BOOL bSuccess = WriteProcessMemory(GetCurrentProcess(),(LPVOID)dwAddress,&pWrite,sizeof(pWrite),NULL);
VirtualProtect((LPVOID)dwAddress,sizeof(DWORD),dwOldValue,&dwTemp);
return bSuccess;
}
This function works great for method 2, but for method 1, you'll need to jump to an intermediary assembly trampoline to restore any code that the patch overwrote before returning to the original function, this gets very tedious, which is why its better to just use an existing and tested library.
此函数对于方法 2 非常有效,但对于方法 1,您需要跳转到中间程序集蹦床以恢复补丁覆盖的任何代码,然后再返回原始函数,这会变得非常乏味,这就是为什么最好只需使用现有的和经过测试的库。
From the sounds of it, using method 1 and patching a jump over the prologue of your target function will do what you need, as it seems you don't care about executing the function you patched.
从它的声音来看,使用方法 1 并修补跳过目标函数的序言将满足您的需求,因为您似乎并不关心执行您修补的函数。
(there is a third method using HW breakpoints, but this is very brittle, and can become problematic, as you are limited to 4 HW breakpoints).
(还有第三种使用硬件断点的方法,但这种方法非常脆弱,并且可能会出现问题,因为您只能使用 4 个硬件断点)。
回答by CashCow
Your "sample" is here:
您的“样本”在这里:
Normally when you "hook" into the DLL, you actually put your function in front of the one in the DLL that gets called, so your function gets called instead. You then capture whatever you want, call the other function, capture its return values and whatever else, then return to the original caller.
通常,当您“挂钩”到 DLL 中时,实际上是将您的函数放在 DLL 中被调用的函数前面,因此您的函数会被调用。然后捕获任何你想要的,调用另一个函数,捕获它的返回值和其他任何东西,然后返回到原始调用者。