WIN钩子注入

在Windows系统下,每个进程都拥有独立的资源空间,采用的是虚拟地址。
简单来说,即使你知道另一个进程的某个变量的内存地址,你却没办法使用别的进程来直接访问的。
哪怕这个地址的是通过 malloc() 等分配的动态内存也不行的。
一般而言,我们通过给指定进程注入我们指定的动态库,使其在同一个进程中,然后在通过指定地址访问到某个变量,读取或修改其值。


通常这样的注入的方式有两种:
1.由指定进程被动的加载该动态库(钩子注入)。
2.由指定进程主动的加载该动态库(远线程注入)。


Windows消息机制:由系统生成消息,然后颁发给指定应用程序,应用程序来处理。

我们可以给指定的线程,安装一个钩子程序,来监听这个程序的消息。

这话怎么理解?一听就迷糊了…

我说的简单一点:我们可以编写 一个函数,去监听 指定线程的 Windows消息。

什么个原理?

我们编写一个 动态库,然后去给指定的线程安装一个挂钩函数,当产生消息的时候,这个指定的线程就要调用我们指定的 钩子函数,如果它们是不同的进程,这个是办法进行调用的,所以操作系统会将该动态库加载到指定的线程中去,这样就达到了我们的目的,注入动态库。

以植物大战僵尸为例子

代码实现

DLL动态库代码

.h 文件

#pragma once
#include<Windows.h>

#define EXPORT	__declspec(dllexport)
/*
\ brief		键盘钩子过程
*/
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam);
/*
\ brief		安装键盘钩子
*/
bool EXPORT SetHook(DWORD pThreadId);

.cpp 文件

#include "Hook.h"

/*
\ brief		键盘消息钩子函数(必须是__stdcall 调用)
\ param		code		消息的信息
\ param		wParam		生成击键消息的键的虚拟键代码
\ param		lParam		先前的键状态标志和过渡状态标志
*/
LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
	// 如果是wParam和lParam的参数包含关于一个按键消息的信息
	// 如果 按下的是 Home 键
	// 如果 按键状态是激活
	if ((code == HC_ACTION) && (wParam == VK_HOME) && GetKeyState(VK_HOME)) {
		// 植物大战僵尸 阳光基址 [[006A9EC0]+768]+5560
		size_t address = 0x006A9EC0;
		address = *reinterpret_cast<size_t*>(address) + 0x768;
		address = *reinterpret_cast<size_t*>(address) + 0x5560;
		size_t* pointer = reinterpret_cast<size_t*>(address);
		// 将阳光修改为 9999
		*pointer = 9999;
	}
	// 传递给下一个挂钩
	return CallNextHookEx(nullptr, code, wParam, lParam);
}

/*
\ brief		安装钩子
\ param		指定的线程
\ return 	成功返回true,失败返回false
*/
bool EXPORT SetHook(DWORD pThreadId)
{
	/*
	\ brief		安装消息钩子
	\ param		KeyboardProc 钩子过程函数
	\ param		钩子过程所在的DLL模块句柄
	\ param		挂钩的线程
	\ return 	成功返回挂钩过程的句柄,失败返回NULL
	*/
	return SetWindowsHookExW(WH_KEYBOARD,
							 KeyboardProc, 
							 GetModuleHandleW(TEXT("Hook.dll")), 
							 pThreadId);
}
DLL动态库重点项目属性

动态库
动态库

注入代码

Hook.h

#pragma once
#include<Windows.h>

#define IMPORT	__declspec(dllimport)

//LRESULT CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam);

bool IMPORT SetHook(DWORD pThreadId);

main.cpp

#include<iostream>
#include<Windows.h>
#include"Hook.h"		// 引入 动态库的头文件

using namespace std;

int main(int argc, char* argv[])
{
	// 获取游戏窗口句柄
	HWND mHwnd = FindWindowW(nullptr, TEXT("植物大战僵尸中文版"));
	if (mHwnd == NULL) {
		cout << "error FindWindowW" << endl;
		system("pause");
		return 0;
	}

	DWORD pId;
	 // 获取 游戏进程和线程ID
	DWORD tId = GetWindowThreadProcessId(mHwnd, &pId);
	
	// 安装钩子,传入线程的ID
	if (SetHook(tId)==false) {
		cout << "error " << endl;
	}
	else {
		cout << "yes ok " << endl;
	}
	// 卡住程序,不让程序退出。
	system("pause");
}

重点截图
项目
项目

先启动植物大战僵尸和然后注入程序(不要让程序退出)
植物大战僵尸

点击植物大战僵尸,然后按下 Home 键(不要让程序退出)
Home键

文章时间2019年12月18日15:49:25

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值