syw6616 发表于 2024-9-17 21:19

驱动编程方式实现win10 64位下读写某一进程的内存数据

//实现功能:为当前运行中的某一程序申请一块内存,并可进行读写。
//有什么用?如何功能扩展?请有兴趣的朋友自己探索!

#include <ntddk.h>

typedef struct _KAPC_STATE {
        LIST_ENTRY ApcListHead;
        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 HANDLEProcessHandle,
__inout PVOID*BaseAddress,
__in ULONG_PTRZeroBits,
__inout PSIZE_TRegionSize,
__in ULONGAllocationType,
__in ULONGProtect
);

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;
        HANDLEhProcess;
        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 软件工具打开对应进程句柄号的程序,查看相应内容地址的属性和内容

Panel 发表于 2024-9-17 21:26

你不如直接替换cr3寄存器
#include <intrin.h>
#include <ntifs.h>

VOIDUnloadDriver(PDRIVER_OBJECT pDriver)
{}

typedef struct _PROCESS_DATA_
{
      CHAR ignore;
      ULONGLONG DirectoryTableBase;
}PROCESS_DATA,*PPROCESS_DATA;

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pRegpath)
{

      pDriver->DriverUnload = UnloadDriver;

      NTSTATUS status = STATUS_SUCCESS;
      PEPROCESS pEprocess = NULL;
      ULONG oldcr3;

      status = PsLookupProcessByProcessId(5420,&pEprocess);

      if (!NT_SUCCESS(status))
      {
                return STATUS_UNSUCCESSFUL;
      }

      ObDereferenceObject(pEprocess);

      PPROCESS_DATA pdata = pEprocess;

      _disable();

      oldcr3 = __readcr3();

      __writecr3(pdata->DirectoryTableBase);
      
      CHAR buffer = { 0 };

      __try {

                ProbeForRead(0xf20020,10,1);

                RtlCopyMemory(buffer, 0xf20020, 10);

                for (size_t i = 0; i < 10; i++)
                {
                        DbgPrintEx(77, 0, "%2x ", buffer);
                }

                DbgPrintEx(77, 0, "\n");
      }
      __except(1){
               
      }


      __writecr3(oldcr3);

      _enable();


      return STATUS_SUCCESS;
}

syw6616 发表于 2024-9-17 22:46

学习了,谢谢!{:1_921:}

szluyang 发表于 2024-9-18 12:54

会编程的人都好厉害。

CGPZ 发表于 2024-9-18 18:12

那个啥,这个驱动编程写的是到底是驱动文件(配置文件inf),还是里面的驱动文件内容
页: [1]
查看完整版本: 驱动编程方式实现win10 64位下读写某一进程的内存数据