 突破TP,NP保护跨进程读写内存1

2021在线班
郁金香灬老师 QQ 150330575
交流群:158280115


学习目标: 
     突破TP,NP保护跨进程读写内存1
	  
	  
	  
#include <ntifs.h>

  OpenProcess->ReadProcessMemory->WriteProcessMemory

//OK 测试通过 遇到2个坑 
//第1个坑 sizeof(PKAPC_STATE)是指针 得改结构大小 sizeof(KAPC_STATE)
//第2个坑 KeStackAttachProcess后 进程空间变化了 得用内核内存 中转 BUF缓冲区
//Address为目标进程的内存地址
//Buffer //当前进程的地址
BOOLEAN KReadProcessMemory(IN PEPROCESS Process, IN PVOID Address, IN UINT32 Length, IN OUT PVOID Buffer)
{

	KAPC_STATE apc_state;
	RtlZeroMemory(&apc_state, sizeof(KAPC_STATE));
	//在所有进程通用
	PVOID tmpBuf_Kernel = ExAllocatePool(NonPagedPool, Length);

	//可以改MDL把　进程地址　映射到　内核驱动也可以
	//中转内存地址 因为 KeStackAttachProcess后 原来的进程R3 Buffer 在目标地址里不存在
	//RtlCopyMemory(tmpBuf_Kernel, Buffer, Length);
	//进入到目标进程的 内存空间
	DbgPrint("yjx:附加到目标进程 Address=%p  Buffer=%p", Address, Buffer);
	//进入目标进程内存空间
	KeStackAttachProcess((PVOID)Process, &apc_state);
	//判断目标地址是否可以访问
	BOOLEAN dwRet = MmIsAddressValid(Address);
	if (dwRet)
	{
		KdPrint(("yjx[sys64] RtlCopyMemory(Address, Buffer, Length);\r\n", Address, Buffer, Length));

		//RtlCopyMemory(Address, tmpBuf_Kernel, Length); //一定要用内核内存 中转
		RtlCopyMemory(tmpBuf_Kernel, Address, Length); // c/c++ memcpy 

	}
	else
	{
		KdPrint(("yjx:sys64:Error Line37"));
	}
	//分离目标进程空间 恢复环境
	KeUnstackDetachProcess(&apc_state);
	DbgPrint("yjx: sys分离目标进程");
	RtlCopyMemory(Buffer, tmpBuf_Kernel, Length);
	//DbgPrint("yjx:sys: Buffer[0]=%llx", *(UINT64*)Buffer);;
	ExFreePool(tmpBuf_Kernel);
	return dwRet;
}
//dwPid为目标进程id
//lpBaseAddress 目标进程地址

//lpBuffer 当前进程地址 1
//内核内存地址 当前进程地址 2
int ReadProcessMemoryForPid(UINT32 dwPid, PVOID pBase, PVOID lpBuffer, UINT32 nSize)
{
	//根据pid获取PEPROCESS OpenProcess
	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 = KReadProcessMemory(Seleted_pEPROCESS, (PVOID)pBase, nSize, lpBuffer);
		ObDereferenceObject(Seleted_pEPROCESS);
		if (br)
		{
			return nSize;
		}
	}
	else
	{
		KdPrint(("yjx sys64 PsLookupProcessByProcessId Fail..."));
	}

	return STATUS_SUCCESS;// STATUS_UNSUCCESSFUL;

}


//int ReadProcessMemoryForPid(UINT32 dwPid, PVOID pBase, PVOID lpBuffer, UINT32 nSize);
void IRP_IO_通过PID读取数据(PIRP pirp)
{
	PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(pirp); //获取应用层传来的参数
	UINT64* 缓冲区 = (UINT64*)(pirp->AssociatedIrp.SystemBuffer);
	KdPrint(("yjx:%s 行号%d\n", __FUNCDNAME__, __LINE__));
	if (缓冲区)
	{
		//
		//int*p = (int*)缓冲区;
		UINT32 PID =     (UINT32)(UINT64)缓冲区[0]; //传入数据
		PVOID pBase =    (PVOID)(UINT64)缓冲区[1]; //传入数据
		//PVOID lpBuffer = (PVOID)(UINT64)缓冲区[2]; //传入数据
		UINT32 nSize = (UINT32)(UINT64)缓冲区[3]; //传入数据


	UINT32 ReadSize=	ReadProcessMemoryForPid(PID, pBase, 缓冲区, nSize);


		pirp->IoStatus.Status = STATUS_SUCCESS;
		pirp->IoStatus.Information = nSize;//返回给DeviceIoControl中的 倒数第二个参数lpBytesReturned
		IoCompleteRequest(pirp, IO_NO_INCREMENT);//调用方已完成所有I/O请求处理操作 并且不增加优先级 
	}
	irpStack;
}
