ring0 恢复SSDTHook

原理:

用ZwQuerySystemInformation 功能号为11(SystemModuleInformation)  得到所有系统模块的地址 遍历搜索得到ntos模块的基地址

读Ntos模块到System进程空间中

在ntos中找到函数真正地址

将地址转换为ssdt的索引

//X64版本#include "ResumeSSDTHook.h"

#define  SEC_IMAGE 0x1000000

PVOID   __NtosModuleBaseAddress = NULL;
ULONG64 __NtosModuleLength = 0;
PVOID   __SSDTAddress = 0;
ULONG32 __NtOpenProcessIndex = 0;

NTSTATUS
    DriverEntry(PDRIVER_OBJECT  DriverObject,PUNICODE_STRING  RegisterPath)
{
    PDEVICE_OBJECT  DeviceObject;
    NTSTATUS        Status;
    int             i = 0;
    char  FunctionName[] = "NtOpenProcess";
    char  ModuleName[] = "ntoskrnl.exe";

    UNICODE_STRING  DeviceName;
    UNICODE_STRING  LinkName;

    RtlInitUnicodeString(&DeviceName,DEVICE_NAME);
    RtlInitUnicodeString(&LinkName,LINK_NAME);

    //创建设备对象;

    Status = IoCreateDevice(DriverObject,0,
    &DeviceName,FILE_DEVICE_UNKNOWN,0,FALSE,&DeviceObject);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    Status = IoCreateSymbolicLink(&LinkName,&DeviceName);

    for (i = 0; i<IRP_MJ_MAXIMUM_FUNCTION; i++)
    {
        DriverObject->MajorFunction[i] = DefaultPassThrough;
    }

    DriverObject->DriverUnload = UnloadDriver;
    //得Ntos
    if (GetSystemMoudleInfoBySystemModuleName(ModuleName,
        &__NtosModuleBaseAddress, &__NtosModuleLength) == FALSE)
    {
        return Status;
    }

    DbgPrint("Win7 Ntos模块地址:%p\r\n", __NtosModuleBaseAddress);
    DbgPrint("Win7 Ntos模块大小:%x\r\n", __NtosModuleLength);
    //得ssdt
    if (GetSSDTAddress(&__SSDTAddress) == FALSE)
    {
        return Status;
    }
    DbgPrint("Win7 SSDT地址:%p\r\n", __SSDTAddress);
    //得需要hook的函数的索引
    if (GetSSDTFunctionIndexFromNtdllExportTableByFunctionName(FunctionName,
        &__NtOpenProcessIndex) == FALSE)
    {
        return STATUS_UNSUCCESSFUL;
    }
    DbgPrint("Win7 __NtOpenProcessIndex地址:%d\r\n", __NtOpenProcessIndex);

    //
    if (ResumeSSDT(__SSDTAddress, __NtosModuleBaseAddress, __NtOpenProcessIndex, 4) == TRUE)
    {
        DbgPrint("恢复成功\r\n");
    }

#ifdef WIN64
    DbgPrint("WIN64: ResumeSSDTHook IS RUNNING!!!");
#else
    DbgPrint("WIN32: ResumeSSDTHook SIS RUNNING!!!");

#endif

    return STATUS_SUCCESS;
}

NTSTATUS
    DefaultPassThrough(PDEVICE_OBJECT  DeviceObject,PIRP Irp)
{
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp,IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}

VOID
    UnloadDriver(PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING  LinkName;
    PDEVICE_OBJECT    NextDeviceObject    = NULL;
    PDEVICE_OBJECT  CurrentDeviceObject = NULL;
    RtlInitUnicodeString(&LinkName,LINK_NAME);

    IoDeleteSymbolicLink(&LinkName);
    CurrentDeviceObject = DriverObject->DeviceObject;
    while (CurrentDeviceObject != NULL)
    {

        NextDeviceObject = CurrentDeviceObject->NextDevice;
        IoDeleteDevice(CurrentDeviceObject);
        CurrentDeviceObject = NextDeviceObject;
    }

    DbgPrint("ResumeSSDTHook IS STOPPED!!!");
}

BOOLEAN GetSystemMoudleInfoBySystemModuleName(char* ModuleName,
    PVOID* ModuleBase, ULONG64* ModuleLength)
{
    int       i = 0;
    NTSTATUS  Status = STATUS_SUCCESS;
    PVOID     BufferData = NULL;
    ULONG     ReturnLength = 0;
    //功能号为11,先获取所需的缓冲区大小 得大小
    Status = ZwQuerySystemInformation(SystemModuleInformation, NULL, 0, &ReturnLength);  //SSDT
    if (Status != STATUS_INFO_LENGTH_MISMATCH)              //没有内存
    {
        return FALSE;
    }

    //申请内存
    BufferData = ExAllocatePool(PagedPool, ReturnLength);   //PagedPool(数据段 置换到磁盘)  NonPagedPool(代码段 不置换到磁盘)

    if (BufferData == NULL)
    {
        return FALSE;
    }

    //再次调用 得数据
    Status = ZwQuerySystemInformation(SystemModuleInformation, BufferData, ReturnLength, &ReturnLength);
    if (!NT_SUCCESS(Status))
    {
        ExFreePool(BufferData);
        return FALSE;
    }

    for (i = 0; i < ((PSYSTEM_MODULES_INFO)BufferData)->NumberOfModules; i++)
    {
        if (strstr(((PSYSTEM_MODULES_INFO)BufferData)->Modules[i].ModuleFullPathData,
            ModuleName) != NULL)  //Ntoskernel.exe
        {
            *ModuleBase = ((PSYSTEM_MODULES_INFO)BufferData)->Modules[i].ModuleBase;
            *ModuleLength = ((PSYSTEM_MODULES_INFO)BufferData)->Modules[i].ModuleLength;

            if (BufferData != NULL)
            {
                ExFreePool(BufferData);
                BufferData = NULL;
            }
            return TRUE;
        }
    }
    if (BufferData != NULL)
    {
        ExFreePool(BufferData);
        BufferData = NULL;
    }

    return FALSE;
}

BOOLEAN ResumeSSDT(ULONG64 SSDTAddress, ULONG64 ModuleBase, ULONG32 SSDTFunctionIndex, ULONG32 ParameterCount)
{
    int i = 0;
    PUINT8 RVAOfSSDT = 0;
    WCHAR  FileFullPathData[] = L"\\SystemRoot\\System32\\ntoskrnl.exe";
    PIMAGE_DOS_HEADER DosHeader = NULL;
    PIMAGE_NT_HEADERS NtHeader = NULL;
    PIMAGE_OPTIONAL_HEADER OptionalHeader = NULL;
    PIMAGE_SECTION_HEADER  SectionHeader = NULL;
    PVOID  PresupporseImageBase = 0; //优先加载地址
    PVOID  BaseOfSSDTInFile = 0;  //文件基地址
    PVOID   v1 = 0;    //函数真正地址
    ULONG32 v2 = 0;   //SSDT[Offset]
    char    v3;
    CHAR    Bits[4] = { 0 };

    PVOID  BufferData = NULL;
    //获得SSDT与ntos模块基地址RVA
    RVAOfSSDT = ((PUINT8)(((PSERVER_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->Unknow0)) - (PUINT8)ModuleBase;

    //读Ntos模块到System进程空间中 (FileAlign)
    if (ReadingFileInRing0Space(FileFullPathData, &BufferData) == FALSE)
    {
        return FALSE;
    }

    DosHeader = (PIMAGE_DOS_HEADER)BufferData;
    NtHeader = (PIMAGE_NT_HEADERS)(DosHeader->e_lfanew + (PUINT8)BufferData);
    OptionalHeader = &(NtHeader->OptionalHeader);
    PresupporseImageBase = OptionalHeader->ImageBase;   //优先加载的地址

    SectionHeader = (PIMAGE_SECTION_HEADER)((PUINT8)NtHeader + sizeof(IMAGE_NT_HEADERS));

    for (i = 0; i<NtHeader->FileHeader.NumberOfSections; i++)
    {
        if (RVAOfSSDT >= SectionHeader[i].VirtualAddress && RVAOfSSDT <
            (SectionHeader[i].VirtualAddress + SectionHeader[i].SizeOfRawData))
        {
            //SSDT的文件偏移
            BaseOfSSDTInFile = (PVOID)((PUINT8)BufferData + (RVAOfSSDT - (PUINT8)(SectionHeader[i].VirtualAddress)) + SectionHeader[i].PointerToRawData);
            break;
        }
    }

    //NtOpenProcess    文件中ssdt索引对应的函数地址 - 模块加载基地址 +  ntos模块的基地址
    v1 = (PUINT8)(((PULONG64)BaseOfSSDTInFile)[SSDTFunctionIndex]) - (PUINT8)PresupporseImageBase + (PUINT8)ModuleBase;
    //偏移
    v1 = (PUINT8)v1 - (PUINT8)(((PSERVER_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->Unknow0);
    v1 = (ULONG32)v1 << 4;

    //处理参数个数
    if (ParameterCount>4)
    {
        ParameterCount = ParameterCount - 4;
    }
    else
    {
        ParameterCount = 0;
    }

    //处理低四位,填写参数个数   如果一个函数的参数为5 那么dwTemp的低4位就是 0001  如果参数是6 就是0002 因为 6要减4
#define SETBIT(x,y) x|=(1<<y)         //将X的第Y位置1
#define CLRBIT(x,y) x&=~(1<<y)        //将X的第Y位清0
#define GETBIT(x,y) (x & (1 << y))    //取X的第Y位,返回0或非0

    memcpy(&v3, &v1, 1);
    for (i = 0; i<4; i++)    //一个16进制 4个二进制      0000
    {
        Bits[i] = GETBIT(ParameterCount, i);
        if (Bits[i])
        {
            SETBIT(v3, i);
        }
        else
        {
            CLRBIT(v3, i);
        }
    }
    memcpy(&v1, &v3, 1);   //获得真实的数据了

     //获得当前的数据
    v2 = ((PULONG32)(((PSERVER_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->Unknow0))[SSDTFunctionIndex];
    if (v1 != v2)
    {
        WPOFF();
        ((PULONG32)(((PSERVER_SERVICE_DESCRIPTOR_TABLE)SSDTAddress)->Unknow0))[SSDTFunctionIndex] = (ULONG32)v1;
        WPON();
    }

    if (BufferData != NULL)
    {
        ExFreePool(BufferData);
        BufferData = NULL;
    }
    return TRUE;
}

VOID WPOFF()
{
    _disable();
    __writecr0(__readcr0() & (~(0x10000)));

}
VOID WPON()
{
    __writecr0(__readcr0() ^ 0x10000);
    _enable();
}

BOOLEAN GetSSDTAddress(ULONG64* SSDTAddress)
{
    //kd>  rdmsr c0000082
    PUCHAR StartSearchAddress = (PUCHAR)__readmsr(0xC0000082);
    PUCHAR EndSearchAddress = StartSearchAddress + PAGE_SIZE;
    PUCHAR i = NULL;
    UCHAR   v1 = 0, v2 = 0, v3 = 0;
    INT64   Offset = 0;    //002320c7
    ULONG64 VariableAddress = 0;
    *SSDTAddress = NULL;
    for (i = StartSearchAddress; i < EndSearchAddress; i++)
    {
        if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2))
        {
            v1 = *i;
            v2 = *(i + 1);
            v3 = *(i + 2);
            if (v1 == 0x4c && v2 == 0x8d && v3 == 0x15)
            {
                memcpy(&Offset, i + 3, 4);
                *SSDTAddress = Offset + (ULONG64)i + 7;
                break;
            }
        }
    }
    //如果是Win32 导出表 搜索  KeServiceDescriptorTable
    if (*SSDTAddress == NULL)
    {
        return FALSE;
    }

    return TRUE;
}
BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionName(CHAR* FunctionName, ULONG32* SSDTFunctionIndex)
{
    ULONG    i;
    BOOLEAN  IsOk = FALSE;
    WCHAR     FileFullPath[] = L"\\SystemRoot\\System32\\ntdll.dll";     //C:\Windows\
    SIZE_T   MappingViewSize = 0;
    PVOID    MappingBaseAddress = NULL;
    PIMAGE_EXPORT_DIRECTORY ImageExportDirectory = NULL;
    PIMAGE_NT_HEADERS  NtHeader = NULL;
    UINT32*  AddressOfFunctions = NULL;
    UINT32*  AddressOfNames = NULL;
    UINT16*  AddressOfNameOrdinals = NULL;
    CHAR*    v1 = NULL;
    ULONG32  FunctionOrdinal = 0;
    PVOID    FunctionAddress = 0;
    ULONG32  Offset_SSDTFunctionIndex = 4;
    //将Ntdll.dll映射 当前的空间中

    *SSDTFunctionIndex = -1;
    IsOk = MappingPEFileInRing0Space(FileFullPath, &MappingBaseAddress, &MappingViewSize);
    if (IsOk == FALSE)
    {
        return FALSE;
    }
    else
    {
        __try {
            NtHeader = RtlImageNtHeader(MappingBaseAddress);   //extern
            if (NtHeader && NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
            {
                ImageExportDirectory = (IMAGE_EXPORT_DIRECTORY*)((UINT8*)MappingBaseAddress +
                    NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

                AddressOfFunctions = (UINT32*)((UINT8*)MappingBaseAddress + ImageExportDirectory->AddressOfFunctions);
                AddressOfNames = (UINT32*)((UINT8*)MappingBaseAddress + ImageExportDirectory->AddressOfNames);
                AddressOfNameOrdinals = (UINT16*)((UINT8*)MappingBaseAddress + ImageExportDirectory->AddressOfNameOrdinals);
                for (i = 0; i < ImageExportDirectory->NumberOfNames; i++)
                {
                    v1 = (char*)((ULONG64)MappingBaseAddress + AddressOfNames[i]);   //获得函数名称
                    if (_stricmp(FunctionName, v1) == 0)
                    {
                        FunctionOrdinal = AddressOfNameOrdinals[i];
                        FunctionAddress = (PVOID)((UINT8*)MappingBaseAddress + AddressOfFunctions[FunctionOrdinal]);

                        *SSDTFunctionIndex = *(ULONG32*)((UINT8*)FunctionAddress + Offset_SSDTFunctionIndex);
                        break;
                    }
                }
            }
        }
        __except (EXCEPTION_EXECUTE_HANDLER)
        {
            ;
        }
    }

    ZwUnmapViewOfSection(NtCurrentProcess(), MappingBaseAddress);  //解除映射

    if (*SSDTFunctionIndex == -1)
    {
        return FALSE;
    }

    return TRUE;
}
BOOLEAN MappingPEFileInRing0Space(WCHAR* FileFullPath, PVOID* MappingBaseAddress, PSIZE_T MappingViewSize)
{

    NTSTATUS          Status;
    UNICODE_STRING    v1;
    OBJECT_ATTRIBUTES ObjectAttributes;
    IO_STATUS_BLOCK   IoStatusBlock;
    HANDLE   FileHandle = NULL;
    HANDLE   SectionHandle = NULL;

    if (!FileFullPath &&MmIsAddressValid(FileFullPath))
    {
        return FALSE;
    }

    if (!MappingBaseAddress&&MmIsAddressValid(MappingBaseAddress))
    {
        return FALSE;
    }

    RtlInitUnicodeString(&v1, FileFullPath);
    InitializeObjectAttributes(&ObjectAttributes,
        &v1,
        OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
        NULL,
        NULL
    );

    //获得文件句柄
    Status = IoCreateFile(&FileHandle,
        GENERIC_READ | SYNCHRONIZE,
        &ObjectAttributes,   //文件绝对路径
        &IoStatusBlock,
        NULL,
        FILE_ATTRIBUTE_NORMAL,
        FILE_SHARE_READ,
        FILE_OPEN,
        FILE_SYNCHRONOUS_IO_NONALERT,
        NULL,
        0,
        CreateFileTypeNone,
        NULL,
        IO_NO_PARAMETER_CHECKING
    );
    if (!NT_SUCCESS(Status))
    {
        return FALSE;
    }

    ObjectAttributes.ObjectName = NULL;
    Status = ZwCreateSection(&SectionHandle,
        SECTION_QUERY | SECTION_MAP_READ,
        &ObjectAttributes,
        NULL,
        PAGE_WRITECOPY,
        SEC_IMAGE, //内存对齐  0x1000
        FileHandle
    );
    ZwClose(FileHandle);
    if (!NT_SUCCESS(Status))
    {
        return FALSE;
    }
    Status = ZwMapViewOfSection(SectionHandle,
        NtCurrentProcess(),    //映射到当前进程的内存空间中
        MappingBaseAddress,
        0,
        0,
        0,
        MappingViewSize,
        ViewUnmap,
        0,
        PAGE_WRITECOPY
    );
    ZwClose(SectionHandle);
    if (!NT_SUCCESS(Status))
    {
        return FALSE;
    }
    return TRUE;
}
BOOLEAN ReadingFileInRing0Space(WCHAR* FileFullPathData, PVOID* BufferData)
{

    NTSTATUS          Status;
    LARGE_INTEGER     ReturnLength = { 0,0 };
    UNICODE_STRING    v1;
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE            FileHandle;
    IO_STATUS_BLOCK   IoStatusBlock;
    FILE_STANDARD_INFORMATION v2 = { 0 };
    if (FileFullPathData == NULL&&*BufferData != NULL)
    {
        return FALSE;
    }

    RtlInitUnicodeString(&v1, FileFullPathData);
    InitializeObjectAttributes(&ObjectAttributes, &v1, OBJ_CASE_INSENSITIVE, NULL, NULL);

    //获取文件句柄
    Status = ZwCreateFile(&FileHandle,
        SYNCHRONIZE,
        &ObjectAttributes,
        &IoStatusBlock,
        NULL,
        FILE_ATTRIBUTE_NORMAL,
        FILE_SHARE_READ,
        FILE_OPEN,
        FILE_SYNCHRONOUS_IO_NONALERT,
        NULL,
        0);
    if (!NT_SUCCESS(Status))
    {
        return FALSE;
    }

    //计算文件长度

    Status = ZwQueryInformationFile(FileHandle,
        &IoStatusBlock,
        &v2,
        sizeof(FILE_STANDARD_INFORMATION),
        FileStandardInformation);
    if (!NT_SUCCESS(Status))
    {
        ZwClose(FileHandle);
        return FALSE;
    }

    //动态申请内存
    *BufferData = ExAllocatePool(PagedPool, v2.EndOfFile.LowPart);
    if (*BufferData == NULL)
    {
        ZwClose(FileHandle);
        return FALSE;
    }

    //读取文件到内存

    Status = ZwReadFile(FileHandle,
        NULL,
        NULL,
        NULL,
        &IoStatusBlock,
        *BufferData,
        v2.EndOfFile.LowPart,
        &ReturnLength,
        NULL);

    if (!NT_SUCCESS(Status))
    {
        ExFreePool(*BufferData);
        ZwClose(FileHandle);
        return FALSE;
    }
    ZwClose(FileHandle);

    return TRUE;
}
#include <ntifs.h>
#include <ntimage.h>
#ifndef CXX_ResumeSSDTHook_H
#define CXX_ResumeSSDTHook_H

#define DEVICE_NAME  L"\\Device\\ResumeSSDTHookDevice"
#define LINK_NAME    L"\\??\\ResumeSSDTHookLink"
#define  SystemModuleInformation 0xB

typedef struct SYSTEM_MODULE_INFO
{
    UINT32 Unknow0[4];
    UINT64 ModuleBase;
    UINT32 ModuleLength;
    UINT32 Flags;
    UINT64 Unknow1;
    char   ModuleFullPathData[256];
} SYSTEM_MODULE_INFO, *PSYSTEM_MODULE_INFO;

typedef struct _SYSTEM_MODULES_INFO
{
    UINT32 NumberOfModules;
    SYSTEM_MODULE_INFO Modules[1];
}SYSTEM_MODULES_INFO, *PSYSTEM_MODULES_INFO;

typedef struct _SERVER_SERVICE_DESCRIPTOR_TABLE_
{
    PVOID Unknow0;
    PVOID Unknow1;
    PVOID Unknow2;
    PVOID Unknow3;
}SERVER_SERVICE_DESCRIPTOR_TABLE, *PSERVER_SERVICE_DESCRIPTOR_TABLE;

extern
PIMAGE_NT_HEADERS
NTAPI
RtlImageNtHeader(PVOID BaseAddress);

extern
NTSTATUS
ZwQuerySystemInformation(
    IN ULONG SystemInformationClass,
    IN PVOID SystemInformation,
    IN ULONG SystemInformationLength,
    OUT PULONG ReturnLength);

VOID
    UnloadDriver(PDRIVER_OBJECT DriverObject);

BOOLEAN GetSystemMoudleInfoBySystemModuleName(char * ModuleName, PVOID * ModuleBase, ULONG64 * ModuleLength);

BOOLEAN ResumeSSDT(ULONG64 SSDTAddress, ULONG64 ModuleBase, ULONG32 SSDTFunctionIndex, ULONG32 ParameterCount);

VOID WPOFF();

VOID WPON();

BOOLEAN GetSSDTAddress(ULONG64 * SSDTAddress);

BOOLEAN GetSSDTFunctionIndexFromNtdllExportTableByFunctionName(CHAR * FunctionName, ULONG32 * SSDTFunctionIndex);

BOOLEAN MappingPEFileInRing0Space(WCHAR * FileFullPath, PVOID * MappingBaseAddress, PSIZE_T MappingViewSize);

BOOLEAN ReadingFileInRing0Space(WCHAR * FileFullPathData, PVOID * BufferData);

NTSTATUS
    DefaultPassThrough(PDEVICE_OBJECT  DeviceObject,PIRP Irp);

#endif
时间: 2024-10-28 16:27:17

ring0 恢复SSDTHook的相关文章

ring0 SSDTHook

SSDT 的全称是 System Services Descriptor Table,系统服务描述符表.这个表就是一个把 Ring3 的 Win32 API 和 Ring0 的内核 API 联系起来.SSDT 并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址.服务函数个数等.通过修改此表的函数地址可以对常用 Windows 函数及 API 进行 Hook,从而实现对一些关心的系统动作进行过滤.监控的目的.一些 HIPS.防毒软件.系统监控.注册表监控软件往往

ring0 SSDTHook 实现x64/x86

#include "HookSSDT.h" #include <ntimage.h> #define SEC_IMAGE 0x001000000 ULONG32 __NtOpenProcessIndex = 0; PVOID __ServiceTableBase = NULL; ULONG32 __OldNtOpenProcessOffset = 0; PVOID __OldNtOpenProcess = NULL; UCHAR __OldCode[15] = {0}; B

SSDTHook实例--编写稳定的Hook过滤函数

解说怎样写Hook过滤函数,比方NewZwOpenProcess.打开进程. 非常多游戏保护都会对这个函数进行Hook. 因为我们没有游戏保护的代码,无法得知游戏公司是怎样编写这个过滤函数. 我看到非常多奇形怪状的Hook过滤函数的写法.看得蛋痛无比. 比方: http://bbs.pediy.com/showthread.php?t=126802 http://bbs.pediy.com/showthread.php? t=126077 第一个bug: 调用这个函数 status = PsLo

ring0 与 ring3 层之间的交互

在进行Windows的ring0层开发时,必不可免的要与 ring3 层进行交互.进行数据间的相互传输.可用的方法有DeviceIoCntrol,ReadFile.我平常都是用的DeviceIoControl在ring3 与 ring0 层进行的数据传输.今天就写写DeviceIoControl 和 ring0通过事件通知 ring3! 首先加载驱动之后,在ring3层调用CreateFile() 打开ring0层生成的LinkName,获得设备对象的句柄.然后调用DeviceIoControl

win下SSDT-Hook

#include <ntifs.h> #pragma pack(1) //SSDTHook中,我们有2个关键问题: //1 怎么找到SSDT,这个表是导出的,所以直接声明就可以 //2 SSDT是只读的,怎么改 // 2.1 通过修改CR0 去掉内核层的页保护 // 2.2 可以通过MDL重映射的方式,去修改. typedef struct _ServiceDesriptorEntry { ULONG *ServiceTableBase; // 服务表基址 ULONG *ServiceCoun

MySQL binlog日志恢复数据

我们了解了MySQL 的 binlog 日志的开启方式以及 binlog 日志的一些原理和常用操作,我们知道,binlog 有两大作用,一个是使用 binlog 恢复数据,另一个就是用来做主从复制.本篇笔记就是来记录如何使用 binlog 日志来做数据恢复.当然了,使用 binlog 日志所恢复的数据只能是部分数据,并不能够使用 binlog 日志来做数据库的备份,如果想要做数据库备份,依然要使用我们传统的备份方法,而 binlog 可以作为增量备份. 视频链接:http://www.ronco

20、oracle用户管理恢复

下面会一一讲解控制文件.redo文件及非归档模式.归档模式数据文件丢失的情况下,如何恢复数据? (1)控制文件(controlfile)丢失 在做恢复实验之前,先备份好数据. 案例1.模拟一个控制文件丢失 select name from v$controlfile; SQL> select name from v$controlfile; NAME -------------------------------------------------------------------------

安卓性能优化之Activity和Fragment通过onSaveInstanceState()保存和恢复数据

Activity和Fragment 都有自己的生命周期,而且很类似.Fragment比Activity多了onAttach()和onCreateView()这些方法.整体它们两者是一样的周期,都会经历从创建视图( onCreate(),onCreateView(),onStart() )到暂停( onPause(), onStop() ) 到重新返回( onResume() ) 到最后销毁( onDetroyView(), onDestroy() ) 这些方法. 之前有提过,熟悉组件的这些生命周

iPhone手机微信聊天记录清空怎么恢复?

众所周知,作为当下两款最火热的社交软件之一,微信已然成为手机上必不可少的软件,毕竟用微信不管是打电话还是发消息是既省钱又方便,现在的智能机基本上都会安装一个微信.不管是生活上还是工作上遇到的重要事情,都可已通过微信来和他人进行交流,长时间的使用微信,手机里也会存有许多的聊天记录,其中肯定有一些重要的,如果在清理内存时直接清空了聊天记录该怎么恢复呢? 1.将需要使用的iTunes软件以及互盾苹果恢复大师软件安装在电脑上,这里我们打开电脑的浏览进行软件的搜索,找到对应的下载资源然后进行软件的下载以及