HOOK技术实现键盘记录器
远程注入 DLL 实现进程隐藏以及键盘记录器
在这篇文章里我将详细讲述从创建 DLL 实现键盘记录到将该 DLL 注入到指定的进程中以实现隐藏进程的过程。
首先第一步我们要编写一个能够实现键盘记录的 DLL 文件,实现键盘记录的方法有很多,这里我采用的是 HOOK 系统消息 WH_KEYBOARD 的方式实现记录键盘的输入内容。
在我讲述程序实现思路之前,有一点需要跟各位说明一下。我需要先说一下 DllMain ()这个函数。对于这个函数我总结了 3 点:
第一点:标志。
一个 DLL 加载到了一个进程中,它到底加载到哪里去了?这是一个疑问,我们知道在 Windows 下每个进程都有一个句柄,其实每个被加载的 DLL 也有一个句柄(但是在一般情况下我们不太关注这个句柄),这个句柄可以理解成这个 DLL 的一个标志,通过这个句柄我们可以找到关于这个 DLL 的很多信息,其中当然也包括“加载到哪里了”。这个句柄就是 DLLMain ()函数中的第一个参数所指定的,他是有系统分配的,我们在程序中可以直接调用。
第二点:大门。
“大门”两字该如何理解呢?其实很简单,就如同我们家里的门一样,你要想从回家或者是去上班都要走大门,那么对于 DLL 文件呢?众所周知, DLL 里面存放的是函数,你想要是用 DLL 中的函数,首先要经过“大门”;你使用完了这些函数,不想在用这个 DLL 了,需要先离开了,那么也要经过大门。(当然这个理解有点狭隘,但是我想对于初学者来说是足够了。随着以后对 DLL 文件的不断深入了解,你必然会对这个函数有个重新的理解吧~)。“大门”二字对应的是 DLLMain ()函数的第三个参数 lpReserved , lpReserved 会指定你当前通过这个“大门”是处于那种状态(进或者是出)。在 windows 下这个参数有以下四个值:
DLL_PROCESS_ATTACH 进程加载DLL
DLL_PROCESS_DETACH 进程卸载DLL
DLL_THREAD_ATTACH 线程加载DLL
DLL_THREAD_DETACH 线程卸载DLL
我们可以看到,抛开进程与线程的区别,它其实只有两个含义:加载与卸载。而加载也就是我说的“进”,卸载也就是我说的“出”。那么什么情况下会走到“进”这条路,什么情况下会走到“出”这条路呢?有个很简单的判断,用 LoadLibrary() 函数动态链接 DLL 文件的时候走的就是“进”,用 FreeLibrary() 函数来解除 DLL 文件时走的就是“出”。除此之外还有静态加载 / 解除 DLL ,这里就不多讲了。
第三点:控制器。
这点我想了很多词都无法表达我想要的那个意思,只能找一个比较贴近的词来形容一下了。
在一般情况下,对于大多数人来,我们在编程 DLL 文件的时候可以不必要关心 DllMain() 函数的,因为 DLL 的主要功能是提供以下可供程序调用的函数。但是在某些情况下, DLL 会舍弃它的这个功能,但是他的作用依然强大。比如以下:
现在假设某 DLL 不对为提供任何一个函数,但是其内部却存在大量的函数。(只是不对外提供,并不等于没有~~)。从前面我们知道, DLL 在被加载的时候会运行 DllMain ()函数,那么我们现在完全可以在 DllMain ()函数中创建一个线程,在创建的线程中执行该 DLL 文件中的代码(比方说我们这里键盘记录)。 DllMain 函数通过在加载 / 解除 DLL 时候控制程序的运行,这里基本上起到了一个控制器的作用。
关于 DllMain() 函数就说这么多吧。我说的都是我在程序中需要用到的地方,关于 DllMain 以及 Dll 文件更多的描述大家就到网上参考吧。
接下来我会详细说一下实现键盘记录的整个过程。
第一步:创建 Dll 文件,该 Dll 文件是整个程序的核心,它具体的实现了键盘记录器的核心功能。
1 创建 Dll 文件
2 建立共享数据段,关于共享数据段的建立参照以下程序:
#pragma data_seg ("mydata")
FILE *fp = NULL; /* 该指针指向我们需要打开的文件以存放从键盘输入的信息 */
int num = 0; /* 输入文件的字符数 */
#pragma data_seg ()
#pragma comment (linker,"/section:mydata,rws")
3 定义全局键盘钩子指针
HHOOK glhHookKey = NULL; /* 在为系统消息 WH_KEYBOARD 挂钩之后会返回该指针 */
4 定义当前 DLL 句柄指针
HINSTANCE glhInstance=NULL; /* 如前面所述,该指针将在 DllMain() 函数中进行初始化 */
5 定义函数 starthook() ,如同该函数名字一样,这是用来开始为 系统消息 WH_KEYBOARD 挂钩
int starthook()
{
int num=0;
/* SetWindowsHookEx () 函数为加载钩子的主要函数,大家可以在网上详细查看一下该函数的用法