CreateRemoteThread函数多参数传入使用方法

2024-08-25 10:18

本文主要是介绍CreateRemoteThread函数多参数传入使用方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


注意事项:

1.Debug版本编译的时候使用增量编译,导致每个函数都是用一个Thunk, 所以请使用Release版本。

2.目标进程非本进程时不能调用本进程内的函数或使用本进程内的变量,有时在隐式使用时可能会引起该

问题,容易引起进程崩溃。(例如WriteProcessMemory写入的函数中调用了本进程的全局变量)

3.多参数使用时请在目标进程中为函数参数分配相应的内存空间,因为CreateRemoteThread第5个参数是LPVOID型,

这意味着它只能放一个指针值,而该指针值应该指向分配的相应内存空间。


使用实例:

假设我们调用的目标进程的主窗口标题为“ImageCall”, 并假设在偏移该进程首地址0x000163D0有一个用于加血的游戏函数。

于是我们可以如下所示来使用CreateRemoteThread多参数调用来在目标进程中调用该加血函数。


(以下使用默认在MFC中,CImageBloodDlg为一个基本对话框类,

AddBlood_Inject()为对话框上某一按钮按下时的触发函数。)


//首先定义全局标题和偏移地址

LPCTSTR gameCaption = _T("ImageCall");
const int ADD_BLOOD_CALL = 0x000163D0;

//之后是上一篇博客中写道的获取进程首地址的函数

//获取目标进程首地址
BOOL CImageBloodDlg::getProcessAddr(DWORD dwPID, DWORD& baseAddr)
{HANDLE hModuleSnap = INVALID_HANDLE_VALUE;MODULEENTRY32 me32;// 在目标进程中获取所有进程的snapshothModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);if (hModuleSnap == INVALID_HANDLE_VALUE){AfxMessageBox(_T("CreateToolhelp32Snapshot (of modules) fail"));return(FALSE);}// 设置MODULEENTRY32数据结构大小字段me32.dwSize = sizeof(MODULEENTRY32);//检索第一个模块的信息,不成功则返回if (!Module32First(hModuleSnap, &me32)){AfxMessageBox(_T("Module32First fail")); // 显示调用失败CloseHandle(hModuleSnap);    // 清除句柄对象return(FALSE);}// 从me32中得到基址baseAddr = (DWORD)me32.modBaseAddr;// 别忘了最后清除模块句柄对象CloseHandle(hModuleSnap);return(TRUE);
}

//然后我们定义一个获取目标地址空间真实地址的结构体

typedef struct tagTrueAddr
{DWORD baseAddr;DWORD Offset;}TrueAddr, *PTrueAddr;

//这是我们想在目标进程中进行调用的函数(使用了内联汇编)

void __stdcall addBloodCall(TrueAddr* addr)
{DWORD baseAddr = addr->baseAddr;DWORD baseOffset = addr->Offset;_asm{mov eax, baseAddradd eax, baseOffsetcall eax}
}

//最后我们通过远程注入来进行CreateRemoteThread的多参数调用,按下相应按钮时触发该函数

void CImageBloodDlg::AddBlood_Inject()
{// TODO:  在此添加控件通知处理程序代码//得到窗口句柄HWND hwnd = ::FindWindow(NULL, gameCaption);//得到进程IDDWORD pid;GetWindowThreadProcessId(hwnd, &pid);//获取进程访问权限HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);//目标进程分配函数参数空间LPVOID paramsCall = VirtualAllocEx(hProcess, NULL, sizeof(TrueAddr), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);if (paramsCall == NULL){AfxMessageBox(_T("get paramsCall failed"));return;}//目标进程分配函数本体空间LPVOID baseCall = VirtualAllocEx(hProcess, NULL, 1000, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);if (baseCall == NULL){AfxMessageBox(_T("get baseCall failed"));return;}//在函数本体空间中写入addBloodCall函数本体if (!WriteProcessMemory(hProcess, baseCall, addBloodCall, 1000, NULL)){AfxMessageBox(_T("writeProcessMemory fail"));return;}//得到目标进程首地址DWORD baseAddr;getProcessAddr(pid, baseAddr);//设置真实地址(baseAddr首地址, Offset偏移地址量)TrueAddr trueAddr;trueAddr.baseAddr = baseAddr;trueAddr.Offset = ADD_BLOOD_CALL;if (!WriteProcessMemory(hProcess, paramsCall, (LPCVOID)&trueAddr, sizeof(TrueAddr), NULL)){AfxMessageBox(_T("Write trueAddress failed"));return;}//传入函数参数并创建远程线程函数PTrueAddr ptAddr = (PTrueAddr)paramsCall;HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)baseCall, (LPVOID)ptAddr, 0,NULL);if (!hRemoteThread){AfxMessageBox(_T("CreateRemoteThread failed"));return;}
}

先定义一个结构体的数据结构类型,并在该结构中包括所有的函数入口参数,

然后为想写入的函数提供唯一的一个结构体指针的参数,最后在CreateRemoteThread中

提供该唯一的函数参数,并为该函数参数指针所指的结构体在目标进程中开辟相应的内存空间,

并使该指针指向它,通过这种方法我们便可以成功使用多参数函数传入的CreateRemoteThread调用了。


这篇关于CreateRemoteThread函数多参数传入使用方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1105279

相关文章

springboot security快速使用示例详解

《springbootsecurity快速使用示例详解》:本文主要介绍springbootsecurity快速使用示例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录创www.chinasem.cn建spring boot项目生成脚手架配置依赖接口示例代码项目结构启用s

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

java中使用POI生成Excel并导出过程

《java中使用POI生成Excel并导出过程》:本文主要介绍java中使用POI生成Excel并导出过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求说明及实现方式需求完成通用代码版本1版本2结果展示type参数为atype参数为b总结注:本文章中代码均为

mysql出现ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)的解决方法

《mysql出现ERROR2003(HY000):Can‘tconnecttoMySQLserveron‘localhost‘(10061)的解决方法》本文主要介绍了mysql出现... 目录前言:第一步:第二步:第三步:总结:前言:当你想通过命令窗口想打开mysql时候发现提http://www.cpp

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

Spring Boot3虚拟线程的使用步骤详解

《SpringBoot3虚拟线程的使用步骤详解》虚拟线程是Java19中引入的一个新特性,旨在通过简化线程管理来提升应用程序的并发性能,:本文主要介绍SpringBoot3虚拟线程的使用步骤,... 目录问题根源分析解决方案验证验证实验实验1:未启用keep-alive实验2:启用keep-alive扩展建

MySQL INSERT语句实现当记录不存在时插入的几种方法

《MySQLINSERT语句实现当记录不存在时插入的几种方法》MySQL的INSERT语句是用于向数据库表中插入新记录的关键命令,下面:本文主要介绍MySQLINSERT语句实现当记录不存在时... 目录使用 INSERT IGNORE使用 ON DUPLICATE KEY UPDATE使用 REPLACE

使用Java实现通用树形结构构建工具类

《使用Java实现通用树形结构构建工具类》这篇文章主要为大家详细介绍了如何使用Java实现通用树形结构构建工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录完整代码一、设计思想与核心功能二、核心实现原理1. 数据结构准备阶段2. 循环依赖检测算法3. 树形结构构建4. 搜索子

GORM中Model和Table的区别及使用

《GORM中Model和Table的区别及使用》Model和Table是两种与数据库表交互的核心方法,但它们的用途和行为存在著差异,本文主要介绍了GORM中Model和Table的区别及使用,具有一... 目录1. Model 的作用与特点1.1 核心用途1.2 行为特点1.3 示例China编程代码2. Tab