温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,汇文网负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
网站客服:3074922707
瑞客论坛 www.ruike1.com
D025-突破TP
NP等游戏保护跨进程读写内存方法2【瑞客论坛
www.ruike1.com】
D025
突破
TP
NP
游戏
保护
跨进
读写
内存
方法
突破TP,NP保护跨进程读写内存2
2021在线班
郁金香灬老师 QQ 150330575
交流群:158280115
学习目标:
突破TP,NP保护跨进程读写内存2
League of Legends.exe
0x400000
IoAllocateMdl IoFreeMdl
MmBuildMdlForNonPagedPool
MmMapLockedPages MmUnmapLockedPages
KeStackAttachProcess KeUnstackDetachProcess
#include <ntifs.h>
//OK 测试通过 遇到2个坑
//第1个坑 sizeof(PKAPC_STATE)是指针 得改结构大小 sizeof(KAPC_STATE)
//第2个坑 KeStackAttachProcess后 进程空间变化了 得用内核内存 中转 BUF缓冲区
//Address为目标进程的内存地址
//Buffer //当前进程的地址
BOOLEAN KReadProcessMemory2(IN PEPROCESS Process, IN PVOID Address, IN UINT32 Length, IN PVOID UserBuffer)
{
KAPC_STATE apc_state;
RtlZeroMemory(&apc_state, sizeof(KAPC_STATE));
//1为UserBuffer 创建 MDL内存描述
//创建MDL来读取内存 UserBuffer=0x200000
PMDL g_pmdl = IoAllocateMdl(UserBuffer,Length, 0, 0, NULL); //8 可以修改成 要读取的内存大小
if (!g_pmdl)
{
return FALSE;
}
//2标记为非分页内存
MmBuildMdlForNonPagedPool(g_pmdl);
//3锁定 映射用户内存 到 内核内存 0x100000
unsigned char* Mapped = (unsigned char*)MmMapLockedPages(g_pmdl, KernelMode); //UserMode
if (!Mapped)
{ //映射失败
IoFreeMdl(g_pmdl);
return FALSE;
}
//成功 映射了 地址
//切换到 目标进程
KeStackAttachProcess((PVOID)Process, &apc_state);
//判断目标地址是否可以访问 UserBuffer不可访问 Mapped可以访问
BOOLEAN dwRet = MmIsAddressValid(Address);
if (dwRet)
{
KdPrint(("yjx[sys64] RtlCopyMemory(Address, Buffer, Length);\r\n", Address, UserBuffer, Length));
//如果目标地址 可以访问 直接复制目标地址内容 到映射的内核地址区域
RtlCopyMemory(Mapped, Address, Length); //memcpy RtlCopyMemory(Address,Mapped, Length); //memcpy
}
else
{
KdPrint(("yjx:sys64:Error Line37"));
}
//分离目标进程空间 恢复环境
KeUnstackDetachProcess(&apc_state);
DbgPrint("yjx: sys分离目标进程");
//MDL清理工作
////释放MDL相关 资源
MmUnmapLockedPages((PVOID)Mapped, g_pmdl);
IoFreeMdl(g_pmdl);
return dwRet;
}
//dwPid为目标进程id
//lpBaseAddress 目标进程地址
//lpBuffer 当前进程地址 1
//内核内存地址 当前进程地址 2
int ReadProcessMemoryForPid2(UINT32 dwPid, PVOID pBase, PVOID lpBuffer, UINT32 nSize)
{
//根据pid获取PEPROCESS
PEPROCESS Seleted_pEPROCESS = NULL;
DbgPrint("yjx:sys64 ReadMemory pid=%d pBase=%p", dwPid, pBase);
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(dwPid), &Seleted_pEPROCESS) == STATUS_SUCCESS)
{
BOOLEAN br = KReadProcessMemory2(Seleted_pEPROCESS, (PVOID)pBase, nSize, lpBuffer);
ObDereferenceObject(Seleted_pEPROCESS);
if (br)
{
return nSize;
}
}
else
{
KdPrint(("yjx sys64 PsLookupProcessByProcessId Fail..."));
}
return 0;// STATUS_UNSUCCESSFUL;
}
//int ReadProcessMemoryForPid2(UINT32 dwPid, PVOID pBase, PVOID lpBuffer, UINT32 nSize);
NTSTATUS IRP_ReadProcessMemory2(PDEVICE_OBJECT device_Object, PIRP pirp)
{
UNREFERENCED_PARAMETER(device_Object); //未使用的参数 禁止警告
DbgPrint("yjx:sysNtAllocateVirtualMemory 进入 IRP_YJX_VirtualAllocEx \n");
NTSTATUS ntStatus = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack = NULL;
irpStack = IoGetCurrentIrpStackLocation(pirp);
#pragma pack(push)
#pragma pack(1)
typedef struct TINPUT_BUF
{
DWORD32 dwPid;
PVOID pBase; //目标进程地址
DWORD32 nSize;//缓冲区大小
}TINPUT_BUF;
#pragma pack(pop)
//结构
PVOID BaseAddress = NULL; //返回地址
PEPROCESS selectedprocess = NULL;//目标进程
SIZE_T RegionSize = 0;//分配大小
TINPUT_BUF*bufInput = pirp->AssociatedIrp.SystemBuffer; //输入 输出 缓冲区
ReadProcessMemoryForPid2(bufInput->dwPid, bufInput->pBase, bufInput, bufInput->nSize);
//ENDCODE:
//pirp->IoStatus.Status = STATUS_SUCCESS;//
////pirp->IoStatus.Information = 4;//返回给DeviceIoControl中的 倒数第二个参数lpBytesReturned
//IoCompleteRequest(pirp, IO_NO_INCREMENT);//调用方已完成所有I/O请求处理操作 并且不增加优先级
if (irpStack) //
{
if (ntStatus == STATUS_SUCCESS)
{ //成功则返回 缓冲区大小
pirp->IoStatus.Information = irpStack->Parameters.DeviceIoControl.OutputBufferLength;//DeviceIoControl
}
else
{ //失败则不返回
pirp->IoStatus.Information = 0;
}
//完成请求
IoCompleteRequest(pirp, IO_NO_INCREMENT);
}
pirp->IoStatus.Status = ntStatus;
return ntStatus;
}