游戏中模拟按键失效?试试Hook dxInput

前提 :现在很多游戏使用模拟按键基本都会失效,例如 sendinput 函数模拟鼠标键盘,也有部分游戏转换键盘为虚拟代码可以模拟,但是也存在封号的风险。如果是dx的游戏可 hook DirectInput函数,而如今现在多数 利用最多的是 IDirectInput8 ,因为这个支持的种类多,具体可以百度。

具体有两个函数可以hook 之后可以注入鼠标以及键盘,即支持所有的键鼠操作,如果人家想检测那边封号肯定也是包封的,只是国内没什么帖子说这个。

其中一个是如下函数

HRESULT GetDeviceState(
         IDirectInputDevice8* pThis,
         DWORD cbData,
         LPVOID lpvData
)
函数自行谷度,我会给例子

函数2

HRESULT GetDeviceData(
         IDirectInputDevice8* pThis,
         DWORD cbObjectData,
         LPDIDEVICEOBJECTDATA rgdod,
         LPDWORD pdwInOut,
         DWORD dwFlags
)

本人尝试过写一个win32的例子 发现第一个和第二个函数都可以使用,但是实战中发现游戏不少用第二个函数,第二个函数 GetDeviceData   参数   LPDIDEVICEOBJECTDATA  rgdod ,里面保存当前游戏中按下的键盘鼠标队列,因此可以修改这个参数的值达到注入按键和鼠标的用处。 

代码如下 复制应该可以用的,需要自己使用minhook库,之后注入游戏。其他APIhook 框架也可以。

#pragma once
#define DIRECTINPUT_VERSION 0x0800
#include "framework.h"
#include <dinput.h>
#include <iostream>
#include "MinHook.h"
#include <cstdlib> 
#include <deque>
#pragma comment(lib, "Dinput8.lib")
#pragma comment(lib, "Dxguid.lib")

	extern HMODULE g_hModule;
	inline volatile bool inject_mouse_flag;
	inline std::deque<std::pair<int, bool>> keyboard_deque;

	typedef HRESULT(__stdcall* GetDeviceDataT)(IDirectInputDevice8*, DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD);
	static GetDeviceDataT pGetDeviceData = nullptr; // original
	HRESULT __stdcall hookGetDeviceData(IDirectInputDevice8* pThis, DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags);
	typedef HRESULT(__stdcall* GetDeviceStateT)(IDirectInputDevice8* pThis, DWORD cbData, LPVOID lpvData);
	typedef HRESULT(__stdcall* GetDeviceDataT)(IDirectInputDevice8*, DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD);
	static GetDeviceStateT pGetDeviceState = nullptr; //pointer to original function


	static uintptr_t get_function_address(LPDIRECTINPUTDEVICE8 lpdid, int index)
	{
		uintptr_t avTable = *((uintptr_t*)lpdid);                   // 虚函数表地址
		uintptr_t pFunction = avTable + index * sizeof(uintptr_t);  // 虚函数表项的地址
		return *((uintptr_t*)pFunction);                            // 目标函数地址
	}
	static HRESULT __stdcall hookGetDeviceState(IDirectInputDevice8* pThis, DWORD cbData, LPVOID lpvData) {
	
		HRESULT result = pGetDeviceState(pThis, cbData, lpvData);

		
		//if (cbData == sizeof(DIMOUSESTATE)) {
		//	if (((LPDIMOUSESTATE)lpvData)->rgbButtons[0] != 0) {
		//		printf("left %x", ((LPDIMOUSESTATE)lpvData)->rgbButtons[0]);
		//		std::cout << "[LMB]" << std::endl;
		//	}
		//	if (((LPDIMOUSESTATE)lpvData)->rgbButtons[1] != 0) {
		//		printf("right %x", ((LPDIMOUSESTATE)lpvData)->rgbButtons[0]);
		//		std::cout << "[RMB]" << std::endl;
		//	}
		//}
		//if (cbData == sizeof(DIMOUSESTATE2)) {//caller is also a mouse but different struct
		//	if (((LPDIMOUSESTATE2)lpvData)->rgbButtons[0] != 0) {
		//		std::cout << "[LMB2]" << std::endl;
		//		printf("left %x", ((LPDIMOUSESTATE2)lpvData)->rgbButtons[0]);
		//	}
		//	if (((LPDIMOUSESTATE2)lpvData)->rgbButtons[1] != 0) {
		//		std::cout << "[RMB2]" << std::endl;
		//		printf("right %x", ((LPDIMOUSESTATE2)lpvData)->rgbButtons[1]);
		//	}
		//}

		return result;

	}


	/**
	 * 参数1 按键key 例如 DIK_W
	 * 参数2 是否按下 按下为true 放开false 
	 * 
	 * 使用方式
	 * inject_keys(DIK_W ,true)
	 * inject_keys(DIK_W ,false)
	 */

	 inline void inject_keys(int key)
	{
		 keyboard_deque.push_back(std::make_pair(key, true));
		// keyboard_deque.push_back(std::make_pair(key, false));
	}

	 //模拟右键点击
	inline void inject_mouse()
	{
		inject_mouse_flag = true;
	}
	//释放右键点击
	inline void stop_mouse_inject()
	{
		inject_mouse_flag = false;
	}


	static HRESULT __stdcall hookGetDeviceData(IDirectInputDevice8* pThis, DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) {
		HRESULT result = pGetDeviceData(pThis, cbObjectData, rgdod, pdwInOut, dwFlags);
		
		//HRESULT result = veh::CallOriginal<HRESULT>(pGetDeviceData, pThis, //cbObjectData, rgdod, pdwInOut, dwFlags);

		static ULONGLONG timeStart = 0;
		if (keyboard_deque.size()>0)
		{
			 
			ULONGLONG timeEnd = GetTickCount64();
			//五秒注入一次不能太离谱好的机械键盘一般是五毫秒
			if (timeEnd - timeStart > 700)
			{
				auto r = keyboard_deque.front();
				timeStart = GetTickCount64();
				rgdod[*pdwInOut].dwData = (r.second? 0x80 : 0x0);
				rgdod[*pdwInOut].dwOfs = r.first;
				*pdwInOut = *pdwInOut + 1;
				keyboard_deque.clear();
				
			}


		}

		if (inject_mouse_flag)
		{
			rgdod[*pdwInOut].dwData = 0x80;
			rgdod[*pdwInOut].dwOfs = DIMOFS_BUTTON1;
			*pdwInOut = *pdwInOut + 1;
			rgdod[*pdwInOut].dwData = 0x0;
			rgdod[*pdwInOut].dwOfs = DIMOFS_BUTTON1;
			*pdwInOut = *pdwInOut + 1;
		}


		return result;
	
	}


	static void __stdcall hook_dinput()
	{

	
	if (MH_Initialize() != MH_OK && MH_Initialize() != MH_ERROR_ALREADY_INITIALIZED)
		{
			printf("MH_Initialize hook_input error \n");
		}

		IDirectInput8* pDirectInput = nullptr;
		if (DirectInput8Create(g_hModule, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)& pDirectInput, NULL) != DI_OK) {
			printf("DI Create failed! \n");
		}

		LPDIRECTINPUTDEVICE8 lpdiMouse;

		if (pDirectInput->CreateDevice(GUID_SysMouse, &lpdiMouse, NULL) != DI_OK) {
			pDirectInput->Release();
			std::cout << "CreateDevice failed!" << std::endl;
		}

		auto hook_start = get_function_address(lpdiMouse, 9);

		if (MH_CreateHook((LPVOID)hook_start, &hookGetDeviceState, reinterpret_cast<LPVOID*>(&pGetDeviceState)) != MH_OK || MH_EnableHook((LPVOID)hook_start) != MH_OK)
			{
				printf("hook getdecive error");

			}

		hook_start = get_function_address(lpdiMouse, 10);

		//veh::Setup();

		//veh::Hook((LPVOID)hook_start, hookGetDeviceData);
		pGetDeviceData = (GetDeviceDataT)hook_start;

		if (MH_CreateHook((LPVOID)hook_start, &hookGetDeviceData, reinterpret_cast<LPVOID*>(&pGetDeviceData)) != MH_OK || MH_EnableHook((LPVOID)hook_start) != MH_OK)
		{
			printf("hook hookGetDeviceData error");
		}



	}

调用 inject_keys 即可模拟键盘点击

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值