H 头文件
#ifndef __Cmd_Api__
#define __Cmd_Api__
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的信息
#include <windows.h>
#include <stdio.h>
#define CN_PUB_Server_Ip "127.0.0.1"
#define CN_PUB_Server_Port 36868
#define CN_PUB_DEFHINT "未解析"
//
const char* CN_PUB_INI_Title = "Set";
const char* CN_PUB_INI_Host = "ServerHost";
const char* CN_PUB_INI_Port ="ServerPort";
//
#define CN_PUB_RES "CmdRes\\"
#define CN_PUB_CFGFILE "Cfg.ini"
#define CN_PUB_APINAME "CmdApi.dll"
//
const int CN_CMDBUFFSIZE = 0x3000;
#define P_ERROR(Condition) if (!(Condition)) goto Exit0;
//输出调试信息标志位
#define LOG_DBG 1
#if LOG_DBG
#define CN_LOG_TAG "CmdPlugin "
#endif
#pragma pack(push, 1)
//特殊Hook 堆栈保存结构
typedef struct _HookCodeExParam32
{
DWORD dwEax, dwEbx, dwEcx, dwEdx, dwEsp, dwEbp, dwEsi, dwEdi;
}THookCodeExParam32,*PHookCodeExParam32;
//滤境解析结果
typedef struct _FilterRet
{
bool bVis;
bool bCom;
char cName[128];
}TFilterRet,*PFilterRet;
//Init
typedef void (__stdcall *TCmdApiInit)(void* Param);
//UnInit
typedef void (__stdcall *TCmdApiUnInit)();
//特征码扫描
typedef unsigned int (__stdcall *TCmdApiMemSigScan)(char* cModName,char* cSigCode);
//CheckBox控制函数
typedef void (__stdcall *TMyCheckBoxProc)(bool bCheck);
//创建CheckBox
typedef bool (__stdcall *TCmdApiCreateCheckBox)(char* cCaption,TMyCheckBoxProc onClick,bool bCheck);
//滤镜解析
typedef bool (__stdcall *TCmdApiFilterOper)(char* pData,int iDataLen,unsigned char byOrd,PFilterRet pRet);
//写HexLog
typedef void (__stdcall *TCmdApiWriteLogProc)(char* sType,char* sTypeEx,char* pData,int iDataLen,int iSock);
//执行指令
typedef void (__stdcall *TCmdApiExecuteCmdProc)(char* sHexCmd);
//设置执行指令函数
typedef void (__stdcall *TCmdApiSetFunc_ExecuteCmd)(TCmdApiExecuteCmdProc pFunc);
//标准Hook
typedef void (__stdcall *TCmdApiHookCodeNormal)(void* CodeAdr,void* NewFunc,void* OldFunc);
//标准UnHook
typedef bool (__stdcall *TCmdApiUnHookCodeNormal)(void* nextHook);
//特殊Hook,直接寄存器操作,方便用于代码被VM的情况
typedef void* (__stdcall *TCmdApiHookCodeEx)(void* CodeAdr,void* NewFunc);
//特殊UnHook
typedef void (__stdcall *TCmdApiUnHookCodeEx)(void* OldFunc);
//设置发送Sock
typedef void (__stdcall *TCmdApiSetSendSock)(int iSock);
//获取设置的发送Sock
typedef int (__stdcall *TCmdApiGetSendSock)();
//判断是否是工具Sock
typedef bool (__stdcall *TCmdApiIsToolSock)(int iSock);
//
typedef struct _InitIO
{
//Api接口
typedef struct _CmdApi
{
char Path[MAX_PATH];
HMODULE Handle;
TCmdApiInit Init;
TCmdApiUnInit UnInit;
TCmdApiMemSigScan MemSigScan;
TCmdApiCreateCheckBox CreateCheckBox;
TCmdApiFilterOper FilterOper;
TCmdApiWriteLogProc WriteLog;
TCmdApiSetFunc_ExecuteCmd SetFunc_ExecuteCmd;
TCmdApiHookCodeNormal HookCodeNormal;
TCmdApiUnHookCodeNormal UnHookCodeNormal;
TCmdApiHookCodeEx HookCodeEx;
TCmdApiUnHookCodeEx UnHookCodeEx;
TCmdApiSetSendSock SetSendSock;
TCmdApiGetSendSock GetSendSock;
TCmdApiIsToolSock IsToolSock;
}TCmdApi,*PCmdApi;
//工具所在目录
char sPath[MAX_PATH];
//控制端Ip
char sIp[20];
//控制端Port
int iPort;
TCmdApi Api;
}TInitIO,*PInitIO;
//API接口
TInitIO g_InitIO= {0};
//默认配置文件
char g_Cfg[MAX_PATH] = {0};
//用于获取存储模块自身句柄
HMODULE g_hModuleThisDll = 0;
//预留执行的buff
char g_ExecuteCmdBuff[CN_CMDBUFFSIZE] = {0};
#pragma pack(pop)
//记录调试信息
void LogDbg( char* fmt,... )
{
#if LOG_DBG
int i = 0;
char output[0x200] = {0};
try{
strcat_s(output,0x200,CN_LOG_TAG);
va_list arg_ptr;
va_start(arg_ptr, fmt);
int iTagLen = strlen(CN_LOG_TAG);
i = _vsnprintf_s(&output[iTagLen],0x200 - iTagLen,_TRUNCATE,fmt,arg_ptr);
va_end(arg_ptr);
OutputDebugStringA(output);
}
catch(...){
}
#else
#endif
}
//初始化接口
bool CmdApiInit(PInitIO pIO)
{
bool hRel = false;
try{
P_ERROR(pIO);
memset(&pIO->Api,0,sizeof(pIO->Api));
//生成库路径
memcpy(&pIO->Api.Path,&pIO->sPath,sizeof(pIO->sPath));
strcat_s(pIO->Api.Path,sizeof(pIO->Api.Path),CN_PUB_RES);
strcat_s(pIO->Api.Path,sizeof(pIO->Api.Path),CN_PUB_APINAME);
LogDbg("pIO->Api.Path: %s",pIO->Api.Path);
//加载库,执行初始化
pIO->Api.Handle = GetModuleHandleA(pIO->Api.Path);
if (NULL == pIO->Api.Handle){
pIO->Api.Handle = LoadLibrary(pIO->Api.Path);
}
LogDbg("pIO->Api.Handle: %.8X",pIO->Api.Handle);
P_ERROR(pIO->Api.Handle);
pIO->Api.Init = TCmdApiInit(GetProcAddress(pIO->Api.Handle, "Init"));
P_ERROR(pIO->Api.Init);
//初始化
pIO->Api.Init(&g_InitIO);
//判断接口
P_ERROR(pIO->Api.UnInit);
P_ERROR(pIO->Api.MemSigScan);
P_ERROR(pIO->Api.CreateCheckBox);
P_ERROR(pIO->Api.FilterOper);
P_ERROR(pIO->Api.WriteLog);
P_ERROR(pIO->Api.SetFunc_ExecuteCmd);
P_ERROR(pIO->Api.HookCodeNormal);
P_ERROR(pIO->Api.UnHookCodeNormal);
P_ERROR(pIO->Api.HookCodeEx);
P_ERROR(pIO->Api.UnHookCodeEx);
P_ERROR(pIO->Api.SetSendSock);
P_ERROR(pIO->Api.GetSendSock);
P_ERROR(pIO->Api.IsToolSock);
hRel = true;
}
catch(...){
}
Exit0:
return hRel;
}
//读配置文件
void Init_Cfg(const char*sToolPath)
{
try{
//配置文件
memcpy(g_Cfg,sToolPath,strlen(sToolPath));
strcat_s(g_Cfg,MAX_PATH,CN_PUB_CFGFILE);
//读取Ip
GetPrivateProfileString(CN_PUB_INI_Title,CN_PUB_INI_Host,CN_PUB_Server_Ip,g_InitIO.sIp,sizeof(g_InitIO.sIp),g_Cfg);
//读取Port
g_InitIO.iPort = GetPrivateProfileInt(CN_PUB_INI_Title,CN_PUB_INI_Port,CN_PUB_Server_Port,g_Cfg);
//
LogDbg("Init_Cfg %s %s %d",g_Cfg,g_InitIO.sIp,g_InitIO.iPort);
}
catch(...){
}
}
void PathOper(char* cPath,int iLen,bool bFlag)
{
for (int i = iLen - 1;i> -1;i--){
if (0x5C == cPath[i]){
if (bFlag){
cPath[i] = 0;
}
break;
}
cPath[i] = 0;
}
}
//获取工具路径
void GetToolPath(char* cPath,int iLen)
{
try{
if (NULL != cPath){
GetModuleFileNameA(g_hModuleThisDll,cPath,iLen);
PathOper(cPath,iLen,false);
PathOper(cPath,iLen,true);
PathOper(cPath,iLen,false);
PathOper(cPath,iLen,true);
PathOper(cPath,iLen,false);
}
LogDbg("g_hModuleThisDll: %.8X %s",g_hModuleThisDll,cPath);
}
catch (...){
}
}
//插件公用初始化函数
bool Init_Plugin_Pub()
{
bool bRet = false;
//获取工具所在目录
GetToolPath(g_InitIO.sPath,sizeof(g_InitIO.sPath));
//读配置文件
Init_Cfg(g_InitIO.sPath);
//接口初始化
if (CmdApiInit(&g_InitIO)){
bRet = true;
}
return bRet;
}
//卸载插件
void UnInit_Plugin()
{
LogDbg("UnInit_Plugin");
g_InitIO.Api.UnInit();
FreeLibrary(g_InitIO.Api.Handle);
}
#endif
#include "CmdApi.h"
#include"tlhelp32.h"
//相关头文件
#include"d3d9.h"
#pragma comment(lib, "d3d9.lib")
//
#define NAKED __declspec(naked)
#define CN_D3D_Stride 50
#define D3D9DLLName "d3d9.dll"
#define Ini_App "D3D9"
#define Ini_Key_SearchBase "SearchBase"
#define Ini_Key_ParamType "ParamType"
#define Ini_Key_CpuSleep "CpuSleep"
#define Ini_Key_Stride "Stride"
#define Ini_Key_KeyBoardSwitch "KeyBoardSwitch"
#define Ini_Key_GameClass "GameClass"
//IDirect3DDevice9::DrawIndexedPrimitive method函数原型
typedef HRESULT (__stdcall *TDrawIndexedPrimitive)(LPDIRECT3DDEVICE9 pDevice,D3DPRIMITIVETYPE type,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount);
//IDirect3DDevice9::Present method函数原型
typedef HRESULT (__stdcall *TPresent)(LPDIRECT3DDEVICE9 pDevice,const RECT *pSourceRect,const RECT *pDestRect,HWND hDestWindowOverride,const RGNDATA *pDirtyRegion);
//
DWORD g_Adr_DrawIndexedPrimitive = 0;
TDrawIndexedPrimitive OldDrawIndexedPrimitive = NULL;
DWORD g_Oft_DrawIndexedPrimitive = (83 - 1)*4;
DWORD g_Param_DrawIndexedPrimitive = 0;
void* OldDrawIndexedPrimitiveParam = NULL;
//
DWORD g_Adr_Present = 0;
TPresent OldPresent = NULL;
DWORD g_Oft_Present = (18 - 1)*4;
//
//游戏窗口句柄
HWND g_Game_Hwnd = NULL;
//原窗口处理函数
WNDPROC g_OldlWindowProc = NULL;
bool g_KeyBoardSwitch = false;
int g_CpuSleep = 0;
DWORD g_Stride = 0;
//HookCodeEx方式获取参数
void __stdcall NewDrawIndexedPrimitiveParam(PHookCodeExParam32 pParam)
{
try{
if (0 == g_Param_DrawIndexedPrimitive){
g_Param_DrawIndexedPrimitive = *(PDWORD)(pParam->dwEsp + 4);
LogDbg("NewDrawIndexedPrimitiveParam %.8X %.8X %.8X",*(PDWORD)(pParam->dwEsp),g_Param_DrawIndexedPrimitive,*(PDWORD)(*(PDWORD)(g_Param_DrawIndexedPrimitive) + g_Oft_DrawIndexedPrimitive));
}
}
catch (...){
}
}
void __stdcall HookDrawIndexedPrimitiveParam(bool bHook)
{
if (bHook){
OldDrawIndexedPrimitiveParam = g_InitIO.Api.HookCodeEx((void*)g_Adr_DrawIndexedPrimitive, &NewDrawIndexedPrimitiveParam);
}
else{
g_InitIO.Api.UnHookCodeEx(OldDrawIndexedPrimitiveParam);
}
}
//NewDrawIndexedPrimitive
HRESULT __stdcall NewDrawIndexedPrimitive(LPDIRECT3DDEVICE9 pDevice,D3DPRIMITIVETYPE type,INT BaseVertexIndex,UINT MinVertexIndex,UINT NumVertices,UINT startIndex,UINT primCount)
{
HRESULT hRet = S_OK;
IDirect3DVertexBuffer9* pStreamData = NULL;
UINT iOffsetInBytes,iStride;
if(D3D_OK == pDevice->GetStreamSource(0,&pStreamData,&iOffsetInBytes,&iStride)){
pStreamData->Release();
}
if(iStride == g_Stride){
pDevice->SetRenderState(D3DRS_ZENABLE,FALSE);//禁用Z轴缓冲
hRet = OldDrawIndexedPrimitive(pDevice,type,BaseVertexIndex,MinVertexIndex,NumVertices,startIndex,primCount);
pDevice->SetRenderState(D3DRS_ZENABLE,TRUE );//恢复Z轴缓冲
}
else{
hRet = OldDrawIndexedPrimitive(pDevice,type,BaseVertexIndex,MinVertexIndex,NumVertices,startIndex,primCount);
}
return hRet;
}
//输出调试的Stride值
void DrawDC()
{
HDC TmpDc = GetDC(NULL);
char aBuff[26] = {0};
sprintf_s(aBuff,20,"Stride:%d ",g_Stride);
TextOut(TmpDc,0,0,aBuff,strlen(aBuff));
ReleaseDC(NULL, TmpDc);
LogDbg("%s",aBuff);
}
//窗口处理函数
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
if(WM_KEYDOWN == uMsg){
if(VK_UP == wParam){
g_Stride += 1;
DrawDC();
}
if(VK_DOWN == wParam){
g_Stride -= 1;
DrawDC();
}
}
return CallWindowProc(g_OldlWindowProc,hwnd,uMsg,wParam,lParam);
}
//窗口处理函数Hook
void __stdcall HookKeyBoard(bool bHook)
{
if (g_KeyBoardSwitch){
if (bHook){
if (NULL == g_Game_Hwnd){
char aBuff[256] = {0};
GetPrivateProfileString(Ini_App,Ini_Key_GameClass,"",aBuff,sizeof(aBuff),g_Cfg);
LogDbg("HookKeyBoard %s %s",Ini_Key_GameClass,aBuff);
g_Game_Hwnd = ::FindWindowA(aBuff,NULL);
}
if (NULL != g_Game_Hwnd){
DWORD dwPid = 0;
GetWindowThreadProcessId(g_Game_Hwnd,&dwPid);
if(dwPid == GetCurrentProcessId()){
g_OldlWindowProc = (WNDPROC)SetWindowLong(g_Game_Hwnd,GWL_WNDPROC,(LONG)WindowProc);
}
}
}
else{
if ((NULL != g_Game_Hwnd) && (NULL != g_OldlWindowProc)){
SetWindowLong(g_Game_Hwnd,GWL_WNDPROC,(LONG)g_OldlWindowProc);
}
}
}
}
//Hook_DrawIndexedPrimitiv指针
void __stdcall HookD3D9_DrawIndexedPrimitive_Mem(bool bHook)
{
if (bHook){
g_Stride = GetPrivateProfileInt(Ini_App,Ini_Key_Stride,CN_D3D_Stride,g_Cfg);
g_KeyBoardSwitch = GetPrivateProfileInt(Ini_App,Ini_Key_KeyBoardSwitch,0,g_Cfg) > 0 ? true:false;
OldDrawIndexedPrimitive = (TDrawIndexedPrimitive)g_Adr_DrawIndexedPrimitive;
*(PDWORD)(*(PDWORD)(g_Param_DrawIndexedPrimitive) + g_Oft_DrawIndexedPrimitive) = DWORD(NewDrawIndexedPrimitive);
}
else{
OldDrawIndexedPrimitive = NULL;
*(PDWORD)(*(PDWORD)(g_Param_DrawIndexedPrimitive) + g_Oft_DrawIndexedPrimitive) = g_Adr_DrawIndexedPrimitive;
}
HookKeyBoard(bHook);
}
//NewPresent
HRESULT __stdcall NewPresent(LPDIRECT3DDEVICE9 pDevice,const RECT *pSourceRect,const RECT *pDestRect,HWND hDestWindowOverride,const RGNDATA *pDirtyRegion)
{
HRESULT hRet = S_OK;
if (-1 == g_CpuSleep){ //黑屏,直接返回
Sleep(168);
return hRet;
};
//执行原函数
hRet = OldPresent(pDevice,pSourceRect,pDestRect,hDestWindowOverride,pDirtyRegion);
//Sleep降压
if (g_CpuSleep > 0){
Sleep(g_CpuSleep);
}
return hRet;
}
//Hook_Present指针
void __stdcall HookD3D9_Present_Mem(bool bHook)
{
if (bHook){
g_CpuSleep = GetPrivateProfileIntA(Ini_App,Ini_Key_CpuSleep,0,g_Cfg);
LogDbg("%d",g_CpuSleep);
OldPresent = (TPresent)g_Adr_Present;
*(PDWORD)(*(PDWORD)(g_Param_DrawIndexedPrimitive) + g_Oft_Present) = DWORD(NewPresent);
}
else{
OldPresent = NULL;
*(PDWORD)(*(PDWORD)(g_Param_DrawIndexedPrimitive) + g_Oft_Present) = g_Adr_Present;
}
}
//Hook方式获取参数_修改代码
void __stdcall GetD3DParam_Hook()
{
while (0 == g_Param_DrawIndexedPrimitive){
HookDrawIndexedPrimitiveParam(true);
Sleep(2);
HookDrawIndexedPrimitiveParam(false);
Sleep(168);
}
}
//全进程搜索参数_不修改代码
DWORD __stdcall GetD3DParam_Search()
{
DWORD dwRet = 0;
DWORD dwTmp;
DWORD dwCurrent = DWORD(GetModuleHandleA(NULL));
DWORD dwMax = 0x7F000000;
while (dwCurrent < dwMax){
dwTmp = dwCurrent;
if (!IsBadReadPtr((void*)(dwTmp),4)){
dwTmp = *(PDWORD)dwTmp + g_Oft_DrawIndexedPrimitive;
if (!IsBadReadPtr((void*)(dwTmp),4)){
if (*PDWORD(dwTmp) == g_Adr_DrawIndexedPrimitive){
dwRet = dwCurrent;
LogDbg("GetD3DParam_Search %.8X %.8X",dwRet,g_Adr_DrawIndexedPrimitive);
break;
}
}
}
dwCurrent += 4;
}
return dwRet;
}
//在主模块搜索一级基址
void __stdcall SearchBaseAdr(DWORD dwParam)
{
bool bFound = false;
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32 ={0};
if (0 == dwParam){
goto Exit0;
}
//创建进程快照
hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId());
if(INVALID_HANDLE_VALUE == hModuleSnap){
goto Exit0;
}
//递归枚举模块
me32.dwSize = sizeof(MODULEENTRY32);
if(::Module32First(hModuleSnap,&me32))
{
do{
DWORD dwCurrent = DWORD(me32.hModule);
LogDbg("Module %.8X %.8X %s",dwCurrent,me32.modBaseSize,me32.szExePath);
DWORD dwOft = 0;
while (dwOft <= me32.modBaseSize){
if (!IsBadReadPtr((void*)(dwCurrent + dwOft),4)){
if (*(PDWORD)(dwCurrent + dwOft) == dwParam){
LogDbg("BaseAdr %.8X %.8X",dwCurrent,dwOft);
}
}
dwOft += 4;
}
}while(::Module32Next(hModuleSnap,&me32));
}
Exit0:
if(INVALID_HANDLE_VALUE != hModuleSnap){
CloseHandle(hModuleSnap);
}
LogDbg("SearchBaseAdr End");
return;
}
bool GetD3DAdr(){
bool bRet = false;
LPDIRECT3D9 Tmp_pD3D = NULL;
LPDIRECT3DDEVICE9 Tmp_pd3dDevice = NULL;
if (NULL == ::GetModuleHandleA(D3D9DLLName)){
goto Exit0;
}
if (NULL == (Tmp_pD3D = Direct3DCreate9(D3D_SDK_VERSION))){
goto Exit0;
}
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof( d3dpp ) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
if (S_OK == Tmp_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,GetDesktopWindow(),
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,&Tmp_pd3dDevice)){
try{
g_Adr_DrawIndexedPrimitive = *(PDWORD)(*(PDWORD)Tmp_pd3dDevice + g_Oft_DrawIndexedPrimitive);
g_Adr_Present = *(PDWORD)(*(PDWORD)Tmp_pd3dDevice + g_Oft_Present);
LogDbg("g_Adr_DrawIndexedPrimitive:%.8X g_Adr_Present:%.8X",g_Adr_DrawIndexedPrimitive,g_Adr_Present);
bRet = true;
}
catch (...){
}
}
Exit0:
if( Tmp_pd3dDevice != NULL ){
Tmp_pd3dDevice->Release();
}
if( Tmp_pD3D != NULL ){
Tmp_pD3D->Release();
}
return bRet;
}
DWORD __stdcall Init_Plugin_MyThread(VOID* lpArgc)
{
while (!GetD3DAdr()){
Sleep(100);
}
//创建降压CheckBox
g_InitIO.Api.CreateCheckBox("D3D_CPU降压", HookD3D9_Present_Mem, false);
//获取参数
if (0 == GetPrivateProfileIntA(Ini_App,Ini_Key_ParamType,0,g_Cfg)){
GetD3DParam_Hook();
LogDbg("GetD3DParam_Hook End");
}
else{
g_Param_DrawIndexedPrimitive = GetD3DParam_Search();
LogDbg("GetD3DParam_Search End");
}
//创建透视CheckBox
g_InitIO.Api.CreateCheckBox("D3D_透视", HookD3D9_DrawIndexedPrimitive_Mem, false);
//搜索模块中对应一级基址,对于特定的游戏可以避免Hook或搜索而直接读取参数
if (0 != GetPrivateProfileIntA(Ini_App,Ini_Key_SearchBase,0,g_Cfg)){
SearchBaseAdr(g_Param_DrawIndexedPrimitive);
}
LogDbg("Init_Plugin_MyThread End");
return true;
}
void Init_Plugin_My()
{
DWORD dwThreadId = 0;
HANDLE hTmp = CreateThread(NULL, 0, Init_Plugin_MyThread, NULL, CREATE_SUSPENDED, &dwThreadId);
SetThreadPriority(hTmp,THREAD_PRIORITY_TIME_CRITICAL);
ResumeThread(hTmp);
CloseHandle(hTmp);
}
void Init_Plugin()
{
LogDbg("_init in");
if (Init_Plugin_Pub()){
Init_Plugin_My();
LogDbg("_init ok");
}
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
if (0 == g_hModuleThisDll){
g_hModuleThisDll = hModule;
}
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Init_Plugin();
break;
case DLL_PROCESS_DETACH:
UnInit_Plugin();
break;
default:
break;
}
return TRUE;
}