上一个内容:32.双击列表启动目标游戏
前置知识 25.入口点注入(查看pe头)、32.双击列表启动目标游戏 以它的代码为基础进行修改
效果图:
代码实现:原理通过读文件流的方式把文件加载到内存中然后解析pe结构
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{};
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);
// 让游戏继续运行
ResumeThread(prinfo.hThread);
}
加载文件的代码实现:
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;
}