免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
如果看不懂、不知道现在做的什么,那就跟着做完看效果,代码看不懂是正常的,只要会抄就行,抄着抄着就能懂了
上一个内容:35.简易远程数据框架的实现
以 35.简易远程数据框架的实现 它的代码为基础进行的修改
通过远程线程获取游戏首地址,然后把首地址的代码改为跳转到辅助功能里。
首先关闭安全检测
添加了RemoteThreadProce函数,修改了CodeRemoteData、CreateRemoteData、OnNMDblclkList1函数,修改了_REMOTE_DATA结构
CWndINJ.cpp: 实现文件
#include "pch.h"
#include "GAMEHACKER2.h"
#include "CWndINJ.h"
#include "afxdialogex.h"
#include <ImageHlp.h>
#include <fstream>
#pragma comment(lib, "ImageHlp.lib")
//void _stdcall INJECTCode() {
// AfxMessageBox(L"aa");
// unsigned address = 0xCCCCCCCC;
// PREMOTE_DATA p = (PREMOTE_DATA)address;
// p->f_LoadLibrary(p->dllName);
//}
// CWndINJ 对话框
IMPLEMENT_DYNAMIC(CWndINJ, CDialogEx)
CWndINJ::CWndINJ(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_PAGE_0, pParent)
, B_INJCET(FALSE)
, B_DEBUG(FALSE)
, B_PAUSE(FALSE)
{
}
CWndINJ::~CWndINJ()
{
}
BOOL CWndINJ::OnInitDialog()
{
CDialogEx::OnInitDialog();
LONG_PTR lStyle;
// 得到窗口的样式,GWL_STYLE在GetWindowLongPtr说明中有
lStyle = GetWindowLongPtr(ExeLst.m_hWnd, GWL_STYLE);
lStyle |= LVS_REPORT;
SetWindowLongPtr(ExeLst.m_hWnd, GWL_STYLE, lStyle);
DWORD dStyle = ExeLst.GetExtendedStyle();
dStyle |= LVS_EX_FULLROWSELECT;
dStyle |= LVS_EX_GRIDLINES;
ExeLst.SetExtendedStyle(dStyle);
ExeLst.InsertColumn(0, L"名称", 0, 200);
ExeLst.InsertColumn(1, L"可执行文件", 0, 400);
ExeLst.InsertColumn(2, L"文件夹", 0, 400);
ExeLst.InsertColumn(3, L"命令行", 0, 400);
ExeLst.InsertColumn(4, L"注入模块", 0, 400);
return 0;
}
void CWndINJ::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST1, ExeLst);
DDX_Check(pDX, IDC_CHECK1, B_INJCET);
DDX_Check(pDX, IDC_CHECK2, B_DEBUG);
DDX_Check(pDX, IDC_CHECK3, B_PAUSE);
}
BEGIN_MESSAGE_MAP(CWndINJ, CDialogEx)
ON_BN_CLICKED(IDC_BUTTON1, &CWndINJ::OnBnClickedButton1)
ON_NOTIFY(NM_DBLCLK, IDC_LIST1, &CWndINJ::OnNMDblclkList1)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST1, &CWndINJ::OnLvnItemchangedList1)
END_MESSAGE_MAP()
// CWndINJ 消息处理程序
void CWndINJ::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
/*ExeLst.InsertItem(0, L"DNF");
ExeLst.SetItemText(0, 1, L"dlls.dll");*/
用来指定创建时进程的主窗口的窗口工作站、桌面、标准句柄和外观。
//STARTUPINFO si{};
//si.cb = sizeof(si);
//PROCESS_INFORMATION prinfo{};
//CreateProcess(L"C:\\Users\\am\\Desktop\\易道云\\游戏保护\\练手游戏\\初级\\JX2\\Sword2.exe",
// NULL,NULL,NULL,
// FALSE,
// // 新进程的主线程处于挂起状态创建,在调用 ResumeThread 函数之前不会运行。
// CREATE_SUSPENDED,
// NULL,
// L"C:\\Users\\am\\Desktop\\易道云\\游戏保护\\练手游戏\\初级\\JX2\\",
// &si,
// &prinfo
// );
///**
// 注入功能写在这里(CreateProcess与ResumeThread函数之间)
//*/
让游戏继续运行
//ResumeThread(prinfo.hThread);
wndAddGame.Init(this);
wndAddGame.DoModal();
}
void CWndINJ::Init(CString& _AppPath)
{
AppPath = _AppPath;
GameIni.Format(L"%s\\config\\Games.ini", AppPath);
LoadGame();
}
void CWndINJ::AddGame(CString& GameName, CString& GamePath, CString& GameFullPath, CString& GameCmds, CString& DllPath)
{
int count = GetPrivateProfileInt(L"main", L"count", 0, GameIni);
count++;
CString key;
key.Format(L"count_%d", count);
WritePrivateProfileString(key, L"GameName", GameName, GameIni);
WritePrivateProfileString(key, L"GamePath", GamePath, GameIni);
WritePrivateProfileString(key, L"GameFullPath", GameFullPath, GameIni);
WritePrivateProfileString(key, L"GameCmds", GameCmds, GameIni);
WritePrivateProfileString(key, L"DllPath", DllPath, GameIni);
CString wCount;
wCount.Format(L"%d", count);
WritePrivateProfileString(L"main", L"count", wCount, GameIni);
int iCount = ExeLst.GetItemCount();
ExeLst.InsertItem(iCount, GameName);
ExeLst.SetItemText(iCount, 1, GamePath);
ExeLst.SetItemText(iCount, 2, GameFullPath);
ExeLst.SetItemText(iCount, 3, GameCmds);
ExeLst.SetItemText(iCount, 4, DllPath);
}
void CWndINJ::LoadGame()
{
int count = GetPrivateProfileInt(L"main", L"count", 0, GameIni);
for (int i = 0; i < count; i++) {
CString GameName, GameExe, GamePath, GameCmds, GameDlls, _AppName;
_AppName.Format(L"count_%d", i+1);
wchar_t wRead[0xFF];
GetPrivateProfileString(_AppName, L"GameName", L"", wRead, 0xFF, GameIni);
GameName.Format(L"%s", wRead);
GetPrivateProfileString(_AppName, L"GamePath", L"", wRead, 0xFF, GameIni);
GameExe.Format(L"%s", wRead);
GetPrivateProfileString(_AppName, L"GameFullPath", L"", wRead, 0xFF, GameIni);
GamePath.Format(L"%s", wRead);
GetPrivateProfileString(_AppName, L"GameCmds", L"", wRead, 0xFF, GameIni);
GameCmds.Format(L"%s", wRead);
GetPrivateProfileString(_AppName, L"DllPath", L"", wRead, 0xFF, GameIni);
GameDlls.Format(L"%s", wRead);
ExeLst.InsertItem(i, GameName);
ExeLst.SetItemText(i, 1, GameExe);
ExeLst.SetItemText(i, 2, GamePath);
ExeLst.SetItemText(i, 3, GameCmds);
ExeLst.SetItemText(i, 4, GameDlls);
}
}
void* _imageload(wchar_t* filename) {
std::ifstream streamReader(filename, std::ios::binary);
streamReader.seekg(0, std::ios::end);
unsigned filesize = streamReader.tellg();
char* _data = new char[filesize];
streamReader.seekg(0, std::ios::beg);
streamReader.read(_data, filesize);
streamReader.close();
return _data;
}
void _unloadimage(void* _data) {
delete[] _data;
}
void CWndINJ::OnNMDblclkList1(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
int index = pNMItemActivate->iItem;
if (index < 0)return;
CString GamePath = ExeLst.GetItemText(index, 2);
CString GameExe = ExeLst.GetItemText(index, 1);
CString GameCmds = ExeLst.GetItemText(index, 3);
CString GameDlls = ExeLst.GetItemText(index, 4);
// 用来指定创建时进程的主窗口的窗口工作站、桌面、标准句柄和外观。
// STARTUPINFO si{};
// si.cb = sizeof(si);
PROCESS_INFORMATION prinfo{};
m_INJCET.StartProcess(GameExe, GamePath, GameCmds.GetBuffer(), &prinfo);
m_INJCET.CreateRemoteData(prinfo.hProcess, GameExe, L"F:\\代码存放地\\c\\GAMEHACKER2\\Release\\Dlls.dll");
//m_INJCET.CodeRemoteData(&_data);
/**
CreateProcess(GameExe,
GameCmds.GetBuffer(),
NULL,NULL,
FALSE,
// 新进程的主线程处于挂起状态创建,在调用 ResumeThread 函数之前不会运行。
CREATE_SUSPENDED,
NULL,
GamePath,
&si,
&prinfo
);
*/
/** 方式一调用api
CStringA GameExeA;
GameExeA = GameExe;
PLOADED_IMAGE image = ImageLoad(GameExeA, NULL);
DWORD dEntryPoint = image->FileHeader->OptionalHeader.AddressOfEntryPoint;
CString wTxt;
wTxt.Format(L"%X", dEntryPoint);
AfxMessageBox(wTxt);
ImageUnload(image)
*/
/** 方式二(要在32位环境下运行)
void* image = _imageload(GameExe.GetBuffer());
IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)image;
unsigned PEAddress = dosHeader->e_lfanew + (unsigned)image;
IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)PEAddress;
DWORD dEntryPoint = ntHeader->OptionalHeader.AddressOfEntryPoint;
CString wTxt;
wTxt.Format(L"%X", dEntryPoint);
AfxMessageBox(wTxt);
_unloadimage(image);
*/
//LPVOID adrRemote = VirtualAllocEx(prinfo.hProcess, 0, 0x3000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//SIZE_T lwt;
//WriteProcessMemory(prinfo.hProcess, adrRemote, INJECTCode, 0x200, &lwt);
//CString wTxt;
//wTxt.Format(L"%X", adrRemote);
//AfxMessageBox(wTxt);
// 让游戏继续运行
//m_INJCET.CreateRemoteData(prinfo.hProcess, GameDlls.GetBuffer());
// ResumeThread(prinfo.hThread);
}
void CWndINJ::OnLvnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
*pResult = 0;
}
INJCET.cpp文件代码:
#include "pch.h"
#include "INJCET.h"
#include <fstream>
void _stdcall INJECTCode() {
unsigned address = 0xCCCCCCCC;
PREMOTE_DATA p = (PREMOTE_DATA)address;
p->f_LoadLibrary(p->dllName);
unsigned dEntry = p->EntryPoint;
char* entryCode = (char*)p->EntryPoint;
entryCode[0] = p->oldCode[0];
entryCode[1] = p->oldCode[1];
entryCode[2] = p->oldCode[2];
entryCode[3] = p->oldCode[3];
entryCode[4] = p->oldCode[4];
_asm {
mov eax, dEntry
jmp eax
}
}
DWORD _stdcall RemoteThreadProce(PREMOTE_DATA p) {
unsigned base = p->f_GetModuleHandleA(0);
DWORD dRet;
p->EntryPoint += base;
p->f_VirtualProtect((LPVOID)p->EntryPoint, 0x1000, PAGE_EXECUTE_READWRITE, &dRet);
char* entryCode = (char*)p->EntryPoint;
p->oldCode[0] = entryCode[0];
p->oldCode[1] = entryCode[1];
p->oldCode[2] = entryCode[2];
p->oldCode[3] = entryCode[3];
p->oldCode[4] = entryCode[4];
int* entryDis = (int*)(p->EntryPoint + 1);
*entryCode = 0xE9;
int Distance = p->HOOKFunction - p->EntryPoint - 5;
*entryDis = Distance;
return 1;
}
BOOL INJCET::StartProcess(const wchar_t* GameExe, const wchar_t* GamePath, wchar_t* GameCmds, PROCESS_INFORMATION* LPinfo)
{
// 用来指定创建时进程的主窗口的窗口工作站、桌面、标准句柄和外观。
STARTUPINFO si{};
si.cb = sizeof(si);
CreateProcess(GameExe,
GameCmds,
NULL, NULL,
FALSE,
// 新进程的主线程处于挂起状态创建,在调用 ResumeThread 函数之前不会运行。
CREATE_SUSPENDED,
NULL,
GamePath,
&si,
LPinfo
);
return TRUE;
}
void* INJCET::ImageLoad(const wchar_t* filename) {
std::ifstream streamReader(filename, std::ios::binary);
streamReader.seekg(0, std::ios::end);
unsigned filesize = streamReader.tellg();
char* _data = new char[filesize];
streamReader.seekg(0, std::ios::beg);
streamReader.read(_data, filesize);
streamReader.close();
return _data;
}
void INJCET::UnloadImage(void* _data) {
delete[] _data;
}
DWORD INJCET::GetEntryPoint(const wchar_t* filename)
{
// 方式二(要在32位环境下运行根据游戏版本选择运行32还是64位的程序)
void* image = ImageLoad(filename);
IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)image;
unsigned PEAddress = dosHeader->e_lfanew + (unsigned)image;
IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)PEAddress;
DWORD dEntryPoint = ntHeader->OptionalHeader.AddressOfEntryPoint;
CString wTxt;
wTxt.Format(L"%X", dEntryPoint);
AfxMessageBox(wTxt);
UnloadImage(image);
return dEntryPoint;
}
BOOL INJCET::CreateRemoteData(HANDLE hProcess, const wchar_t* GameExe, const wchar_t* dllName)
{
LPVOID adrRemote = VirtualAllocEx(hProcess, 0, 0x3000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
SIZE_T lwt;
LPVOID adrRemoteData = (LPVOID)((unsigned)adrRemote + 0x2000);
LPVOID adrRemoteProc= (LPVOID)((unsigned)adrRemote + 0x500);
_REMOTE_DATA remoteData{};
remoteData.EntryPoint = GetEntryPoint(GameExe);
CodeRemoteData(&remoteData, dllName);
WriteProcessMemory(hProcess, adrRemoteData, &remoteData, sizeof(remoteData), &lwt);
char _code[0x200];
memcpy(_code, INJECTCode, sizeof(_code));
for (int i = 0; i < 0x100; i++) {
unsigned* pcode = (unsigned*)(&_code[i]);
if (pcode[0] == 0xCCCCCCCC) {
pcode[0] = (unsigned)adrRemoteData;
break;
}
}
WriteProcessMemory(hProcess, adrRemote, _code, 0x200, &lwt);
remoteData.HOOKFunction = (unsigned)adrRemote;
WriteProcessMemory(hProcess, adrRemoteProc, RemoteThreadProce, 0x200, &lwt);
CString wTxt;
wTxt.Format(L"%X", adrRemote);
AfxMessageBox(wTxt);
DWORD dwThreadId = 0;
HANDLE remotehdl = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)adrRemoteProc, adrRemoteData, 0, &dwThreadId);
WaitForSingleObject(remotehdl, INFINITE);
//DWORD dwThreadId = 0;
//HANDLE remoteHdl = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)adrRemote, NULL, 0, &dwThreadId);
//WaitForSingleObject(remoteHdl, INFINITE);
return TRUE;
}
void INJCET::CodeRemoteData(PREMOTE_DATA _data, const wchar_t* dllName)
{
short lenth;
// 求长度
for (lenth = 0; dllName[lenth]; lenth++);
HMODULE hKernel = LoadLibrary(_T("kernel32.dll"));
//_data->f_LoadLibrary = (_LoadLibrary)GetProcAddress(hKernel, "LoadLibraryW");
_data->f_LoadLibrary = (_LoadLibrary)GetProcAddress(hKernel, "LoadLibraryW");
_data->f_GetModuleHandleA = (_GetModuleHandleA)GetProcAddress(hKernel, "GetModuleHandleA");
_data->f_VirtualProtect = (_VirtualProtect)GetProcAddress(hKernel, "VirtualProtect");
//LoadLibraryW
// wchar两字节拷贝是一字节所以长度要成2
memcpy(_data->dllName, dllName, (lenth + 1) * 2);
/*CString wTxt;
wTxt.Format(L"%X", _data->f_LoadLibrary);
AfxMessageBox(wTxt);*/
}
INJCET.h文件代码:
#pragma once
#include <Windows.h>
typedef unsigned int (WINAPI* _LoadLibrary)(wchar_t* dllName);
typedef unsigned int (WINAPI* _GetModuleHandleA)(wchar_t* modName);
typedef int (WINAPI* _VirtualProtect)(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);
typedef struct _REMOTE_DATA {
wchar_t dllName[0xFF]; // 要输入的dll文件路径
unsigned EntryPoint;
unsigned HOOKFunction;
char oldCode[5];
_LoadLibrary f_LoadLibrary;
_GetModuleHandleA f_GetModuleHandleA;
_VirtualProtect f_VirtualProtect;
}*PREMOTE_DATA;
class INJCET
{
public:
BOOL StartProcess(
const wchar_t * GameExe,
const wchar_t * GamePath,
wchar_t * GameCmds,
PROCESS_INFORMATION* LPinfo
);
void* ImageLoad(const wchar_t* filename);
void UnloadImage(void* _data);
DWORD GetEntryPoint(const wchar_t* filename);
public:
BOOL CreateRemoteData(HANDLE hProcess, const wchar_t* GameExe, const wchar_t* dllName);
void CodeRemoteData(PREMOTE_DATA _data, const wchar_t* dllName);
};