利⽤HOOK技术实现DLL远程进程注⼊
上⼀篇博⽂《HOOK钩⼦教程》中,作者较为详细地讲述了如何使⽤HOOK,并举了⼀个例⼦:⽤HOOK拦截WM_CLOSE消息⼀次。
实际上,HOOK有多种⽤法,本⽂讲述其中⼀种:利⽤HOOK技术实现DLL远程进程注⼊。
远程进程注⼊,按照作者的理解,就是让其他进程替你并运⾏DLL中的代码。⽽上⼀篇博⽂中,作者讲到对其他进程安装钩⼦时,钩⼦的过程必须封装在DLL中,就是说HOOK的代码被执⾏的时候,⽬标进程实际上就是在执⾏DLL中的代码。于是注⼊的思路就有了,把要执⾏的函数封装在DLL中,同时把HookProc写在同⼀个DLL中,HOOK成功了之后,接收到消息的HookProc就会执⾏,于是就能执⾏想执⾏的代码了。
还有⼀个问题,那就是HookProc是回调函数,要等到有消息传来的时候才会被调⽤,⽽DLL注⼊要让线程主动执⾏DLL中的代码。那要怎么做呢?
其实也很简单,上⼀篇博⽂中,最后的例程⾥,DllMain给记事本主动发了⼀个WM_CLOSE消息,HookProc便被执⾏了。
完整的流程就出来了:
⾸先SetWindowsHookEx设置了钩⼦,然后PostMessage给⽬标进程发送消息,在HookProc中判断是不是这个消息,是就执⾏相应代码,并阻⽌该消息传递到⽬标进程,最后调⽤UnhookWindowsHookEx卸载钩⼦。
第⼆步中,要给⽬标进程发送⼀个消息,那到底应该发送什么消息才好呢?作者作了多次尝试,发现WM_KEYDOWN、WM_CREATE等消息均⽆效(估计是后⾯的参数没设置好,如果有知道具体原因的,欢迎在评论中留⾔讨论),⽽WM_CLOSE和WM_DESTROY能被捕获。作者在这⾥选择了WM_CLOSE。
接收到这个消息之后,HookProc便弹出⼀个MessageBox表⽰注⼊成功:
MessageBox(NULL,”This is a messagebox ”,”hook”,MB_OK);
所以整个HookProc的代码如下:
extern “C” __declspec(dllexport) LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam){
if(nCode<0)
return CallNextHookEx(hooker,nCode,wParam,lParam);
tagMSG* msg;
msg=(tagMSG*)lParam;
if(nCode==HC_ACTION && (msg->message==WM_CLOSE)){
if(handled==FALSE){
handled=TRUE;
MessageBox(NULL,”This is a messagebox ”,”hook”,MB_OK);
}
UnhookWindowsHookEx(hooker);
msg->message=WM_NULL;
return CallNextHookEx(hooker,nCode,wParam,(LPARAM)msg);
}
return CallNextHookEx(hooker,nCode,wParam,lParam);
}
⽽DllMain则负责进⾏钩⼦的安装,所以整个DLL的代码如下:
// notepadhook.cpp : Defines the entry point for the DLL application.
//
#include “stdafx.h”
#include <stdio.h>
#include <stdlib.h>
HHOOK hooker;
HWND notepadhandle;
BOOL handled;
extern “C” __declspec(dllexport) LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam);
char* ConvertInttoChar(int i);
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved){
if(ul_reason_for_call==DLL_PROCESS_ATTACH){
handled=FALSE;
notepadhandle=FindWindow(“Notepad”,NULL);
if(notepadhandle==NULL){
printf(“Notepad Not Found.\n”);
return TRUE;
}
hooker=SetWindowsHookEx(WH_GETMESSAGE,HookProc,
(HINSTANCE)hModule,GetWindowThreadProcessId(notepadhandle,NULL));
if(hooker){
printf(“Hook Successfully.\nHookID:%d\n”,hooker);
}
else{
printf(“Hook Failed.\nError:%d\n”,GetLastError());
return TRUE;
}
PostMessage(notepadhandle,WM_CLOSE,0,0);
}
return TRUE;
}
extern “C” __declspec(dllexport) LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam){
if(nCode<0)
return CallNextHookEx(hooker,nCode,wParam,lParam);
tagMSG* msg;
msg=(tagMSG*)lParam;
if(nCode==HC_ACTION && (msg->message==WM_CLOSE)){
if(handled==FALSE){
handled=TRUE;
MessageBox(NULL,”This is a messagebox ”,”hook”,MB_OK);
}
UnhookWindowsHookEx(hooker);
msg->message=WM_NULL;
return CallNextHookEx(hooker,nCode,wParam,(LPARAM)msg);
}
return CallNextHookEx(hooker,nCode,wParam,lParam);
}
新建⼀个DLL⼯程,命名为notepadhook,如图:
在notepadhook.cpp中键⼊如上代码,编译连接得到notepadhook.dll。
新建⼀个C++ Source File,命名为hook:
键⼊如下代码以加载DLL:
#include <stdio.h>
#include <windows.h>
int main(){
LoadLibrary(“notepadhook.dll”);
getchar();
return 1;
}
编译连接得到,将与notepadhook.dll放在同⼀⽬录中,打开记事本,运⾏,可以看到记事本中弹出了⼀个消息框,如图:
如上图所⽰,对话框是从记事本弹出的,说明注⼊已经成功。
⾄此,我们的DLL注⼊已经完成了,但是还有⼀些问题。就算我们把所有的printf去掉,也把getchar去掉⽽改成Sleep,打开程序依然会有⼀个⿊框,根本没办法做到隐蔽。作者经查阅资料得知这是因为编译器给EXE加上了某些参数,作者的解决办法是⽤RADASM编写⼀个⼀样功能的EXE:
新建⼀个Win32 App⼯程,在Asm⽂件中键⼊如下代码:
.386
.model flat, stdcall
option casemap :none ;case sensitive
include windows.inc
notepad++include kernel32.inc
includelib kernel32.lib
assume cs:xCode
xCode segment
.data
xDllName db ’notepadhook.dll’,0
.
code
start:
invoke LoadLibrary,offset xDllName
invoke Sleep,1000
invoke ExitProcess,NULL
end start
编译构建得到exe,将exe与dll放到同⼀⽬录,运⾏记事本,运⾏EXE,发现⿊框就没了,⽽且即使DLL有printf也不会出现⿊框。
以上是《利⽤HOOK技术实现DLL远程进程注⼊》的全部内容,对于⽂中内容有疑问的,或有改进意见的,欢迎通过评论留⾔。(作者仅对X_TK博客中的评论进⾏回复,转载⾄其他论坛及博客的,本作者概不负责)。感谢您阅读本⽂。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论