一、驱动层写数据源码
1、具体功能实现
BOOLEAN KWriteProcessMemory(IN PEPROCESS 目标进程, IN PVOID 被写入地址, IN UINT32 写入长度, IN PVOID 待写入数据) { KAPC_STATE apc_state; RtlZeroMemory(&apc_state, sizeof(KAPC_STATE)); //创建MDL来读取内存 PMDL 映射内存结构 = IoAllocateMdl(待写入数据, 写入长度, 0, 0, NULL); if (!映射内存结构) { return FALSE; } //将映射内存变成可读 MmBuildMdlForNonPagedPool(映射内存结构); //获取可读的地址 unsigned char* 可写内存 = (unsigned char*)MmMapLockedPages(映射内存结构, KernelMode); if (!可写内存) { IoFreeMdl(映射内存结构); return FALSE; } //切换到目标进程进行操作 KeStackAttachProcess((PVOID)目标进程, &apc_state); //判断该地址是否可读 BOOLEAN 是否可读 = MmIsAddressValid(被写入地址); if (是否可读) { RtlCopyMemory(被写入地址, 可写内存, 写入长度); } else { KdPrint(("nxyn2不可读")); } //恢复环境 KeUnstackDetachProcess(&apc_state); MmUnmapLockedPages((PVOID)可写内存, 映射内存结构); IoFreeMdl(映射内存结构); return 是否可读; } int WriteProcessMemoryForPid(UINT32 dwPid, PVOID 目标地址, PVOID 写入地址, UINT32 写入大小) { //根据pid获取PEPROCESS PEPROCESS Seleted_pEPROCESS = NULL; if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(dwPid), &Seleted_pEPROCESS) == STATUS_SUCCESS) { BOOLEAN br = KWriteProcessMemory(Seleted_pEPROCESS, (PVOID)目标地址, 写入大小, 写入地址); ObDereferenceObject(Seleted_pEPROCESS); if (br) { return 写入大小; } } else { KdPrint(("nxyn 2读取失败")); } return 0; } NTSTATUS IRP_WriteProcessMemory(PIRP pirp) { NTSTATUS ntStatus = STATUS_SUCCESS; PIO_STACK_LOCATION irpStack = NULL; irpStack = IoGetCurrentIrpStackLocation(pirp); #pragma pack(push) #pragma pack(8) typedef struct TINPUT_BUF { UINT64 dwPid;//目标进程PID PVOID 被写入地址; UINT64 写入长度; UINT64 写入地址; }TINPUT_BUF; #pragma pack(pop) TINPUT_BUF* 输入数据 = (TINPUT_BUF*)(pirp->AssociatedIrp.SystemBuffer); WriteProcessMemoryForPid(输入数据->dwPid, 输入数据->被写入地址, 输入数据->写入地址/*起始地址*/, 输入数据->写入长度); 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; }
2、在头文件声明IRP_WriteProcessMemory函数
NTSTATUS IRP_WriteProcessMemory(PIRP pirp);
3、控制码关联
#define irp写被保护数据 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED,FILE_ANY_ACCESS) else if (控制码== irp写被保护数据) { return IRP_WriteProcessMemory(IRP指针); }
二、应用层实现
1、添加一个按钮
2、源码实现
#define irp写被保护数据 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED,FILE_ANY_ACCESS) void CtestDlg::OnBnClickedButtonXrsj2() { #pragma pack(push) #pragma pack(8) typedef struct TINPUT_BUF { UINT64 dwPid;//目标进程PID PVOID 被写入地址; UINT64 写入长度; UINT64 写入地址; }TINPUT_BUF; #pragma pack(pop) UpdateData(true); DWORD 返回字节数 = 0; DWORD 临时数据 = 0; UINT_PTR 地址 = 0x406728; UINT64 待写入数据 = 123; TINPUT_BUF 输入缓存区 = { mbpid,(PVOID)地址,4 ,(UINT64) & 待写入数据}; DeviceIoControl( 设备句柄, irp写被保护数据, &输入缓存区, sizeof(TINPUT_BUF), &临时数据, sizeof(临时数据), &返回字节数, NULL ); char 缓存[256]; sprintf_s(缓存, "2写被保护值%X", 临时数据); ::MessageBoxA(0, 缓存, "2写被保护测试", MB_OK); }