滴水逆向联盟

标题: 请教监控MessageBoxW函数项目中遇到的问题!! [打印本页]

作者: xiaomingerniu    时间: 2023-12-19 22:56
标题: 请教监控MessageBoxW函数项目中遇到的问题!!
根据项目要求,利用InlineHook监控MessageBoxW函数,输出所有进程调用该函数时传入的参数。
我的思路是:
一、在3环程序中:
1、通过驱动,在MessageBoxW函数所在的内存区域中找到一处大小为0x20字节、值全为0的的空间(ParamAddr),将该地址PTE的R/W位为1,用于后续存放MessageBoxW的4个参数;
2、通过驱动,在MessageBoxW函数所在的内存区域中找到一处大小为0x100字节、值全为0的空间(ShellCode_End),并验证该地址处的PTE,确保其R/W位为1后写入ShellCode,内容是利用与ESP的偏移取出传入的4个参数,并将其依次存入步骤1中寻找到的内存区域,然后继续MessageBoxW函数开头5个字节的命令,最后调回MessageBoxW函数起始位置+5处;
3、通过驱动,改写MessageBoxW函数地址处的PTE,使其R/W位为1,然后将其覆写为大小为5字节的jmp硬编码(ShellCode_Begin),使其执行时跳转到步骤2中寻找到的内存区域。
4、通过一个循环函数或者另起一个线程,不断输出步骤1中的内存区域中4个地址的值,也就是传入的MessageBoxW的4个参数。
二、在0环程序中:
通过3环传入的控制码,实现查找、改写指定内存地址的PTE,以及在MessageBoxW函数所在的内存区域中找到符合条件的内存区域等功能

目前遇到的问题就是,我还是只能正常输出本进程的参数,在其他进程调用MessageBoxW函数时,会显示内存访问失败,经查看WinDbg,发现是步骤1中的内存地址,也就是用于存放MessageBoxW函数参数的内存地址PTE的R/W位为0;但不解的是,同样的物理地址,利用!vtop命令查看不同的进程,PTE的R/W位竟然不同:本进程的PTE的R/W位是1?WinDbg内容如下:
106c03a0 是本进程
kd> !vtop 106c03a0 77d703c4
X86VtoP: Virt 0000000077d703c4, pagedir 00000000106c03a0
X86VtoP: PAE PDPE 00000000106c03a8 - 0000000030ec2001
X86VtoP: PAE PDE 0000000030ec2df0 - 0000000030b20067
X86VtoP: PAE PTE 0000000030b20b80 - 0000000027007067
X86VtoP: PAE Mapped phys 00000000270073c4
Virtual address 77d703c4 translates to physical address 270073c4.
106c03e0 是另外一个用于测试的调用MessageBoxW函数的进程
kd> !vtop 106c03e0 77d703c4
X86VtoP: Virt 0000000077d703c4, pagedir 00000000106c03e0
X86VtoP: PAE PDPE 00000000106c03e8 - 000000003a6d1001
X86VtoP: PAE PDE 000000003a6d1df0 - 000000003a687067
X86VtoP: PAE PTE 000000003a687b80 - 0000000027007025
X86VtoP: PAE Mapped phys 00000000270073c4
Virtual address 77d703c4 translates to physical address 270073c4.

为啥物理地址同样是270073c4,PTE一个是27007067,一个是27007025?

我把代码贴出来,恳请老师指教!!!万分感谢!!!

3环的************************************************************************************************************************
#include <Windows.h>
#include <stdio.h>
#include <WINIOCTL.H>

//获取值
#define GETVALUE CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ANY_ACCESS)
//修改值
#define CHANGEVALUE CTL_CODE(FILE_DEVICE_UNKNOWN,0x802,METHOD_BUFFERED,FILE_ANY_ACCESS)
//在DLL空间分配内存
#define ALLOCATE CTL_CODE(FILE_DEVICE_UNKNOWN,0x803,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define SYMBOLLINKNAME L"\\\\.\\SymbolLinkName"
#define SHELLCODESIZE 0x100
#define PARAMSIZE 0x40

struct IO {
        DWORD dwAddress;
        DWORD dwSize;
};

DWORD g_dwParamAddr = 0;
HANDLE g_hDevice = NULL;

BYTE OrgCode[5] = {0x8b,0xff,0x55,0x8b,0xec};
BYTE ShellCode_Begin[5] = {0};
BYTE ShellCode_End[] = {

        0x60,                                                //pushad
        0x9c,                                                //pushfd
       
        0x8B,0x44,0x24,0x34,                //mov eax,dword ptr [esp+0x34]
        0xA3,0x00,0x10,0x40,0x00,        //mov dword ptr ds:[0x0040100],eax        //待修改
        0x8B,0x44,0x24,0x30,                //mov eax,dword ptr [esp+0x30]
        0xA3,0x00,0x10,0x40,0x00,        //mov dword ptr ds:[0x0040100],eax        //待修改
        0x8B,0x44,0x24,0x2c,                //mov eax,dword ptr [esp+0x2c]
        0xA3,0x00,0x10,0x40,0x00,        //mov dword ptr ds:[0x0040100],eax        //待修改
        0x8B,0x44,0x24,0x28,                //mov eax,dword ptr [esp+0x28]
        0xA3,0x00,0x10,0x40,0x00,        //mov dword ptr ds:[0x0040100],eax        //待修改

        0x9d,                                                //popfd
        0x61,                                                //popad

        //OrgShellCode
        0x8b,0xff,                                        //mov edi,edi
        0x55,                                                //push ebp
        0x8b,0xec,                                        //mov ebp,esp

        //Jump Return
        0xe9,0x00,0x00,0x00,0x00,        //待修改

        //nop
        0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,
        0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,
        0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,
};


void ChangeShellCode(PBYTE ShellCode, DWORD dwSize, PBYTE pbSource);
void FixFuncAddr(PDWORD pdwFuncAddr);
BOOL CreateIoConnect();
BOOL VerfyPTE(HANDLE hDevice, DWORD dwLinnerAddr);
DWORD WINAPI ThreadProc(LPVOID lpParameter);

int main()
{
        DWORD dwMsgwAddr = 0;
        DWORD dwMyMsgwAddr = 0;
        DWORD dwReturnLength = 0;
        BOOL bRet = FALSE;
        DWORD dwPTE = 0;
        DWORD dwPteAddr = 0;

        //获取MessageBoxW地址
        printf("\n获取MessageBoxW地址\n");
        PBYTE pbMsgBoxW = (PBYTE)MessageBoxW;
        printf("MessageBoxW's First Byte Is 0x%.2x\n",*pbMsgBoxW);
        dwMsgwAddr = (DWORD)pbMsgBoxW;
        printf("MessageBoxW地址:0x%.8X\n", dwMsgwAddr);

        //查看MessageBoxW前5个字节
        printf("\n查看MessageBoxW前5个字节:");
        for (DWORD i = 0; i < sizeof(ShellCode_Begin); i++)
        {
                printf("0x%.2x  ", pbMsgBoxW[i]);
        }
        printf("\n");

        //创建设备连接
        printf("\n创建设备连接\n");
        HANDLE hDevice = CreateFileW(SYMBOLLINKNAME,GENERIC_ALL,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
        if (hDevice == INVALID_HANDLE_VALUE)
        {
                printf("Create Device Failed, ErrCode Is %d\n",GetLastError());
                system("pause");
                return -1;
        }
        printf("Create Device Success\n");
        g_hDevice = hDevice;

        //检查MessageBoxW的PTE
        printf("\n检查MessageBoxW地址(0x%.8X)的PTE\n",dwMsgwAddr);
        if (!VerfyPTE(hDevice,dwMsgwAddr))
        {
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }


       
        //*****************************************ShellCode_End***************************************************************
        //1.利用驱动在Dll空间存放ShellCode_End
        printf("\n利用驱动在Dll空间存放ShellCode_End\n");
        IO stIo_1;
        stIo_1.dwAddress = dwMsgwAddr;
        stIo_1.dwSize = SHELLCODESIZE;
        bRet = DeviceIoControl(hDevice,ALLOCATE,&stIo_1,sizeof(stIo_1),&dwMyMsgwAddr,sizeof(dwMyMsgwAddr),&dwReturnLength,NULL);
        if (bRet == FALSE)
        {
                printf("DeviceIoControl ALLOCATE Failed, ErrCode Is %d\n",GetLastError());
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }
        printf("DeviceIoControl ALLOCATE Success!\nShellCode_End's Store Address Is 0x%.8X,ReturnLength Is %d\n",dwMyMsgwAddr,dwReturnLength);
        //检查ShellCode_End的PTE
        printf("\n检查ShellCode_End地址(0x%.8X)的PTE\n",dwMyMsgwAddr);
        if (!VerfyPTE(hDevice,dwMyMsgwAddr))
        {
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }

        //2.修正跳回地址
        printf("\n修正跳回地址:0x%.8x\n",dwMsgwAddr + 5);
        //跳转地址 = 当前地址 + 5 + E9参数
        //E9参数 = 跳转地址 - 当前地址 - 5
        DWORD dwBackAddr = dwMsgwAddr + 5 - (DWORD)(dwMyMsgwAddr + 0x2d) - 5;
        printf("E9参数:0x%.8X\n", dwBackAddr);
        ChangeShellCode((PBYTE)(ShellCode_End + 0x2e), 4, (PBYTE)(&dwBackAddr));

        //3.在DLL空间分配内存,用于存放传入MessageBoxW的4个参数
        printf("\n在DLL空间分配内存,用于存放传入MessageBoxW的4个参数\n");
        IO stIo_2;
        stIo_2.dwAddress = (DWORD)(dwMyMsgwAddr + sizeof(ShellCode_End));
        stIo_2.dwSize = PARAMSIZE;
        DWORD dwParamAddr = 0;
        DWORD arrParamAddr[4] = {0};
        bRet = DeviceIoControl(hDevice,ALLOCATE,&stIo_2,sizeof(stIo_2),&dwParamAddr,sizeof(dwParamAddr),&dwReturnLength,NULL);
        if (bRet == FALSE)
        {
                printf("DeviceIoControl ALLOCATE Failed, ErrCode Is %d\n",GetLastError());
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }
        printf("DeviceIoControl ALLOCATE Success!\nParameter's Store Address Is 0x%.8X,ReturnLength Is %d\n",dwParamAddr,dwReturnLength);
        g_dwParamAddr = dwParamAddr;
       
        //分4个部分存放
        printf("存放参数的地址分别为:\n");
        for (i = 0; i < 4; i++)
        {
                arrParamAddr[i] = dwParamAddr + i * 4;
                printf("0x%.8X ",arrParamAddr[i]);
        }
        printf("\n");
       
        //分4个部分修改
        ChangeShellCode((PBYTE)(ShellCode_End + 0x07),4,(PBYTE)(&arrParamAddr[0]));
        ChangeShellCode((PBYTE)(ShellCode_End + 0x10),4,(PBYTE)(&arrParamAddr[1]));
        ChangeShellCode((PBYTE)(ShellCode_End + 0x19),4,(PBYTE)(&arrParamAddr[2]));
        ChangeShellCode((PBYTE)(ShellCode_End + 0x22),4,(PBYTE)(&arrParamAddr[3]));
       
        //检查存放参数处的PTE
        printf("\n检查存放参数地址(0x%.8X)的PTE\n",dwParamAddr);
        if (!VerfyPTE(hDevice,dwParamAddr))
        {
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }
       
        printf("\n在Dll空间写入ShellCode_End\
        //4.在Dll空间写入ShellCode_Endn");
        memcpy((LPVOID)dwMyMsgwAddr, (LPVOID)ShellCode_End, sizeof(ShellCode_End));
        printf("ShellCode_End Success\n");

        //*****************************************ShellCode_Begin***************************************************************
        //修正ShellCode_Begin
        //E9参数 = 跳转地址 - 当前地址 - 5
        printf("\n修正ShellCode_Begin\n");
        DWORD dwJumpAddr = dwMyMsgwAddr - dwMsgwAddr - 5;
        printf("ShellCode_Begin:0x%.8X\n", (DWORD)ShellCode_Begin);
        printf("ShellCode_End:0x%.8X\n", (DWORD)ShellCode_End);
        printf("E9参数:0x%.8X\n", dwJumpAddr);
        ShellCode_Begin[0] = 0xe9;
        ChangeShellCode((PBYTE)(ShellCode_Begin + 1), 4, (PBYTE)(&dwJumpAddr));
       
        //在Dll空间写入ShellCode_Begin
        printf("\n在Dll空间写入ShellCode_Begin\n");
        memcpy((LPVOID)dwMsgwAddr, (LPVOID)ShellCode_Begin, sizeof(ShellCode_Begin));
        printf("ShellCode_Begin Success\n");       

        //*****************************************CreateThread***************************************************************
        //printf("\n创建线程\n");
        printf("监视MessageBoxW参数地址的变化\n");       
        if (!VerfyPTE(hDevice,g_dwParamAddr))
        {
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }       
        //HANDLE hThread = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);

        //测试MessageBoxW
        printf("\n测试MessageBoxW,按任意键开始\n");
        getchar();
        //MessageBoxW(NULL,L"Hello",L"Caption",MB_OKCANCEL);
        ThreadProc(NULL);
        //MessageBoxW(0,0,0,0);
        //ThreadProc(NULL);

        /*
        if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED)
        {
                printf("等待线程结束失败,错误代码:%d\n",GetLastError());
        }
        printf("线程已终止\n");
        Sleep(500);
        CloseHandle(hThread);
        printf("\n线程句柄已关闭\n");
        */

        //收尾
        printf("\n检查MessageBoxW函数起始地址(0x%.8X)的PTE\n",dwMsgwAddr);
        if (!VerfyPTE(hDevice,dwMsgwAddr))
        {
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }
        printf("恢复MessageBoxW函数起始处硬编码\n");
        memcpy((LPVOID)dwMsgwAddr,OrgCode,5);

        printf("\n检查注入ShellCode函数起始地址(0x%.8X)的PTE\n",dwMyMsgwAddr);
        if (!VerfyPTE(hDevice,dwMyMsgwAddr))
        {
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }
        printf("恢复注入ShellCode处硬编码\n");
        memset((LPVOID)dwMyMsgwAddr,0,SHELLCODESIZE);

        printf("\n检查注入MessageBoxW参数地址(0x%.8X)的PTE\n",dwParamAddr);
        if (!VerfyPTE(hDevice,dwParamAddr))
        {
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }
        printf("恢复注入MessageBoxW参数处硬编码\n");
        memset((LPVOID)dwParamAddr,0,PARAMSIZE);
       
        CloseHandle(hDevice);
        printf("\n设备句柄已关闭\n\n");
        system("pause");
        return 0;
}

void ChangeShellCode(PBYTE ShellCode, DWORD dwSize, PBYTE pbSource)
{
        printf("修改前的ShellCode:");
        for (DWORD i = 0; i < dwSize; i++)
        {
                printf("0x%.2x  ", ShellCode[i]);
                ShellCode[i] = pbSource[i];
        }

        printf("\n修改后的ShellCode:");
        for (i = 0; i < dwSize; i++)
        {
                printf("0x%.2x  ", ShellCode[i]);
        }
        printf("\n");
}

void FixFuncAddr(PDWORD pdwFuncAddr)
{
        printf("修正前,函数地址:0x%.8X\n", *pdwFuncAddr);
        if (*(PBYTE)(*pdwFuncAddr) == 0xe9)
        {
                *pdwFuncAddr = *pdwFuncAddr + 5 + *(PDWORD)(*pdwFuncAddr + 1);
        }
        printf("修正后,函数地址:0x%.8X\n", *pdwFuncAddr);
}

BOOL CreateIoConnect()
{
        //打开设备句柄时,请使用其他 CreateFile 参数,如下所示:       
        //fdwCreate 参数必须指定OPEN_EXISTING。
        HANDLE hDevice = CreateFileW(SYMBOLLINKNAME,GENERIC_ALL,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
        if (hDevice == INVALID_HANDLE_VALUE)
        {
                printf("CreateFile Failed, ErrCode Is %d\n",GetLastError());
                return FALSE;
        }
        printf("CreateFile Success\n");       
        return TRUE;
}

BOOL VerfyPTE(HANDLE hDevice, DWORD dwLinnerAddr)
{
        DWORD dwPTE = 0;
        DWORD dwReturnLength = 0;
        DWORD dwPteAddr = 0xc0000000 + ((dwLinnerAddr >> 9) & 0x7ffff8);
        BOOL bRet = DeviceIoControl(hDevice,GETVALUE,&dwPteAddr,sizeof(dwPteAddr),&dwPTE,sizeof(dwPTE),&dwReturnLength,NULL);
        if (bRet == FALSE)
        {
                printf("DeviceIoControl GETVALUE Failed, ErrCode Is %d\n",GetLastError());
                return FALSE;
        }
        printf("DeviceIoControl GETVALUE Success!\n0x%.8X处的PTE:0x%.8X,ReturnLength Is %d\n",dwLinnerAddr,dwPTE,dwReturnLength);
        //判断是否需要修改PTE
        if ((dwPTE & 0x3) != 3)
        {
                //修改PTE为可读可写
                bRet = DeviceIoControl(hDevice,CHANGEVALUE,&dwPteAddr,sizeof(dwPteAddr),&dwPTE,sizeof(dwPTE),&dwReturnLength,NULL);
                if (bRet == FALSE)
                {
                        printf("DeviceIoControl CHANGEVALUE Failed, ErrCode Is %d\n",GetLastError());
                        return FALSE;
                }
                printf("DeviceIoControl CHANGEVALUE Success!\nNew PTE Is 0x%.8X,ReturnLength Is %d\n",dwPTE,dwReturnLength);
        }
        else
        {
                printf("无须修改PTE\n");
        }

        return TRUE;
}

DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
       
        printf("\n线程函数已启动,按Q键终止\n");
        printf("检查传入参数地址(0x%.8X)的PTE\n",g_dwParamAddr);
        if (!VerfyPTE(g_hDevice,g_dwParamAddr))
        {
                system("pause");
                return -1;
        }

        DWORD dwOrgData = *(PDWORD)g_dwParamAddr;

        DWORD arrParamAddr[4] = {0};
        arrParamAddr[0] = *(PDWORD)(g_dwParamAddr + 0x0);
        arrParamAddr[1] = *(PDWORD)(g_dwParamAddr + 0x4);
        arrParamAddr[2] = *(PDWORD)(g_dwParamAddr + 0x8);
        arrParamAddr[3] = *(PDWORD)(g_dwParamAddr + 0xc);

        //printf("MessageBoxW(0x%x,0x%x,0x%x,0x%x)\n",arrParamAddr[3],arrParamAddr[2],arrParamAddr[1],arrParamAddr[0]);       
       
        while (!GetAsyncKeyState('Q'))
        {
                Sleep(2000);
                printf("MessageBoxW(0x%x,0x%x,0x%x,0x%x)\n",arrParamAddr[3],arrParamAddr[2],arrParamAddr[1],arrParamAddr[0]);
        }

        printf("按任意键结束线程\n");
        getchar();
       
        return 0;
}


0环的************************************************************************************************************************
#include <ntifs.h>

//获取值
#define GETVALUE CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ANY_ACCESS)
//修改值
#define CHANGEVALUE CTL_CODE(FILE_DEVICE_UNKNOWN,0x802,METHOD_BUFFERED,FILE_ANY_ACCESS)
//在DLL空间分配内存
#define ALLOCATE CTL_CODE(FILE_DEVICE_UNKNOWN,0x803,METHOD_BUFFERED,FILE_ANY_ACCESS)

//将在多处引用,所以作为宏全局声明,避免多次输入
#define DEVICENAME L"\\Device\\MyDevice"
#define SYMBOLLINKNAME L"\\??\\SymbolLinkName"

//停止循环输出函数的指令
ULONG g_ulFlag = 0;
//PDRIVER_OBJECT
PDRIVER_OBJECT g_pDriver = NULL;

//驱动停止函数
VOID DriverUnload(PDRIVER_OBJECT pDriver);
//派遣函数:Create
NTSTATUS DispatchCreateFunc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp);
//派遣函数:Close
NTSTATUS DispatchCloseFunc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp);
//派遣函数:DeviceControl
NTSTATUS DispatchDeviceControlFunc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp);

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
        NTSTATUS status;
        ULONG ulRet = 0;
        PDEVICE_OBJECT pDeviceObj;
        UNICODE_STRING DeviceName;
        UNICODE_STRING SymbolLinkName;
        g_pDriver = pDriver;

        //设置设备名称
        RtlInitUnicodeString(&DeviceName,DEVICENAME);
        //设置符号链接名称
        RtlInitUnicodeString(&SymbolLinkName,SYMBOLLINKNAME);

        //创建设备对象
        status = IoCreateDevice(pDriver,0,&DeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&pDeviceObj);
        if (status != STATUS_SUCCESS)
        {
                DbgPrint("创建设备对象失败\r\n");
                //If a driver's call to IoCreateDevice returns an error, the driver should release any resources that it allocated for that device.
                IoDeleteDevice(pDeviceObj);
                return status;
        }

        //设置交互方式
        pDeviceObj->Flags |= DO_BUFFERED_IO;

        //创建符号链接
        status = IoCreateSymbolicLink(&SymbolLinkName,&DeviceName);
        if (status != STATUS_SUCCESS)
        {
                DbgPrint("创建符号链接失败\r\n");
                return STATUS_UNSUCCESSFUL;
        }

        //设置派遣函数
        pDriver->MajorFunction[IRP_MJ_CREATE] = DispatchCreateFunc;
        pDriver->MajorFunction[IRP_MJ_CLOSE] = DispatchCloseFunc;
        pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControlFunc;

        pDriver->DriverUnload = DriverUnload;

        return STATUS_SUCCESS;
}

//驱动停止函数
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
        //删除符号链接
        UNICODE_STRING SymbolLinkName;
        RtlInitUnicodeString(&SymbolLinkName,SYMBOLLINKNAME);
        IoDeleteSymbolicLink(&SymbolLinkName);

        //删除设备
        //This member is automatically updated when the driver calls IoCreateDevice successfully.
        //A driver can use this member and the NextDevice member of DEVICE_OBJECT to step through a list of all the device objects that the driver created.
        IoDeleteDevice(pDriver->DeviceObject);

        DbgPrint("驱动已停止\r\n");
}

//派遣函数:Create
NTSTATUS DispatchCreateFunc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp)
{
        NTSTATUS status = STATUS_SUCCESS;
        DbgPrint("Create Dispatch Function Success\r\n");       

        //将IRP中的状态置为成功
        pIrp->IoStatus.Status = status;
        //返还的字节数
        pIrp->IoStatus.Information = 0;//Information 的类型是 ULONG_PTR,即 unsinged long
        //结束IRP请求
        IoCompleteRequest(pIrp,IO_NO_INCREMENT);

        return status;
}

//派遣函数:Close
NTSTATUS DispatchCloseFunc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp)
{
        NTSTATUS status = STATUS_SUCCESS;
        DbgPrint("Close Dispatch Function Success\r\n");

        pIrp->IoStatus.Status = status;
        pIrp->IoStatus.Information = 0;
        IoCompleteRequest(pIrp,IO_NO_INCREMENT);

        return status;
}

//派遣函数:DeviceControl
NTSTATUS DispatchDeviceControlFunc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp)
{
        NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
        PIO_STACK_LOCATION pIrpStack;
        ULONG ulRead = 0;
        ULONG ulWrite = 0;
        //从三环传入的ShellCode_End大小
        ULONG ulBufferSize = 0;
        //ZeroMemoryBuffer
        PUCHAR pcZeroBuffer = NULL;
        //存放ShellCode_End的地址
        PUCHAR pcShellBuffer = NULL;
        ULONG ulRet = 0;

        //从三环传入的控制码
        ULONG IoControlCode;
        //从三环传入的数据长度
        ULONG IoInLength;
        //向三环输出的数据长度
        ULONG IoOutLength;
        //向三环实际输出的数据长度
        ULONG RealOutLength;
        //与三环传输的缓冲区(输入、输出是同一个缓冲区)
        PVOID pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;       

        DbgPrint("DeviceControl Dispatch Function Success\r\n");

        //接收来自三环的数据(IRP)
        pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
        //接收控制码
        IoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
        //接收传入数据长度
        IoInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
        //输出数据长度
        IoOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
        //确定交互数据的缓冲区
        pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;

        //分析收到的控制码
        switch (IoControlCode)
        {
        case GETVALUE:
                {
                        DbgPrint("\r\nGETVALUE\r\n");
                        //读取缓冲区
                        RtlCopyMemory(&ulRead,pIoBuffer,sizeof(ulRead));
                        DbgPrint("需要查找的内存地址:0x%.8X\r\n",ulRead);

                        //写入缓冲区,发数据给三环
                        ulWrite = *(PULONG)ulRead;
                        DbgPrint("0x%.8X地址的值:0x%X\r\n",ulRead,ulWrite);
                        RtlCopyMemory(pIoBuffer,&ulWrite,sizeof(ulWrite));

                        //设置返还数据的长度
                        RealOutLength = sizeof(ulWrite);
                        pIrp->IoStatus.Information = RealOutLength;                       
                        DbgPrint("OutputLength Is %d\r\n",RealOutLength);

                        status = STATUS_SUCCESS;
                        break;
                }
        case CHANGEVALUE:
                {
                        DbgPrint("\r\nCHANGEVALUE\r\n");
                        //读取缓冲区
                        RtlCopyMemory(&ulRead,pIoBuffer,sizeof(ulRead));
                        DbgPrint("需要修改的内存地址:0x%.8X\r\n",ulRead);

                        //写入缓冲区,发数据给三环
                        //xx01 => xx11
                        *(PULONG)ulRead = ((*(PULONG)ulRead) & 0xfffffffc) + 3;
                        ulWrite = *(PULONG)ulRead;
                        DbgPrint("0x%.8X地址修改后的值:0x%X\r\n",ulRead,ulWrite);
                        RtlCopyMemory(pIoBuffer,&ulWrite,sizeof(ulWrite));

                        //设置返还数据的长度
                        RealOutLength = sizeof(ulWrite);
                        pIrp->IoStatus.Information = RealOutLength;                       
                        DbgPrint("OutputLength Is %d\r\n",RealOutLength);

                        status = STATUS_SUCCESS;
                        break;
                }
        case ALLOCATE:
                {
                        DbgPrint("\r\nWRITEMEMORY\r\n");
                        //读取缓冲区
                        RtlCopyMemory(&ulRead,pIoBuffer,sizeof(ulRead));
                        DbgPrint("从三环传入的遍历内存起始地址:0x%.8X\r\n",ulRead);
                        //从三环传入的ShellCode_End大小
                        RtlCopyMemory(&ulBufferSize,(PVOID)((ULONG)pIoBuffer + 4),sizeof(ulBufferSize));
                        DbgPrint("从三环传入的待开辟内存大小:0x%x\r\n",ulBufferSize);

                        //创建ZeroBuffer用于比较
                        pcZeroBuffer = (PUCHAR)ExAllocatePool(NonPagedPool,ulBufferSize);
                        if (pcZeroBuffer == NULL)
                        {
                                DbgPrint("ExAllocatePool失败\r\n");
                                status = STATUS_UNSUCCESSFUL;
                                break;
                        }
                        RtlFillMemory(pcZeroBuffer,ulBufferSize,0);

                        //遍历查找符合条件的内存区域
                        pcShellBuffer = (PUCHAR)ulRead;
                        while (TRUE)
                        {
                                ulRet = RtlCompareMemory(pcShellBuffer,pcZeroBuffer,ulBufferSize);

                                if (ulRet == ulBufferSize)
                                {
                                        DbgPrint("已找到0x%x大小的内存区域,地址:0x%.8X\r\n",ulBufferSize,(ULONG)pcShellBuffer);
                                        break;
                                }

                                pcShellBuffer += 4;
                        }

                        //写入缓冲区,发数据给三环
                        ulWrite = (ULONG)pcShellBuffer;
                        DbgPrint("可写入ShellCode的地址:0x%.8X\r\n",ulWrite);
                        RtlCopyMemory(pIoBuffer,&ulWrite,sizeof(ulWrite));

                        //设置返还数据的长度
                        RealOutLength = sizeof(ulWrite);
                        pIrp->IoStatus.Information = RealOutLength;                       
                        DbgPrint("OutputLength Is %d\r\n",RealOutLength);

                        status = STATUS_SUCCESS;
                        break;
                }
        default:
                DbgPrint("Switch Exception\r\n");
                break;
        }
       

        pIrp->IoStatus.Status = status;
        IoCompleteRequest(pIrp,IO_NO_INCREMENT);

        return STATUS_SUCCESS;
}



作者: xiaomingerniu    时间: 2023-12-31 22:19
后来换了个方法,实现了要求的功能:
将SHELLOCE写入USER32.DLL的领空,函数头插入JMP后,使用中断门提权,触发用去驱动在0环中写入的一个函数,利用0环ESP偏移算出3环的ESP,然后再计算参数所在的位置,将其传给DBGPRINT输出。总算在2023年最后做出这个项目了。

3环部分************************************************************************************************************************
#include <Windows.h>
#include <stdio.h>
#include <WINIOCTL.H>

//获取值
#define GETVALUE CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ANY_ACCESS)
//验证并修改页表
#define CHANGEVALUE CTL_CODE(FILE_DEVICE_UNKNOWN,0x802,METHOD_BUFFERED,FILE_ANY_ACCESS)
//在内核空间分配内存
#define ALLOCATE CTL_CODE(FILE_DEVICE_UNKNOWN,0x803,METHOD_BUFFERED,FILE_ANY_ACCESS)
//查找内存区域
#define LOOKUPMEMORY CTL_CODE(FILE_DEVICE_UNKNOWN,0x804,METHOD_BUFFERED,FILE_ANY_ACCESS)
//将0环HOOK函数修改页属性后传给三环
#define GETFUNCADDR CTL_CODE(FILE_DEVICE_UNKNOWN,0x805,METHOD_BUFFERED,FILE_ANY_ACCESS)
//修改IDT表
#define CHANGEIDTENTRY CTL_CODE(FILE_DEVICE_UNKNOWN,0x806,METHOD_BUFFERED,FILE_ANY_ACCESS)

#define SYMBOLLINKNAME L"\\\\.\\SymbolLinkName"
#define SHELLCODESIZE 0x100
#define PARAMSIZE 0x40
#define GATESIZE 0x40

DWORD g_dwMsgAddr = 0;
DWORD g_dwParamAddr = 0;
HANDLE g_hDevice = NULL;

BYTE OrgCode[5] = {0x8b,0xff,0x55,0x8b,0xec};
BYTE ShellCode_Begin[5] = {0};
BYTE ShellCode_End[] = {

        0x60,                                                        //pushad
        0x9c,                                                        //pushfd

        //InterruptGate
        0xcd,0x20,                                                //int 0x20

        0x9d,                                                        //popfd
        0x61,                                                        //popad

        //OrgShellCode
        0x8b,0xff,                                                //mov edi,edi
        0x55,                                                        //push ebp
        0x8b,0xec,                                                //mov ebp,esp

        //Jump Return
        0xe9,0x00,0x00,0x00,0x00,                //待修改
};
BYTE ShellCode_Int[] = {

        0x60,                                                        //pushfd
        0x9C,                                                        //pushfd
       
        0x8B,0x44,0x24,0x30,                        //mov eax,dword ptr [esp+0x30]
        0x8B,0x58,0x34,                                        //mov ebx,dword ptr [eax+0x34]
        0x53,                                                        //push ebx

        0x8B,0x44,0x24,0x34,                        //mov eax,dword ptr [esp+0x34]
        0x8B,0x58,0x30,                                        //mov ebx,dword ptr [eax+0x20]
        0x53,                                                        //push ebx

        0x8B,0x44,0x24,0x38,                        //mov eax,dword ptr [esp+0x38]
        0x8B,0x58,0x2c,                                        //mov ebx,dword ptr [eax+0x2C]
        0x53,                                                        //push ebx

        0x8B,0x44,0x24,0x3C,                        //mov eax,dword ptr [esp+0x3C]
        0x8B,0x58,0x28,                                        //mov ebx,dword ptr [eax+0x28]
        0x53,                                                        //push ebx

        0xB8,0xE0,0x18,0xC2,0xBA,                //mov eax,0xBAC218E0                                //待修改

        0xFF,0xD0,                                                //call eax
       
        0x9D,                                                        //popfd
        0x61,                                                        //popad
               
        0xCF,                                                        //iretd

        0x90,0x90,0x90,0x90
};

//修改ShellCode中指定位置的值
VOID ChangeShellCode(PBYTE ShellCode, DWORD dwSize, PBYTE pbSource);
//修正函数地址
VOID FixFuncAddr(PDWORD pdwFuncAddr);
//检查并修正线性地址的页属性
BOOL VerfyPage(HANDLE hDevice, DWORD dwLinnerAddr);
//循环输出指定内存地址的值
DWORD WINAPI ThreadProc(LPVOID lpParameter);
//利用驱动在Dll空间存放ShellCode_End
BOOL StoreShellEndInDll(IN HANDLE hDevice, IN DWORD dwStartAddr, OUT PDWORD pdwStoreAddr);
//利用驱动在Dll空间存放IntGate函数
BOOL StoreIntGateInDll(IN HANDLE hDevice, IN DWORD dwStartAddr, OUT PDWORD pdwStoreAddr);
//利用驱动将ShellCode_Begin覆盖函数头
BOOL ReWriteFuncHeaderWithShellCodeBegin(IN HANDLE hDevice, IN DWORD dwStartAddr, IN DWORD dwDestAddr);
//利用驱动在内核空间存放Parameter
BOOL StoreParameterInKernel(HANDLE hDevice);

//中断门
void __declspec(naked) IntGate()
{
        __asm
        {
                //int 3

                pushad                                                        //0x60,
                pushfd                                                        //0x9C,

                mov eax,dword ptr [esp+0x30]        //0x8B,0x44,0x24,0x30,
                mov ebx,dword ptr [eax+0x34]        //0x8B,0x58,0x34,
                push ebx                                                //0x53,

                mov eax,dword ptr [esp+0x34]        //0x8B,0x44,0x24,0x34,
                mov ebx,dword ptr [eax+0x30]        //0x8B,0x58,0x30,
                push ebx                                                //0x53,

                mov eax,dword ptr [esp+0x38]        //0x8B,0x44,0x24,0x38,
                mov ebx,dword ptr [eax+0x2c]        //0x8B,0x58,0x2c,
                push ebx                                                //0x53,

                mov eax,dword ptr [esp+0x3c]        //0x8B,0x44,0x24,0x3C,
                mov ebx,dword ptr [eax+0x28]        //0x8B,0x58,0x28,
                push ebx                                                //0x53,

                mov eax,0xBAC79A10                                //0xB8,0xE0,0x18,0xC2,0xBA,
                call eax                                                //0xFF,0xD0,

                popfd                                                        //0x9D,
                popad                                                        //0x61,

                iretd                                                        //0xCF
        }
}

int main()
{
        DWORD dwMsgwAddr = 0;
        DWORD dwMyMsgwAddr = 0;
        DWORD dwIntGateAddr = 0;
        DWORD dwReturnLength = 0;
        DWORD dwPTE = 0;
        DWORD dwPteAddr = 0;

        //获取MessageBoxW地址
        printf("\n获取MessageBoxW地址\n");
        PBYTE pbMsgBoxW = (PBYTE)MessageBoxW;
        printf("MessageBoxW's First Byte Is 0x%.2x\n",*pbMsgBoxW);
        dwMsgwAddr = (DWORD)pbMsgBoxW;
        g_dwMsgAddr = dwMsgwAddr;
        printf("MessageBoxW地址:0x%.8X\n", dwMsgwAddr);

        //查看MessageBoxW前5个字节
        printf("\n查看MessageBoxW前5个字节:");
        for (DWORD i = 0; i < sizeof(ShellCode_Begin); i++)
        {
                printf("0x%.2x  ", pbMsgBoxW[i]);
        }
        printf("\n");

        //创建设备连接
        printf("\n创建设备连接\n");
        HANDLE hDevice = CreateFileW(SYMBOLLINKNAME,GENERIC_ALL,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
        if (hDevice == INVALID_HANDLE_VALUE)
        {
                printf("Create Device Failed, ErrCode Is %d\n",GetLastError());
                system("pause");
                return -1;
        }
        printf("Create Device Success\n");
        g_hDevice = hDevice;

        //检查MessageBoxW的页属性
        printf("\n检查MessageBoxW地址(0x%.8X)的页属性\n",dwMsgwAddr);
        if (!VerfyPage(hDevice,dwMsgwAddr))
        {
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }

        //*****************************************ShellCode_Int****************************************************************
        if (!StoreIntGateInDll(hDevice,dwMsgwAddr,&dwIntGateAddr))
        {
                printf("\nStoreIntGateInDll失败,错误代码:%d\n",GetLastError());
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }
        printf("ShellCode_Int存放地址:0x%.8X\n",dwIntGateAddr);
       
        //*****************************************ShellCode_End****************************************************************
        if (!StoreShellEndInDll(hDevice,dwIntGateAddr + GATESIZE,&dwMyMsgwAddr))
        {
                printf("\nStoreShellEndInDll失败,错误代码:%d\n",GetLastError());
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }
        printf("ShellCode_End存放地址:0x%.8X\n",dwMyMsgwAddr);

        //*****************************************ShellCode_Begin***************************************************************
        if (!ReWriteFuncHeaderWithShellCodeBegin(hDevice,dwMsgwAddr,dwMyMsgwAddr))
        {
                printf("\nReWriteFuncHeaderWithShellCodeBegin失败,错误代码:%d\n",GetLastError());
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }

        //测试MessageBoxW
        printf("\n测试MessageBoxW,按任意键开始\n");
        getchar();

        MessageBoxW(NULL,L"Hello",L"Caption",MB_OKCANCEL);
       
        //收尾
        printf("\n恢复原ShellCode\n");
        system("pause");

        printf("\n检查注入ShellCode_Int函数起始地址(0x%.8X)的页属性\n",dwIntGateAddr);
        if (!VerfyPage(hDevice,dwIntGateAddr))
        {
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }
        printf("恢复注入ShellCode_Int处硬编码\n");
        memset((LPVOID)dwIntGateAddr,0,GATESIZE);

        printf("\n检查MessageBoxW函数起始地址(0x%.8X)的页属性\n",dwMsgwAddr);
        if (!VerfyPage(hDevice,dwMsgwAddr))
        {
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }
        printf("恢复MessageBoxW函数起始处硬编码\n");
        memcpy((LPVOID)dwMsgwAddr,OrgCode,sizeof(OrgCode));

        printf("\n检查注入ShellCode_End函数起始地址(0x%.8X)的页属性\n",dwMyMsgwAddr);
        if (!VerfyPage(hDevice,dwMyMsgwAddr))
        {
                CloseHandle(hDevice);
                system("pause");
                return -1;
        }
        printf("恢复注入ShellCode_End处硬编码\n");
        memset((LPVOID)dwMyMsgwAddr,0,SHELLCODESIZE);

        CloseHandle(hDevice);
        printf("\n设备句柄已关闭\n\n");
        system("pause");
        return 0;
}

//修改ShellCode中指定位置的值
VOID ChangeShellCode(PBYTE ShellCode, DWORD dwSize, PBYTE pbSource)
{
        printf("修改前的ShellCode:");
        for (DWORD i = 0; i < dwSize; i++)
        {
                printf("0x%.2x  ", ShellCode[i]);
                ShellCode[i] = pbSource[i];
        }

        printf("\n修改后的ShellCode:");
        for (i = 0; i < dwSize; i++)
        {
                printf("0x%.2x  ", ShellCode[i]);
        }
        printf("\n");
}

//修正函数地址
VOID FixFuncAddr(PDWORD pdwFuncAddr)
{
        printf("修正前,函数地址:0x%.8X\n", *pdwFuncAddr);
        if (*(PBYTE)(*pdwFuncAddr) == 0xe9)
        {
                *pdwFuncAddr = *pdwFuncAddr + 5 + *(PDWORD)(*pdwFuncAddr + 1);
        }
        printf("修正后,函数地址:0x%.8X\n", *pdwFuncAddr);
}

//检查并修正线性地址的页属性
BOOL VerfyPage(HANDLE hDevice, DWORD dwLinnerAddr)
{
        DWORD dwPDE = 0;
        DWORD dwPTE = 0;
        DWORD arrPage[2] = {0};
        DWORD dwReturnLength = 0;
       
        if (!DeviceIoControl(hDevice,CHANGEVALUE,&dwLinnerAddr,sizeof(dwLinnerAddr),arrPage,sizeof(arrPage),&dwReturnLength,NULL))
        {
                printf("DeviceIoControl CHANGEVALUE Failed, ErrCode Is %d\n",GetLastError());
                return FALSE;
        }

        dwPDE = arrPage[0];
        dwPTE = arrPage[1];
        printf("DeviceIoControl ALLOCATE Success!\nPDE:0x%.8X,PTE:0x%.8X\n",dwPDE,dwPTE);

        return TRUE;
}

//利用驱动在Dll空间存放ShellCode_End
BOOL StoreShellEndInDll(IN HANDLE hDevice, IN DWORD dwStartAddr, OUT PDWORD pdwStoreAddr)
{
        printf("\nStoreShellEndInDll\n");
        DWORD dwReturnLength = 0;

        DWORD arrIO[2] = {0};
        arrIO[0] = dwStartAddr;
        arrIO[1] = SHELLCODESIZE;

        //在DLL空间找到存放ShellCode_End的地址
        printf("\n在DLL空间找到存放ShellCode_End的地址\n");
        if (!DeviceIoControl(hDevice,LOOKUPMEMORY,arrIO,sizeof(arrIO),pdwStoreAddr,sizeof(DWORD),&dwReturnLength,NULL))
        {
                printf("DeviceIoControl LOOKUPMEMORY Failed, ErrCode Is %d\n",GetLastError());
                return FALSE;
        }
        DWORD dwMyMsgwAddr = *pdwStoreAddr;
        printf("DeviceIoControl LOOKUPMEMORY Success!\nShellCode_End存放的地址:0x%.8X,ReturnLength Is %d\n",dwMyMsgwAddr,dwReturnLength);
       
        //**************************MessageBoxW函数参数**************************
        //StoreParameterInDll(hDevice);
       
        //********************************跳回地址*******************************
        //修正跳回地址
        printf("\n修正跳回地址:0x%.8x\n",g_dwMsgAddr + 5);
        //跳转地址 = 当前地址 + 5 + E9参数
        //E9参数 = 跳转地址 - 当前地址 - 5
        DWORD dwBackAddr = g_dwMsgAddr + 5 - (DWORD)(dwMyMsgwAddr + 0xb) - 5;
        printf("E9参数:0x%.8X\n", dwBackAddr);
        ChangeShellCode((PBYTE)(ShellCode_End + 0xc), 4, (PBYTE)(&dwBackAddr));
       
        //在Dll空间写入ShellCode_End
        printf("\n检查存放ShellCode_End地址(0x%.8X)的页属性\n",dwMyMsgwAddr);
        if (!VerfyPage(hDevice,dwMyMsgwAddr))
        {
                return FALSE;
        }

        printf("\n在Dll空间写入ShellCode_End\n");
        __try
        {
                memcpy((LPVOID)dwMyMsgwAddr, (LPVOID)ShellCode_End, sizeof(ShellCode_End));
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
                printf("写入ShellCode_End失败,错误代码:%d\n",GetLastError());
                return FALSE;
        }
       
        printf("ShellCode_End Success\n");
        return TRUE;
}

//利用驱动在内核空间存放Parameter
BOOL StoreParameterInKernel(IN HANDLE hDevice)
{
        printf("\nStoreParameterInKernel\n");

        //在内核空间分配内存,用于存放传入MessageBoxW的4个参数
        printf("在内核空间分配内存,用于存放传入MessageBoxW的4个参数\n");
        DWORD dwReturnLength = 0;
        DWORD dwAllocateSize = PARAMSIZE;
        DWORD dwParamAddr = 0;
        DWORD arrParamAddr[4] = {0};
        if (!DeviceIoControl(hDevice,ALLOCATE,&dwAllocateSize,sizeof(dwAllocateSize),&dwParamAddr,sizeof(dwParamAddr),&dwReturnLength,NULL))
        {
                printf("DeviceIoControl ALLOCATE Failed, ErrCode Is %d\n",GetLastError());
                return FALSE;
        }
        printf("DeviceIoControl ALLOCATE Success!\nParameter's Store Address Is 0x%.8X,ReturnLength Is %d\n",dwParamAddr,dwReturnLength);
        g_dwParamAddr = dwParamAddr;
       
        //分4个部分存放
        printf("\n存放参数的地址分别为:\n");
        for (int i = 0; i < 4; i++)
        {
                arrParamAddr[i] = dwParamAddr + i * 4;
                printf("0x%.8X ",arrParamAddr[i]);
        }
        printf("\n");
       
        //检查存放参数处的页属性
        printf("\n检查存放参数地址(0x%.8X)的页属性\n",dwParamAddr);
        if (!VerfyPage(hDevice,dwParamAddr))
        {
                return FALSE;
        }

        //分4个部分修改ShellCode_End
        ChangeShellCode((PBYTE)(ShellCode_End + 0x07),4,(PBYTE)(&arrParamAddr[0]));
        ChangeShellCode((PBYTE)(ShellCode_End + 0x10),4,(PBYTE)(&arrParamAddr[1]));
        ChangeShellCode((PBYTE)(ShellCode_End + 0x19),4,(PBYTE)(&arrParamAddr[2]));
        ChangeShellCode((PBYTE)(ShellCode_End + 0x22),4,(PBYTE)(&arrParamAddr[3]));

        return TRUE;
}

//利用驱动将ShellCode_Begin覆盖函数头
BOOL ReWriteFuncHeaderWithShellCodeBegin(IN HANDLE hDevice, IN DWORD dwStartAddr, IN DWORD dwDestAddr)
{
        printf("\nReWriteFuncHeaderWithShellCodeBegin\n");

        //E9参数 = 目标地址 - 当前地址 - 5
        printf("\n修正ShellCode_Begin\n");
        DWORD dwJumpAddr = dwDestAddr - dwStartAddr - 5;
        printf("ShellCode_Begin:0x%.8X\n", (DWORD)ShellCode_Begin);
        printf("ShellCode_End:0x%.8X\n", (DWORD)ShellCode_End);
        printf("E9参数:0x%.8X\n", dwJumpAddr);
        //修正ShellCode_Begin
        ShellCode_Begin[0] = 0xe9;
        ChangeShellCode((PBYTE)(ShellCode_Begin + 1), 4, (PBYTE)(&dwJumpAddr));
       
        //在Dll空间写入ShellCode_Begin
        printf("\n检查存放ShellCode_Begin地址(0x%.8X)的页属性\n",dwStartAddr);
        if (!VerfyPage(hDevice,dwStartAddr))
        {
                return FALSE;
        }
        printf("\n在Dll空间写入ShellCode_Begin\n");

        __try
        {
                memcpy((LPVOID)dwStartAddr, (LPVOID)ShellCode_Begin, sizeof(ShellCode_Begin));
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
                printf("写入ShellCode_Begin失败,错误代码:%d\n",GetLastError());
                return FALSE;
        }
       
        printf("ShellCode_Begin Success\n");
        return TRUE;
}

//利用驱动在Dll空间存放IntGate函数
BOOL StoreIntGateInDll(IN HANDLE hDevice, IN DWORD dwStartAddr, OUT PDWORD pdwStoreAddr)
{
        printf("\nStoreIntGateInDll\n");
        DWORD dwReturnLength = 0;

        DWORD arrIO[2] = {0};
        arrIO[0] = dwStartAddr;
        arrIO[1] = GATESIZE;

        //在DLL空间找到存放ShellCode_Int的地址
        printf("\n在DLL空间找到存放ShellCode_Int的地址\n");
        if (!DeviceIoControl(hDevice,LOOKUPMEMORY,arrIO,sizeof(arrIO),pdwStoreAddr,sizeof(DWORD),&dwReturnLength,NULL))
        {
                printf("DeviceIoControl LOOKUPMEMORY Failed, ErrCode Is %d\n",GetLastError());
                return FALSE;
        }
        DWORD dwIntGateAddr = *pdwStoreAddr;
        printf("DeviceIoControl LOOKUPMEMORY Success!\nShellCode_Int存放的地址:0x%.8X,ReturnLength Is %d\n",dwIntGateAddr,dwReturnLength);

        //获取0环HOOK函数地址
        printf("\n获取0环HOOK函数的地址\n");
        DWORD dwHookFuncAddr = 0;
        if (!DeviceIoControl(hDevice,GETFUNCADDR,NULL,0,&dwHookFuncAddr,sizeof(dwHookFuncAddr),&dwReturnLength,NULL))
        {
                printf("DeviceIoControl GETFUNCADDR Failed, ErrCode Is %d\n",GetLastError());
                return FALSE;
        }
        printf("DeviceIoControl GETFUNCADDR Success!\nHOOK函数的地址:0x%.8X,ReturnLength Is %d\n",dwHookFuncAddr,dwReturnLength);
        printf("读取HOOK函数首地址的值:0x%X\n",*(PDWORD)dwHookFuncAddr);

        //*************************************构建中断门***************************************
        printf("\n构建中断门\n");
        ULONGLONG ullIntGateEntry = 0;
       
        if (!DeviceIoControl(hDevice,CHANGEIDTENTRY,&dwIntGateAddr,sizeof(dwIntGateAddr),&ullIntGateEntry,sizeof(ullIntGateEntry),&dwReturnLength,NULL))
        {
                printf("DeviceIoControl GETFUNCADDR Failed, ErrCode Is %d\n",GetLastError());
                return FALSE;
        }
        printf("DeviceIoControl GETFUNCADDR Success!\n添加的IDT项:0x%.16I64X,ReturnLength Is %d\n",ullIntGateEntry,dwReturnLength);


        //修正ShellCode_Int中赋给EAX的0环函数(HookMsg)的地址
        printf("mov eax,0x%.8X\n", dwHookFuncAddr);
        ChangeShellCode((PBYTE)(ShellCode_Int + 0x23), 4, (PBYTE)(&dwHookFuncAddr));
       
        //在Dll空间写入ShellCode_Int
        printf("\n检查存放ShellCode_Int地址(0x%.8X)的页属性\n",dwIntGateAddr);
        if (!VerfyPage(hDevice,dwIntGateAddr))
        {
                return FALSE;
        }

        printf("\n在Dll空间写入ShellCode_Int\n");
        __try
        {
                memcpy((LPVOID)dwIntGateAddr, (LPVOID)ShellCode_Int, sizeof(ShellCode_Int));
        }
        __except(EXCEPTION_EXECUTE_HANDLER)
        {
                printf("写入ShellCode_Int失败,错误代码:%d\n",GetLastError());
                return FALSE;
        }
       
        printf("ShellCode_Int Success\n");
        return TRUE;
}

0环部分************************************************************************************************************************
#include <ntifs.h>

//获取值
#define GETVALUE CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ANY_ACCESS)
//修正线性地址的页属性
#define CHANGEVALUE CTL_CODE(FILE_DEVICE_UNKNOWN,0x802,METHOD_BUFFERED,FILE_ANY_ACCESS)
//在内核空间分配内存
#define ALLOCATE CTL_CODE(FILE_DEVICE_UNKNOWN,0x803,METHOD_BUFFERED,FILE_ANY_ACCESS)
//查找内存区域
#define LOOKUPMEMORY CTL_CODE(FILE_DEVICE_UNKNOWN,0x804,METHOD_BUFFERED,FILE_ANY_ACCESS)
//将0环HOOK函数修改页属性后传给三环
#define GETFUNCADDR CTL_CODE(FILE_DEVICE_UNKNOWN,0x805,METHOD_BUFFERED,FILE_ANY_ACCESS)
//修改IDT表
#define CHANGEIDTENTRY CTL_CODE(FILE_DEVICE_UNKNOWN,0x806,METHOD_BUFFERED,FILE_ANY_ACCESS)

//将在多处引用,所以作为宏全局声明,避免多次输入
#define DEVICENAME L"\\Device\\MyDevice"
#define SYMBOLLINKNAME L"\\??\\SymbolLinkName"

//PDRIVER_OBJECT
PDRIVER_OBJECT g_pDriver = NULL;
//HOOK函数地址
ULONG g_ulHookFuncAddr = 0;
//IDT寄存器
typedef struct _IDT
{
        ULONG ulIdtR;
        USHORT usIdtL;       
}IDT;

//驱动停止函数
VOID DriverUnload(PDRIVER_OBJECT pDriver);
//派遣函数:Create
NTSTATUS DispatchCreateFunc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp);
//派遣函数:Close
NTSTATUS DispatchCloseFunc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp);
//派遣函数:DeviceControl
NTSTATUS DispatchDeviceControlFunc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp);
//检查并修改线性地址的页属性
BOOLEAN CheckPageAttribute(IN ULONG ulMemAddr,OUT PULONG plPDE,OUT PULONG plPTE);
//三环调用的HOOK函数
VOID __stdcall HookMsg(ULONG hWnd, ULONG lpText, ULONG lpCaption, ULONG uType);

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
        NTSTATUS status;
        ULONG ulRet = 0;
        PDEVICE_OBJECT pDeviceObj;
        UNICODE_STRING DeviceName;
        UNICODE_STRING SymbolLinkName;
        g_pDriver = pDriver;

        //设置设备名称
        RtlInitUnicodeString(&DeviceName,DEVICENAME);
        //设置符号链接名称
        RtlInitUnicodeString(&SymbolLinkName,SYMBOLLINKNAME);

        //创建设备对象
        status = IoCreateDevice(pDriver,0,&DeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&pDeviceObj);
        if (status != STATUS_SUCCESS)
        {
                DbgPrint("创建设备对象失败\r\n");
                //If a driver's call to IoCreateDevice returns an error, the driver should release any resources that it allocated for that device.
                IoDeleteDevice(pDeviceObj);
                return status;
        }

        //设置交互方式
        pDeviceObj->Flags |= DO_BUFFERED_IO;

        //创建符号链接
        status = IoCreateSymbolicLink(&SymbolLinkName,&DeviceName);
        if (status != STATUS_SUCCESS)
        {
                DbgPrint("创建符号链接失败\r\n");
                return STATUS_UNSUCCESSFUL;
        }

        //确定HOOK函数地址
        g_ulHookFuncAddr = (ULONG)HookMsg;
        DbgPrint("g_ulHookFuncAddr:0x%.8X\r\n",g_ulHookFuncAddr);

        //设置派遣函数
        pDriver->MajorFunction[IRP_MJ_CREATE] = DispatchCreateFunc;
        pDriver->MajorFunction[IRP_MJ_CLOSE] = DispatchCloseFunc;
        pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControlFunc;

        pDriver->DriverUnload = DriverUnload;

        return STATUS_SUCCESS;
}

//驱动停止函数
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
        //删除符号链接
        UNICODE_STRING SymbolLinkName;
        RtlInitUnicodeString(&SymbolLinkName,SYMBOLLINKNAME);
        IoDeleteSymbolicLink(&SymbolLinkName);

        //删除设备
        //This member is automatically updated when the driver calls IoCreateDevice successfully.
        //A driver can use this member and the NextDevice member of DEVICE_OBJECT to step through a list of all the device objects that the driver created.
        IoDeleteDevice(pDriver->DeviceObject);

        DbgPrint("驱动已停止\r\n");
}

//派遣函数:Create
NTSTATUS DispatchCreateFunc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp)
{
        NTSTATUS status = STATUS_SUCCESS;
        DbgPrint("Create Dispatch Function Success\r\n");       

        //将IRP中的状态置为成功
        pIrp->IoStatus.Status = status;
        //返还的字节数
        pIrp->IoStatus.Information = 0;//Information 的类型是 ULONG_PTR,即 unsinged long
        //结束IRP请求
        IoCompleteRequest(pIrp,IO_NO_INCREMENT);

        return status;
}

//派遣函数:Close
NTSTATUS DispatchCloseFunc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp)
{
        NTSTATUS status = STATUS_SUCCESS;
        DbgPrint("Close Dispatch Function Success\r\n");

        pIrp->IoStatus.Status = status;
        pIrp->IoStatus.Information = 0;
        IoCompleteRequest(pIrp,IO_NO_INCREMENT);

        return status;
}

//派遣函数:DeviceControl
NTSTATUS DispatchDeviceControlFunc(PDEVICE_OBJECT pDeviceObj, PIRP pIrp)
{
        NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
        PIO_STACK_LOCATION pIrpStack;
        ULONG ulRead = 0;
        ULONG ulWrite = 0;
        //从三环传入的ShellCode_End大小
        ULONG ulBufferSize = 0;
        //ZeroMemoryBuffer
        PUCHAR pcZeroBuffer = NULL;
        //存放ShellCode_End的地址
        PUCHAR pcShellBuffer = NULL;
        //页属性:PDE & PTE
        ULONG arrPage[2] = {0};
        //判断结果
        ULONG ulRet = 0;
        //IDT寄存器
        IDT stIdt = {0};
        //需要在IDT中添加的函数地址
        ULONGLONG ullIntGateEntry = 0;

        //从三环传入的控制码
        ULONG IoControlCode;
        //从三环传入的数据长度
        ULONG IoInLength;
        //向三环输出的数据长度
        ULONG IoOutLength;
        //向三环实际输出的数据长度
        ULONG RealOutLength;
        //与三环传输的缓冲区(输入、输出是同一个缓冲区)
        PVOID pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;       

        DbgPrint("DeviceControl Dispatch Function Success\r\n");

        //接收来自三环的数据(IRP)
        pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
        //接收控制码
        IoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
        //接收传入数据长度
        IoInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
        //输出数据长度
        IoOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
        //确定交互数据的缓冲区
        pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;

        //分析收到的控制码
        switch (IoControlCode)
        {
        case GETVALUE:
                {
                        DbgPrint("\r\nGETVALUE\r\n");
                        //DbgBreakPoint();
                        //读取缓冲区
                        RtlCopyMemory(&ulRead,pIoBuffer,sizeof(ulRead));
                        DbgPrint("需要查找的内存地址:0x%.8X\r\n",ulRead);

                        //写入缓冲区,发数据给三环
                        ulWrite = *(PULONG)ulRead;
                        DbgPrint("0x%.8X地址的值:0x%X\r\n",ulRead,ulWrite);
                        RtlCopyMemory(pIoBuffer,&ulWrite,sizeof(ulWrite));

                        //设置返还数据的长度
                        RealOutLength = sizeof(ulWrite);
                        pIrp->IoStatus.Information = RealOutLength;                       
                        DbgPrint("OutputLength Is %d\r\n",RealOutLength);

                        status = STATUS_SUCCESS;
                        break;
                }
        case CHANGEVALUE:
                {
                        DbgPrint("\r\nCHANGEVALUE\r\n");
                        //DbgBreakPoint();
                        //读取缓冲区
                        RtlCopyMemory(&ulRead,pIoBuffer,sizeof(ulRead));
                        DbgPrint("需要修改的内存地址:0x%.8X\r\n",ulRead);

                        //查看并修正线性地址的页属性
                        if (!CheckPageAttribute(ulRead,&arrPage[0],&arrPage[1]))
                        {
                                DbgPrint("线性地址无效\r\n");
                                //设置返还数据的长度
                                RealOutLength = 0;
                                pIrp->IoStatus.Information = RealOutLength;                       
                                DbgPrint("OutputLength Is %d\r\n",RealOutLength);

                                status = STATUS_UNSUCCESSFUL;
                                break;
                        }
                        DbgPrint("0x%.8X地址最终的页属性:\r\nPDE:0x%.8X,PTE:0x%.8X\r\n",ulRead,arrPage[0],arrPage[1]);

                        //写入缓冲区,发数据给三环
                        RtlCopyMemory(pIoBuffer,arrPage,sizeof(arrPage));

                        //设置返还数据的长度
                        RealOutLength = sizeof(arrPage);
                        pIrp->IoStatus.Information = RealOutLength;                       
                        DbgPrint("OutputLength Is %d\r\n",RealOutLength);

                        status = STATUS_SUCCESS;
                        break;
                }
        case ALLOCATE:
                {
                        DbgPrint("\r\nALLOCATE\r\n");
                        //DbgBreakPoint();
                        //读取缓冲区
                        RtlCopyMemory(&ulRead,pIoBuffer,sizeof(ulRead));
                        DbgPrint("从三环传入的待开辟内存大小:0x%xr\n",ulRead);

                        //在高2G开辟内存空间
                        pcZeroBuffer = (PUCHAR)ExAllocatePool(NonPagedPool,ulBufferSize);
                        if (pcZeroBuffer == NULL)
                        {
                                DbgPrint("ExAllocatePool失败\r\n");
                                status = STATUS_UNSUCCESSFUL;
                                break;
                        }
                        ulWrite = (ULONG)pcZeroBuffer;
                        DbgPrint("ExAllocatePool成功,地址为:0x%.8X\r\n",ulWrite);
                        RtlFillMemory(pcZeroBuffer,ulRead,0);

                        //查看并修正线性地址的属性
                        if (!CheckPageAttribute(ulWrite,&arrPage[0],&arrPage[1]))
                        {
                                DbgPrint("线性地址无效\r\n");
                                //设置返还数据的长度
                                RealOutLength = 0;
                                pIrp->IoStatus.Information = RealOutLength;                       
                                DbgPrint("OutputLength Is %d\r\n",RealOutLength);

                                status = STATUS_UNSUCCESSFUL;
                                break;
                        }
                        DbgPrint("0x%.8X地址最终的页属性:\r\nPDE:0x%.8X,PTE:0x%.8X\r\n",ulWrite,arrPage[0],arrPage[1]);

                        //将内存地址写入缓冲区,发数据给三环
                        RtlCopyMemory(pIoBuffer,&ulWrite,sizeof(ulWrite));

                        //设置返还数据的长度
                        RealOutLength = sizeof(ulWrite);
                        pIrp->IoStatus.Information = RealOutLength;                       
                        DbgPrint("OutputLength Is %d\r\n",RealOutLength);

                        status = STATUS_SUCCESS;
                        break;
                }
        case LOOKUPMEMORY:
                {
                        DbgPrint("\r\nLOOKUPMEMORY\r\n");
                        //DbgBreakPoint();
                        //读取缓冲区
                        RtlCopyMemory(&ulRead,pIoBuffer,sizeof(ulRead));
                        DbgPrint("从三环传入的遍历内存起始地址:0x%.8X\r\n",ulRead);
                        //从三环传入的ShellCode_End大小
                        RtlCopyMemory(&ulBufferSize,(PVOID)((ULONG)pIoBuffer + 4),sizeof(ulBufferSize));
                        DbgPrint("从三环传入的待开辟内存大小:0x%x\r\n",ulBufferSize);

                        //创建ZeroBuffer用于比较
                        pcZeroBuffer = (PUCHAR)ExAllocatePool(NonPagedPool,ulBufferSize);
                        if (pcZeroBuffer == NULL)
                        {
                                DbgPrint("ExAllocatePool失败\r\n");
                                status = STATUS_UNSUCCESSFUL;
                                break;
                        }
                        RtlFillMemory(pcZeroBuffer,ulBufferSize,0);

                        //遍历查找符合条件的内存区域
                        pcShellBuffer = (PUCHAR)ulRead;
                        while (TRUE)
                        {
                                ulRet = RtlCompareMemory(pcShellBuffer,pcZeroBuffer,ulBufferSize);

                                if (ulRet == ulBufferSize)
                                {
                                        DbgPrint("已开辟0x%x大小的内存区域,地址:0x%.8X\r\n",ulBufferSize,(ULONG)pcShellBuffer);
                                        break;
                                }

                                pcShellBuffer += 4;
                        }

                        //写入缓冲区,发数据给三环
                        ulWrite = (ULONG)pcShellBuffer;
                        DbgPrint("可写入ShellCode的地址:0x%.8X\r\n",ulWrite);
                        RtlCopyMemory(pIoBuffer,&ulWrite,sizeof(ulWrite));

                        //设置返还数据的长度
                        RealOutLength = sizeof(ulWrite);
                        pIrp->IoStatus.Information = RealOutLength;                       
                        DbgPrint("OutputLength Is %d\r\n",RealOutLength);

                        status = STATUS_SUCCESS;
                        break;
                }
        case GETFUNCADDR:
                {
                        DbgPrint("\r\nGETFUNCADDR\r\n");

                        //获取HOOK函数的地址
                        ulWrite = (ULONG)HookMsg;
                        DbgPrint("HookMsg函数的地址:0x%.8X\r\n",ulWrite);

                        //将函数的页属性设置为用户级:US = 1
                        if (!CheckPageAttribute(ulWrite,&arrPage[0],&arrPage[1]))
                        {
                                DbgPrint("线性地址无效\r\n");
                                //设置返还数据的长度
                                RealOutLength = 0;
                                pIrp->IoStatus.Information = RealOutLength;                       
                                DbgPrint("OutputLength Is %d\r\n",RealOutLength);

                                status = STATUS_UNSUCCESSFUL;
                                break;
                        }
                        DbgPrint("0x%.8X地址最终的页属性:\r\nPDE:0x%.8X,PTE:0x%.8X\r\n",ulWrite,arrPage[0],arrPage[1]);

                        //将函数地址传给三环
                        RtlCopyMemory(pIoBuffer,&ulWrite,sizeof(ulWrite));

                        //设置返还数据的长度
                        RealOutLength = sizeof(ulWrite);
                        pIrp->IoStatus.Information = RealOutLength;                       
                        DbgPrint("OutputLength Is %d\r\n",RealOutLength);

                        status = STATUS_SUCCESS;
                        break;
                }
        case CHANGEIDTENTRY:
                {
                        DbgPrint("\r\nCHANGEIDTENTRY\r\n");

                        //读取缓冲区
                        RtlCopyMemory(&ulRead,pIoBuffer,sizeof(ulRead));
                        DbgPrint("需要提权的函数地址:0x%.8X\r\n",ulRead);

                        //将函数地址转换为IDT项
                        ullIntGateEntry = (((ULONGLONG)ulRead >> 16) << 48) + 0xee0000080000 + (ulRead & 0xffff);
                        DbgPrint("即将添加的IDT项:%.16X\r\n",ullIntGateEntry);

                        //获取IDT地址
                        __asm sidt stIdt;
                        DbgPrint("IDT基址:0x%.8X,IDT长度:0x%x\n",stIdt.ulIdtR,stIdt.usIdtL);

                        //修改指定IDT项
                        RtlCopyMemory((PVOID)0x8003f500,&ullIntGateEntry,8);
                        DbgPrint("已修改IDT项(8003f500): %.16I64X\r\n",*(PULONGLONG)0x8003f500);

                        //写入缓冲区,发数据给三环
                        RtlCopyMemory(pIoBuffer,&ullIntGateEntry,sizeof(ullIntGateEntry));

                        //设置返还数据的长度
                        RealOutLength = sizeof(ullIntGateEntry);
                        pIrp->IoStatus.Information = RealOutLength;                       
                        DbgPrint("OutputLength Is %d\r\n",RealOutLength);

                        status = STATUS_SUCCESS;
                        break;
                }
        default:
                DbgPrint("Switch Exception\r\n");
                break;
        }


        pIrp->IoStatus.Status = status;
        IoCompleteRequest(pIrp,IO_NO_INCREMENT);

        return STATUS_SUCCESS;
}

//检查并修改线性地址的页属性
BOOLEAN CheckPageAttribute(IN ULONG ulMemAddr,OUT PULONG plPDE,OUT PULONG plPTE)
{
        ULONG ulPDE = 0;
        ULONG ulPTE = 0;
        ULONG ulPdeAddr = 0xc0600000 + ((ulMemAddr >> 0x12) & 0x003ff8);
        ULONG ulPteAddr = 0xc0000000 + ((ulMemAddr >> 0x09) & 0x7ffff8);

        DbgPrint("\r\n检查线性地址(0x%.8X)的页属性\r\n",ulMemAddr);

        //查看PDE属性
        ulPDE = *(PULONG)ulPdeAddr;
        DbgPrint("PDE:0x%.8X\r\n",ulPDE);
        //P位
        if ((ulPDE & 0x1) != 0x1)
        {
                DbgPrint("PDE的P位为0,地址无效\r\n");
                return FALSE;
        }
        else
        {
                //RW、US位
                if ((ulPDE & 0x7) != 0x7)
                {
                        ulPDE = (ulPDE & 0xfffffff8) + 0x7;
                        *(PULONG)ulPdeAddr = ulPDE;
                        DbgPrint("已修改PDE的RW、US位,PDE:0x%.8X\r\n",ulPDE);
                }

                //PS位
                if (((ulPDE & 0x80) >> 0x7) == 0x1)
                {
                        DbgPrint("PDE的PS位为1,大页,检查终止\r\n");
                        *plPDE = ulPDE;
                        *plPTE = -1;
                        return TRUE;
                }
                else
                {
                        //小页,检查PTE
                        ulPTE = *(PULONG)ulPteAddr;
                        //P位
                        if ((ulPTE & 0x1) != 0x1)
                        {
                                DbgPrint("PTE的P位为0,地址无效\r\n");
                                return FALSE;
                        }
                        else
                        {
                                //RW、US位
                                if ((ulPTE & 0x7) != 0x7)
                                {
                                        ulPTE = (ulPTE & 0xfffffff8) + 0x7;
                                        *(PULONG)ulPteAddr = ulPTE;
                                        DbgPrint("已修改PTE的RW、US位,PTE:0x%.8X\r\n",ulPTE);
                                }
                                else
                                {
                                        DbgPrint("无需修改\r\n");
                                }
                                *plPDE = ulPDE;
                                *plPTE = ulPTE;
                                return TRUE;
                        }
                }
        }
}

//三环调用的HOOK函数
VOID __stdcall HookMsg(ULONG hWnd, ULONG lpText, ULONG lpCaption, ULONG uType)
{
        __asm pushfd

        DbgPrint("3环调用0环函数成功!!!\r\n");
        DbgPrint("MessageBoxW(hWnd:0x%x, lpText:0x%x, lpCaption:0x%x, uType:0x%x)\n", hWnd, lpText, lpCaption, uType);

        __asm popfd

        return;
}



唯一的遗憾是还是没弄懂一楼的问题,看看学到后面能否明白吧




欢迎光临 滴水逆向联盟 (http://www.dtdebug.com/) Powered by Discuz! X3.2