VC注入dll后,如何用代码实现inline hook?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC注入dll后,如何用代码实现inline hook?相关的知识,希望对你有一定的参考价值。

最近在研究inline hook,但是没找到合适的代码例子做参考。
现在我在用植物大战僵尸这个小游戏做练习。现在的目标就是,在点击拾取阳光的时候,希望能随意控制拾取到的阳光值,比如拾取到的阳光值翻一倍,两倍,这种。
现在我可以在OD下使用inline patch的方式实现这个,其实很简单,在阳光值修改位置写入一个jmp,然后跳到一个00填充的无用位置,写入汇编代码修改阳光值,比如 imul eax,eax,2这样,可以翻一倍。最后jmp回去,就OK了。
现在我想用代码实现这个过程,但是没搞过,不太懂。
详细点的要求就是,构造一个用于hook的结构体,大致是这样:

struct JmpHook

DWORD hookAddr //要hook的目标地址,会在此处写入jmp指令
DWORD hookProc //jmp的跳转位置,即hook挂接的处理函数
int[] code //hookAddr后的一段汇编指令,用于卸载inline hook时的恢复现场

这个结构体中的第三个数据成员 code,没太想好改怎么弄。我想的是通过这么一个结构来记录hook相关的信息,然后在卸载的时候进行恢复,在hook的时候,会读取hook点后面的指令填充到code中。jmp过去的会是一个函数。
求hook和unhook函数的写法。或者不用这个结构体也行,请给出合理的实现。
如果嫌麻烦,给点提示也可以不过我会追问。只要能帮我搞定这个问题就行了,这个具体的代码谁来写无所谓,给我说下关键点,我自己写也行。

最常用的DLL注入是借助CreateRemoteThread() 函数,把LoadLibrary()做为线程函数的地址实现注入,网上的大部代码都是这样的。早期有一款安全类的工具,叫mt.exe 它里面有一个mt.exe -su的命令,就是使用的这种方法,我找了一个我原来写的实例。我直接打包了。


另外一种是直接PE注入。这类似于病毒感染的方法,大体上的思维就是在游戏的可执行文件中寻找空段。写入类似于shellcode一段精简代码,这段代码实现你想要的功能,最后你修改pe文件的入口点即可。这样就实现了一种劫持。这个实例代码不知道放哪里去了,但是找到一个分析红客联盟创始人lion写的shellcode的一篇笔记,我一起打包了,应该会对你有所帮助。这方面的资料网上很多的,不是什么新东西了。


如果你要实现的代码很少,完全可以把指令当成一个char类型的数组,直接写入pe的空段就可以了,如果很多,可以新建立一个PE空段,再写入,或者直接将要执行的代码写入到一个DLL中封装。。


 

参考技术A 关键点吗……
1、恢复现场,要存多少字节根据你填入的jmp占用多少字节而定,jmp rel32是5个字节。
2、od找0那一段,程序操作的话你可以用malloc申请的内存来,而不一定是exe里的0
3、VirtualProtect调用可以使代码段可写(否则修改的时候会出现写入异常,程序崩溃)
4、jmp rel32指令的机器代码是 E9 rel32 一共5个字节。如果嫌计算相对地址麻烦你也可以用 jmp mem32,机器指令是FF 25 mem32(没记错的话……也有可能是FF 15)。但是我觉得这样更麻烦
5、jmp rel32指令中,rel32相对的是执行jmp之后的eip。例如
40000: E9 11 22 33 44
40005: ......
那么翻译过来就是
40000: jmp 44372216
6、不确定要hook的代码位置的指令多长的话,你可能需要一个反汇编库来确定,当然更容易(但是不通用)的方式是人工查看……跳转来跳转去记得一定要跳转到机器代码边界上,比如刚才那个
40000: E9 11 22 33 44
你不可以跳转到(40000, 40005)区间的任何一个地址上,但是可以跳转到40000或40005地址上。本回答被提问者和网友采纳

C++实现inline hook,注入后程序异常退出

被hook函数的地址为0x00492770。
实现代码如下:
#pragma pack(1)
typedef struct _JMPCODE

BYTE jmp; //E9 1字节
DWORD addr; //0x地址 4字节
JMPCODE,*PJMPCODE;

typedef int (__stdcall *myFunction)(LPCTSTR lpDesc, LPCTSTR lpSrc, int iLen);
myFunction oldFunctionAddr = (myFunction)0x00492770;

__declspec(naked) void __stdcall My_Function(LPCTSTR lpDesc, LPCTSTR lpSrc, int iLen)

//gameData << "My_Function Enter! " << endl;
__asm

push ebp
mov ebp,dword ptr[esp+10]
push esi


printf("---------printf %s------", lpSrc);
__asm

pop esi
mov ebx,oldFunctionAddr
add ebx,5
jmp ebx



VOID InLine_HookFunctionA()

JMPCODE Jmpcode;
Jmpcode.jmp=0xe9;
Jmpcode.addr=(DWORD)(My_Function)-(DWORD)(oldFunctionAddr)-5;

int ret = WriteProcessMemory(GetCurrentProcess(),oldFunctionAddr,&Jmpcode,sizeof(JMPCODE),NULL);


调用0x00492770的代码如下:
00CD4EEB . 51 push ecx
00CD4EEC . 8DAE 1C200000 lea ebp, dword ptr [esi+0x201C] ; |
00CD4EF2 . 50 push eax
00CD4EF3 . 52 push edx
00CD4EF4 . 8BCD mov ecx, ebp ; |
00CD4EF6 . 896C24 1C mov dword ptr [esp+0x1C], ebp ; |
00CD4EFA . E8 71D87BFF call 0x00492770

异常提示信息如下:
(13d0.1738): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=013cc320 ebx=00492775 ecx=00000000 edx=0dc4fe34 esi=00000000 edi=00000000
eip=00492779 esp=0dc4fe08 ebp=00000000 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202
*** ERROR: Symbol file could not be found. Defaulted to export symbols for D:\xxxx\aaaa.exe
aaaa+0x92779:
00492779 8b4604 mov eax,dword ptr [esi+4] ds:0023:00000004=????????

从获取异常日志看是aaaa+0x92779异常导致,但没明白什么原因。哪位大侠帮忙分析下给点提示。谢谢!

参考技术A 你要搞清楚一个概念,DLL被加载后地址是要重定位的,所有的全局变量、函数这些,都会随DLL加载的基址不同,地址会进行对应偏移的。

你WriteProcessMemory那句,往oldFunctionAddr地址写东西,肯定会引起异常的,谁知道被你hook的程序这个地址是啥东西?有没有分配过内存呢?

你要往被注入进程写东西,就必须先用VirtualAllocEx申请内存,你一定要牢记这个概念,所有地址都是动态的,函数、全局变量只有偏移量是固定的。

以上是关于VC注入dll后,如何用代码实现inline hook?的主要内容,如果未能解决你的问题,请参考以下文章

vc 无dll的代码注入

C++实现inline hook,注入后程序异常退出

如何用VC编写一个程序,运行打开指定网页

C#如何用程序把文本文件打包成dll文件

vc运行c程序时出现没有匹配的符号信息?如何处理?

C+的dll如何用易语言正确调用?