我有一个内存地址,它是另一个程序(其中一个dll)中函数的内存地址.我已经通过DLL注入加载到程序中.我已经有了低音地址,以及每次程序加载时函数的实际位置.所以,这不是问题.
我想简单地挂钩该位置,并获取变量.我知道函数的伪代码.所以这不是问题.或者另一种很棒的方法是在该存储器位置执行断点并获取调试寄存器.
我找不到任何明确的例子.我也没有该功能的"名称",我只有内存地址.有没有办法只使用内存地址?大多数(如果不是全部)示例都使用了我没有的函数名称.
如果有人能指出我正确的方向,那么我可以完成这项任务,我将非常感激.它也可以帮助很多其他可能有同样问题的人.
编辑:我还应该提到Id而不是用其他代码重载我的程序,我真的只想要准系统,就像一个带有卷帘窗的基本车.请不要给我豪华套餐.
您错过了最重要的部分,这是32位还是64位代码?无论如何,代码项目都具有良好的运行环境,此处的 lib 涵盖了这两个方面。
如果您想做这个“老派”,那么可以很简单地完成:
首先,您需要找到要挂接的函数的虚拟地址(由于ASLR,您永远不应依赖它位于同一位置),这通常是通过RVA +模块基本加载地址来完成的导出,对于导出功能,可以使用GetProcAddress。
从那里开始,类型挂钩取决于您要完成的工作,在这种情况下,有两种方法:
第一个比较简单,但是很混乱,因为它通常涉及一些内联汇编(除非您钩住/HOTPATCH二进制文件或只想存根它),第二个则干净得多,但是需要调试器进行一些工作。
您将跳到的函数应该具有与所挂接的函数相同的参数和调用约定(ABI),在该函数中,您可以捕获传递的参数,对其进行操作,过滤调用或执行后续操作。
对于这两种方式,您都需要一种方法来编写一些程序集以进行修补,在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;
}
Run Code Online (Sandbox Code Playgroud)
此函数对方法2很有用,但是对于方法1,您需要跳到中间程序汇编蹦床以恢复补丁覆盖的所有代码,然后再返回原始功能,这变得非常乏味,这就是为什么这样做更好的原因只需使用现有的经过测试的库即可。
从它的声音来看,使用方法1并修补目标函数的序言中的跳转将满足您的需求,因为您似乎并不在乎执行所修补的函数。
(存在使用HW断点的第三种方法,但这非常脆弱,并且可能会出现问题,因为您仅限于4个HW断点)。