好友
阅读权限10
听众
最后登录1970-1-1
|
//实现功能:为当前运行中的某一程序申请一块内存,并可进行读写。
//有什么用?如何功能扩展?请有兴趣的朋友自己探索!
#include <ntddk.h>
typedef struct _KAPC_STATE {
LIST_ENTRY ApcListHead[MaximumMode];
struct _KPROCESS *Process;
union {
UCHAR InProgressFlags;
struct {
BOOLEAN KernelApcInProgress : 1;
BOOLEAN SpecialApcInProgress : 1;
};
};
BOOLEAN KernelApcPending;
BOOLEAN UserApcPending;
} KAPC_STATE, *PKAPC_STATE, *PRKAPC_STATE;
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_IRQL_requires_max_(APC_LEVEL)
NTKERNELAPI
VOID
KeStackAttachProcess (
_Inout_ PRKPROCESS PROCESS,
_Out_ PRKAPC_STATE ApcState
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_IRQL_requires_max_(APC_LEVEL)
NTKERNELAPI
VOID
KeUnstackDetachProcess (
_In_ PRKAPC_STATE ApcState
);
#endif
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(_In_ HANDLE ProcessId,_Outptr_ PEPROCESS *Process);
NTSTATUS
ZwAllocateVirtualMemory(
__in HANDLE ProcessHandle,
__inout PVOID *BaseAddress,
__in ULONG_PTR ZeroBits,
__inout PSIZE_T RegionSize,
__in ULONG AllocationType,
__in ULONG Protect
);
KIRQL Irql;
VOID WPOFF()
{
ULONG_PTR cr0 = 0;
Irql = KeRaiseIrqlToDpcLevel();
cr0 = __readcr0();
cr0 &= 0xfffffffffffeffff;
__writecr0(cr0);
#ifdef _WIN64
_disable();
#endif
}
VOID WPON()
{
ULONG_PTR cr0 = __readcr0();
cr0 |= 0x10000;
#ifdef _WIN64
_enable();
#endif
__writecr0(cr0);
KeLowerIrql(Irql);
}
NTSTATUS ReadWriteProcess()
{
NTSTATUS Status;
HANDLE hProcess;
CLIENT_ID ClientId;
PVOID AllocateAddress;
size_t ReginSize;
OBJECT_ATTRIBUTES ObjAttr;
PEPROCESS Process = NULL;
ClientId.UniqueProcess = (HANDLE)9544; //进程句柄,可从任务管理器中取得
ClientId.UniqueThread = 0;
AllocateAddress = 0; //不赋值 会C000018错误
memset(&ObjAttr, 0, sizeof(OBJECT_ATTRIBUTES));
PsLookupProcessByProcessId((HANDLE)ClientId.UniqueProcess, &Process);
Status = ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &ObjAttr, &ClientId);
if (!NT_SUCCESS(Status))
{
DbgPrint("ZwOpenProcess Error -- %#X", Status);
ZwClose(hProcess);
return Status;
}
DbgPrint("ZwOpenProcess Success");
ReginSize = 0xff;
Status = ZwAllocateVirtualMemory(hProcess, &AllocateAddress, 0, &ReginSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(Status))
{
DbgPrint("ZwAllocateVirtualMemory Error -- %#X", Status);
ZwClose(hProcess);
return Status;
}
/*要依附所在进程,才可以更改对应内存中的值*/
//--------------------------------------------------------
KAPC_STATE kApc;
KeStackAttachProcess((PRKPROCESS)Process, &kApc);
//--------------------------------------------------------
(DWORD32)(*(PVOID*)AllocateAddress) = 0xABCD; //写入内存
//---------------------
// (DWORD32)(*((PVOID*)AllocateAddress+4)) = 0xDCBA; //写入内存------------------------------------
KeUnstackDetachProcess(&kApc);
//////////////////////////////////////////////////////////
DbgPrint("address: %p - %p -size:- %d", &AllocateAddress, AllocateAddress, ReginSize);
// WPON();
// DbgPrint("%p\n",*(PVOID*)AllocateAddress);
// WPOFF();
ZwClose(hProcess);
return Status;
}
HANDLE DriverAllocMem(HANDLE ProcessId, ULONG RegionSize)
{
NTSTATUS status;
PEPROCESS Process;
HANDLE BaseAddr = NULL;
KAPC_STATE ApcState;
status = PsLookupProcessByProcessId(ProcessId, &Process);
if (NT_SUCCESS(status))
{
KeStackAttachProcess((PKPROCESS)Process, &ApcState);
_try
{
ZwAllocateVirtualMemory(NtCurrentProcess(), (PVOID*)&BaseAddr, 0, (PSIZE_T)&RegionSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
MmProtectMdlSystemAddress(BaseAddr, PAGE_EXECUTE_READWRITE);
RtlZeroMemory(BaseAddr, RegionSize); //关键点
//这里是关键点,内存清理后,然后ring0下再调用 VirtualProtectEx() 修改内存属性,这样申请到的内存,用之前的代码,就莫名其妙的就可以访问了
//原因我不懂,之前因为申请到的内存,不能访问,我就用CE查看内存,然后发现用CE访问过后的内存就可以驱动读写了
//后来我就胡乱测试,发现这个方法可以,ring0申请内存,然后清零,然后ring3修改内存属性,就可以访问
KeUnstackDetachProcess(&ApcState);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
KeUnstackDetachProcess(&ApcState);
return 0;
}
}
return BaseAddr;
}
VOID MyUnload(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("GoodBye World!");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegisterPath)
{
pDriverObject->DriverUnload = MyUnload;
DbgPrint("Hello World");
ReadWriteProcess();
return STATUS_SUCCESS;
}
//可用CheatEngine 软件工具打开对应进程句柄号的程序,查看相应内容地址的属性和内容
|
|