现在的位置: 首页 > 综合 > 正文

hotpatch逆向代码~HotPatch.c

2013年08月22日 ⁄ 综合 ⁄ 共 16684字 ⁄ 字号 评论关闭

#include <ntddk.h>
#include <KerStr.h>
#include <RtlHelp.c>

#define MEM_HOT_PATCH 'HotP'
PVOID _MmSystemLoadLock ;
#define HotPatchSectionName '.hotp1'
LIST_ENTRY _MiHotPatchList ;
ERESOURCE _PsLoadedModuleResource ;
LIST_ENTRY _PsLoadedModuleList ;
ULONG_PTR _MiSessionImageStart ;
ULONG_PTR _MiSessionImageEnd ;

extern ULONG RtlGetHotPatchHeader(ULONG ImageBase) ;
extern ULONG
RtlFindRtlPatchHeader(LIST_ENTRY  HotPatchList,
                     PLDR_DATA_TABLE_ENTRY  LdrData );

extern BOOL RtlpIsSameImage(PRTL_PATCH_HEADER PatchHeader,
                     PLDR_DATA_TABLE_ENTRY LdrData);

extern NTSTATUS RtlCreateHotPatch(PRTL_PATCH_HEADER *ImageBase ,
                           PHOTPATCH_HEADER HPSectionData ,
                           PLDR_DATA_TABLE_ENTRY LdrData,
                           NTSTATUS Flags);
extern NTSTATUS
ExLockUserBuffer (
    __inout_bcount(Length) PVOID Buffer,
    __in ULONG Length,
    __in KPROCESSOR_MODE ProbeMode,
    __in LOCK_OPERATION LockMode,
    __deref_out PVOID *LockedBuffer,
    __deref_out PVOID *LockVariable
    );

extern VOID
ExUnlockUserBuffer (
    __inout PVOID LockVariable
    );

//two function form Windows Research Kernel source code

extern void RtlFreeHotPatchData(PRTL_PATCH_HEADER PatchData) ;

NTSTATUS
MiPerformHotPatch(PLDR_DATA_TABLE_ENTRY LdrData ,
                 ULONG ImageBase ,
                 NTSTATUS Flags)
{

ULONG TempLdr = 0;
PHOTPATCH_HEADER HPSectionData ;
NTSTATUS stat ;
PLDR_DATA_TABLE_ENTRY Link1 ;
PRTL_PATCH_HEADER PatchHeader ;
PVOID LockedBuffer ;
PVOID LockVariable ;

HPSectionData = RtlGetHotPatchHeader(ImageBase) ;

//获得HotPacth文件中的HotPacth数据

if (!HPSectionData)
{
    return STATUS_INVALID_IMAGE_FORMAT ;
}

ImageBase = RtlFindRtlPatchHeader(_MiHotPatchList ,LdrData) ;

//查找HotPatch是否已安装

if (!ImageBase )
{
    if (!Flags && 1)
    {
        return STATUS_NOT_SUPPORTED;

        //如果RtlPatchHeader不存在而HOTP_PATCH_APPLY=0
        //则出错
    }
   
    stat = RtlCreateHotPatch(&ImageBase, HPSectionData, LdrData ,Flags);

    PatchHeader = (PRTL_PATCH_HEADER)ImageBase ;
   
    //创建HotPacth头

    if (!NT_SUCCESS(stat))
    {
        return stat ;
    }
    ExAcquireResourceExclusiveLite(_PsLoadedModuleResource ,TRUE) ;
   
    //开始遍历PsLoadedModuleList
   
    //寻找符合的模块
   
    Link1 = _PsLoadedModuleList.Blink ;
    while (Link1 != _PsLoadedModuleList)
    {
        TempLdr = Link1 ;
        if (Link1->DllBase < _MiSessionImageStart ||
            Link1->DllBase >= _MiSessionImageEnd)
        {
            if (RtlpIsSameImage(PatchHeader ,Link1))
            {
                break ;
            }
           
        }

        Link1 = _PsLoadedModuleList.Blink ;
   
    }
    //验证模块

    ExReleaseResourceLite(_PsLoadedModuleResource) ;
    if (!PatchHeader->TargetDllBase)
    {
        return STATUS_DLL_NOT_FOUND ;
    }
    stat = ExLockUserBuffer(LdrData->DllBase,
        LdrData->SizeOfImage ,
        KernelMode,
        &LockedBuffer,
        &LockVariable
        ) ;
    //锁定用户内存
   
    if (!NT_SUCCESS(stat))
    {
        RtlFreeHotPatchData(PatchHeader );
        return stat ;
    }

    stat = RtlInitializeHotPatch(PatchHeader ,(ULONG)LockedBuffer - LdrData->DllBase) ;
    ExUnlockUserBuffer(LockVariable);
    if (!NT_SUCCESS(stat))
    {
        RtlFreeHotPatchData(PatchHeader );
        return stat ;

    }
       

}

}
NTSTATUS RtlpApplyRelocationFixups(PRTL_PATCH_HEADER PatchHeader , PVOID DllBase)
{
   
}
NTSTATUS RtlInitializeHotPatch(PRTL_PATCH_HEADER PatchHeader , PVOID DllBase)
{
    NTSTATUS stat ;
    stat = RtlpApplyRelocationFixups()
        if (!NT_SUCCESS(stat))
        {
            return stat ;
        }
    stat = RtlpValidateTargetRanges(PatchHeader ,TRUE) ;
        if (!NT_SUCCESS(stat))
        {
            return stat ;
        }
    stat = RtlReadHookInformation(PatchHeader) ;
    return stat ;
}
NTSTATUS MmHotPatchRoutine(PSYSTEM_HOTPATCH_CODE_INFORMATION RemoteInfo)
{
    UNICODE_STRING HotPatchName ;
    ULONG ImageBase ;
    HANDLE ImageHandle;
    NTSTATUS stat ;
    NTSTATUS stat2 ;

    stat2 = RemoteInfo->Flags ;
    HotPatchName.Length = RemoteInfo->KernelInfo.NameLength ;
    HotPatchName.MaximumLength = RemoteInfo->KernelInfo.NameLength  ;
    HotPatchName.Buffer = (ULONG)RemoteInfo + RemoteInfo->KernelInfo.NameOffset ;
    __asm
    {
        push    eax
        mov        eax, fs : 0x124   
        dec        dword ptr [eax + 0xd4]
        pop        eax
    }
    //enable the KTHREAD->KernelApcDisable

    KeWaitForSingleObject(_MmSystemLoadLock ,
        WrSuspended,
        NULL,
        NULL,
        NULL) ;

    //wait for mmsystemLoadLock

   
    stat = MmLoadSystemImage(&HotPatchName ,
        NULL,
        NULL,
        NULL,
        &ImageHandle,
        &ImageBase
        ) ;
   
    //加载hotpatch驱动程序

   
    if (!NT_SUCCESS(stat))
    {
        if (stat == STATUS_IMAGE_ALREADY_LOADED )
        {
            goto OK1;
               
            
        }
        goto Failed;

    }

    //如果驱动加载失败,返回
    //如果加载成功或镜象已经加载,则返回Image Base Address

OK1:
    stat = MiPerformHotPatch((PLDR_DATA_TABLE_ENTRY)ImageHandle , ImageBase , stat2) ;

    //执行补丁

   
    if (!NT_SUCCESS(stat))
    {
        if (stat == STATUS_IMAGE_ALREADY_LOADED)
        {
            goto OK2;

        }
        MmUnloadSystemImage(ImageHandle);

   
    }

    //如果执行失败,卸载镜象

OK2:
    stat = stat2 ;

Failed:
    KeReleaseMutant(_MmSystemLoadLock , 1 , NULL,NULL) ;
        __asm
        {
            push    eax
            push    esi
            mov        eax, fs : 0x124   
            inc        dword ptr [esi + 0xd4]
            jnz        end1
            lea        eax, [esi + 0x34]

            ;ApcState
            cmp        [ eax ], eax
            jz        end1
            mov        cl , 1
            mov        byte ptr [esi + 0x49] ,1
            call    HalRequestSoftwareInterrupt
           
            pop        esi
            pop        eax
        }
        //disable the KTHREAD->KernelApcDisable
        return stat ;

}

Hotpatch逆向代码(2) KerStr.h和RtlHelp.c~

enum assembly_type
{
    APPLICATION_MANIFEST,
    ASSEMBLY_MANIFEST
};

struct entity
{
    DWORD kind;
    union
    {
        struct
        {
            WCHAR *tlbid;
            WCHAR *version;
            WCHAR *helpdir;
    } typelib;
        struct
        {
            WCHAR *clsid;
    } comclass;
    struct {
            WCHAR *iid;
            WCHAR *name;
    } proxy;
        struct
        {
            WCHAR *name;
        } class;
        struct
        {
            WCHAR *name;
            WCHAR *clsid;
        } clrclass;
        struct
        {
            WCHAR *name;
            WCHAR *clsid;
        } clrsurrogate;
    } u;
};

struct assembly_identity
{
    WCHAR                *name;
    WCHAR                *arch;
    WCHAR                *public_key;
    WCHAR                *language;
    WCHAR                *type;
    struct version        version;
    BOOL                  optional;
};
struct dll_redirect
{
    WCHAR                *name;
    WCHAR                *hash;
    struct entity_array  entities;
};
struct entity_array
{
    struct entity        *base;
    unsigned int          num;
    unsigned int          allocated;
};

struct assembly
{
    enum assembly_type      type;
    struct assembly_identity id;
    struct file_info        manifest;
    WCHAR                  *directory;
    BOOL                    no_inherit;
    struct dll_redirect    *dlls;
    unsigned int            num_dlls;
    unsigned int            allocated_dlls;
    struct entity_array      entities;
};

struct file_info
{
    ULONG              type;
    WCHAR              *info;
};

typedef struct _ACTIVATION_CONTEXT
{
    ULONG              magic;
    int                ref_count;
    struct file_info    config;
    struct file_info    appdir;
    struct assembly    *assemblies;
    unsigned int        num_assemblies;
    unsigned int        allocated_assemblies;
} ACTIVATION_CONTEXT;

typedef struct _LDR_DATA_TABLE_ENTRY {
    LIST_ENTRY InLoadOrderLinks; //0x00
    LIST_ENTRY InMemoryOrderLinks; //00x08
    LIST_ENTRY InInitializationOrderLinks; //0x10
    PVOID DllBase; //0x18
    PVOID EntryPoint; //0x01c
    ULONG SizeOfImage; // 0x20
    UNICODE_STRING FullDllName; //0x24
    UNICODE_STRING BaseDllName; //0x2c
    ULONG Flags; //0x3
    USHORT LoadCount;
    USHORT TlsIndex;
    union {
        LIST_ENTRY HashLinks;
        struct {
            PVOID SectionPointer;
            ULONG CheckSum;
        };
    };
    union {
        struct {
            ULONG TimeDateStamp;
        };
        struct {
            PVOID LoadedImports;
        };
    };
    struct _ACTIVATION_CONTEXT * EntryPointActivationContext;
    PVOID PatchInformation;

} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

typedef struct _RTL_PATCH_HEADER {
  LIST_ENTRY PatchList;
  HMODULE PatchImageBase;
  struct _RTL_PATCH_HEADER * NextPatch;
  ULONG PatchFlags;
  LONG PatchRefCount;
  PHOTPATCH_HEADER HotpatchHeader;
  UNICODE_STRING TargetDllName;
  HMODULE TargetDllBase;
  PLDR_DATA_TABLE_ENTRY TargetLdrDataTableEntry;
  PLDR_DATA_TABLE_ENTRY PatchLdrDataTableEntry;
  PSYSTEM_HOTPATCH_CODE_INFORMATION CodeInfo;
} RTL_PATCH_HEADER, *PRTL_PATCH_HEADER;

//_RTL_PATCH_HEADER & _HOTPATCH_HEADER

//this two struct is form OpenRCE

typedef struct _HOTPATCH_HEADER {
  DWORD Signature; //0x00
  DWORD Version; //0x04
  DWORD FixupRgnCount; //0x08
  DWORD FixupRgnRva; //0x0c
  DWORD ValidationCount; //0x10
  DWORD ValidationArrayRva; //0x14
  DWORD HookCount; //0x18
  DWORD HookArrayRva; //0x1c
  ULONGLONG OrigHotpBaseAddress; //0x20
  ULONGLONG OrigTargetBaseAddress; //0x28
  DWORD TargetNameRva; //0x30
  DWORD ModuleIdMethod; //0x34
  union {
    ULONGLONG Quad;
    GUID Guid;
    struct {
      GUID Guid;
      DWORD Age;
    } PdbSig;
    BYTE Hash128[16];
    BYTE Hash160[20];
  } TargetModuleIdValue;
} HOTPATCH_HEADER, *PHOTPATCH_HEADER;

typedef struct _FILE_RENAME_INFORMATION {
    BOOLEAN ReplaceIfExists;
    HANDLE RootDirectory;
    ULONG FileNameLength;
    WCHAR FileName[1];
} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;

typedef struct _HOTPATCH_HOOK_DESCRIPTOR{
    ULONG_PTR TargetAddress; //0x0c
    PVOID MappedAddress; //00x10
    ULONG CodeOffset; //0x14
    ULONG CodeSize; //0x18
    ULONG OrigCodeOffset; //0x1c
    ULONG ValidationOffset; //0x20
    ULONG ValidationSize; //0x24
} HOTPATCH_HOOK_DESCRIPTOR, *PHOTPATCH_HOOK_DESCRIPTOR;

typedef struct _SYSTEM_HOTPATCH_CODE_INFORMATION {

    ULONG Flags;  //0x00
    ULONG InfoSize; //00x04
   
    union {
   
        struct {
       
            ULONG DescriptorsCount; //00x08
           
            HOTPATCH_HOOK_DESCRIPTOR CodeDescriptors[1]; // variable size structure
           
        } CodeInfo;
       
        struct {
       
            USHORT NameOffset; //0x08
            USHORT NameLength; //0x0a
           
        } KernelInfo;
       
        struct {
       
            USHORT NameOffset; //0x8
            USHORT NameLength; //0x0a
           
            USHORT TargetNameOffset; //0x0c
            USHORT TargetNameLength; //0x0e
           
        } UserModeInfo;
       
        struct {
       
            HANDLE FileHandle1;
            PIO_STATUS_BLOCK IoStatusBlock1;
            PFILE_RENAME_INFORMATION RenameInformation1;
            ULONG RenameInformationLength1;
            HANDLE FileHandle2;
            PIO_STATUS_BLOCK IoStatusBlock2;
            PFILE_RENAME_INFORMATION RenameInformation2;
            ULONG RenameInformationLength2;
           
        } RenameInfo;
       
        struct {
       
            HANDLE ParentDirectory;
            HANDLE ObjectHandle1;
            HANDLE ObjectHandle2;
           
        } AtomicSwap;
    };

    //
    //  NOTE Do not add anything after CodeDescriptors array as
    //  it is assumed to have a variable size
    //
   
} SYSTEM_HOTPATCH_CODE_INFORMATION, *PSYSTEM_HOTPATCH_CODE_INFORMATION;

NTSTATUS MmLoadSystemImage(
    IN PUNICODE_STRING ImageFileName,
    IN PUNICODE_STRING NamePrefix OPTIONAL,
    IN PUNICODE_STRING LoadedBaseName OPTIONAL,
    IN ULONG LoadFlags,
    OUT PVOID *ImageHandle,
    OUT PVOID *ImageBaseAddress
    );

//the routine to load the image into system kernel

NTSYSAPI
LONG
KeReleaseMutant (
    __inout PRKMUTANT Mutant,
    __in KPRIORITY Increment,
    __in BOOLEAN Abandoned,
    __in BOOLEAN Wait
    );

NTHALAPI
VOID
FASTCALL
HalRequestSoftwareInterrupt (
    KIRQL RequestIrql
    );

NTSTATUS
MmUnloadSystemImage (
    IN PVOID ImageHandle
    ) ;
PIMAGE_NT_HEADERS
NTAPI
RtlImageNtHeader(
    PVOID Base
    );

PIMAGE_SECTION_HEADER
RtlpFindSectionHeader(PIMAGE_NT_HEADERS ImageNtHeader ,
                     LPCSTR SectionName)
{
    ULONG    OHeaderSize ;
    ULONG    NumberOfSection ;
    ULONG    SectionHeaderStart ;
    ULONG    i ;
    OHeaderSize = ImageNtHeader->FileHeader.SizeOfOptionalHeader ;
    NumberOfSection = ImageNtHeader->FileHeader.NumberOfSections ;
    SectionHeaderStart = (ULONG)ImageNtHeader->OptionalHeader + OHeaderSize ;
    if (NumberOfSection <= 0)
    {
        return 0;
    }
    for (i= 0 ; i < NumberOfSection ; i++)
    {
        if (RtlCompareMemory(SectionHeaderStart ,
            SectionName ,
            IMAGE_SIZEOF_SHORT_NAME) == IMAGE_SIZEOF_SHORT_NAME)
        {
            return SectionHeaderStart ;
        }
        SectionHeaderStart += sizeof(IMAGE_SECTION_HEADER) ;
       
       
       
    }   
    return 0;

}

//该函数的作用是从PE镜象中找到指定Section名的Section Header并返回

ULONG RtlGetHotPatchHeader(ULONG ImageBase)
{
PIMAGE_NT_HEADERS ImageNtHeader ;
PIMAGE_SECTION_HEADER SectionStart ;
PHOTPATCH_HEADER HPSectionData ;

    ImageNtHeader = RtlImageNtHeader(ImageBase) ;
    if (!ImageBase)
    {
        return 0 ;
    }
    SectionStart = RtlpFindSectionHeader(ImageNtHeader , HotPatchSectionName );
    if (!SectionStart)
    {
        return 0 ;
    }
    if (SectionStart->Misc.VirtualSize < sizeof(HOTPATCH_HEADER))
    {
        return 0;
    }
    HPSectionData = SectionStart->VirtualAddress ;
   
    if (HPSectionData->Signature != 0x31544F48 )
    {
        //Char 'HOT1'
        return 0 ;
    }
    if (HPSectionData->Version = 0x10000)
    {
        return HPSectionData;
       
    }
    return 0;
   
   
}

// 该函数的作用从PE镜象中找到HOTPATCH节的地址,并进行一些基本验证

ULONG
RtlFindRtlPatchHeader(LIST_ENTRY  HotPatchList,
                     PLDR_DATA_TABLE_ENTRY  LdrData )
{
LIST_ENTRY HotPatchList1 ;

HotPatchList1 = HotPatchList1.Blink ;

while (HotPatchList1 != HotPatchList)
{
    if (*(ULONG*)HotPatchList1 + 0x2c == (ULONG)LdrData)
    {
        return HotPatchList1 ;
    }
    HotPatchList1 = HotPatchList1.Blink ;
   
    
}
return 0 ;
}

// 从目前已安装的补丁列表中寻找当前的补丁是否是已经安装的
//即是从MiHotPatchList这个双向链表中寻找是否有符合的RTL_PATCH_HEADER

BOOLEAN RtlpValidatePeHeaderHash2(PRTL_PATCH_HEADER PatchHeader,
                     PVOID DllBase)
{
    //not implement
    return FALSE ;
}
BOOLEAN RtlpValidatePeChecksum(PRTL_PATCH_HEADER PatchHeader,
                     PLDR_DATA_TABLE_ENTRY LdrData)

{
    //not implement
    return FALSE
}

BOOLEAN RtlpValidateTargetModule(PRTL_PATCH_HEADER PatchHeader,
                     PVOID DllBase)

{
    ULONG Method ;

    Method = PatchHeader->HotpatchHeader->ModuleIdMethod ;
    switch (Method)
    {
    case 0x0 :
             DbgPrintEx(0x57 ,0x2 ,"HOTP_ID_None/n" ) ;
                return TRUE ;
    case 0x1 :
             DbgPrintEx(0x57, 0x2 , "HOTP_ID_PeHeaderHash1") ;
             return FALSE ;
    case 0x2 :
             DbgPrintEx(0x57, 0x2 , "HOTP_ID_PeHeaderHash2") ;
             return RtlpValidatePeHeaderHash2(PatchHeader , LdrData->DllBase ) ;
    case 0x3 :
             return RtlpValidatePeChecksum(PatchHeader , LdrData->DllBase ) ;
    case 0x10 :
        DbgPrintEx(0x57, 0x2 ,"HOTP_ID_PeDebugSignature") ;
             return FALSE ;
    default :
        DbgPrintEx(0x57 ,0x2 ,"Unrecognized" ) ;
        return FALSE ;

            

    }
    return FALSE ;

}
BOOL RtlpIsSameImage(PRTL_PATCH_HEADER PatchHeader,
                     PLDR_DATA_TABLE_ENTRY LdrData)
{
    ULONG ImageNtHeader ;
    ImageNtHeader = RtlImageNtHeader(LdrData->DllBase) ;
    if (!ImageNtHeader)
    {
        return FALSE ;   
    }
    if (!RtlEqualUnicodeString(PatchHeader->TargetDllName, LdrData->BaseDllName , TRUE) )
    {
        return FALSE ;
    }
    if (!RtlpValidateTargetModule(PatchHeader , LdrData ))
    {
        return FALSE ;
    }
    PatchHeader->TargetLdrDataTableEntry = LdrData ;
    PatchHeader->TargetDllBase = LdrData->DllBase ;
   
    return TRUE ;

}

void RtlpFreeHotPatchMemory(PVOID Pool)
{
    ExFreePoolWithTag(Pool,
        MEM_HOT_PATCH);
    return ;
}
void RtlFreeHotPatchData(PRTL_PATCH_HEADER PatchData)
{

    if (PatchData->CodeInfo)
    {
        RtlpFreeHotPatchMemory(PatchData->CodeInfo) ;
   

    }
        RtlFreeAnsiString(&PatchData->TargetDllName) ;
        RtlpFreeHotPatchMemory(PatchData);
       
    return ;
}
   
NTSTATUS RtlCreateHotPatch(PRTL_PATCH_HEADER *ImageBase ,
                           PHOTPATCH_HEADER HPSectionData ,
                           PLDR_DATA_TABLE_ENTRY LdrData,
                           NTSTATUS Flags)
{
PRTL_PATCH_HEADER PatchHeader ;
ANSI_STRING AnsiDllName ;
UNICODE_STRING UniDllName ;
NTSTATUS stat ;

    PatchHeader = ExAllocatePoolWithTag(PagedPool , 0x34 ,MEM_HOT_PATCH) ;
    if (!PatchHeader)
    {
        return STATUS_NO_MEMORY ;
    }
    RtlZeroMemory(PatchHeader , 0x0d);
   
    PatchHeader->PatchFlags = Flags & 0xfffffffe ;
    PatchHeader->HotpatchHeader = HPSectionData ;
    PatchHeader->PatchLdrDataTableEntry = LdrData ;
    PatchHeader->PatchImageBase = LdrData->DllBase ;
    PatchHeader->PatchList.Blink = PatchHeader ;
    PatchHeader->PatchList.Flink = PatchHeader ;
    RtlInitAnsiString(&AnsiDllName ,
        (LPCSTR)(HPSectionData->TargetNameRva + LdrData->DllBase));
    stat = RtlAnsiStringToUnicodeString(&UniDllName , &AnsiDllName , TRUE) ;
    if (!NT_SUCCESS(stat))
    {
        RtlFreeHotPatchData(PatchHeader);
        return stat ;
    }
    ImageBase = PatchHeader ;
    return stat ;
   
   
}
#define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE 8

VOID
ExUnlockUserBuffer (
    __inout PVOID LockVariable
    )

{
    MmUnlockPages ((PMDL)LockVariable);
    ExFreePool ((PMDL)LockVariable);
    return;
}

NTSTATUS
ExLockUserBuffer (
    __inout_bcount(Length) PVOID Buffer,
    __in ULONG Length,
    __in KPROCESSOR_MODE ProbeMode,
//    __in LOCK_OPERATION LockMode,
    __deref_out PVOID *LockedBuffer,
    __deref_out PVOID *LockVariable
    )

    //modify to Windows xp module
   

/*++

Routine Description:

    Wrapper for MmProbeAndLockPages.  Creates an MDL and locks the
    specified buffer with that MDL.       

Arguments:

    Buffer - pointer to the buffer to be locked.
    Length - size of the buffer to be locked.
    ProbeMode - processor mode for doing the probe in MmProbeAndLockPages.
    LockMode - the mode the pages should be locked for.
    LockedBuffer - returns a pointer to the locked buffer for use by the
                  caller.
    LockVariable - returns a context pointer.  This must be passed into
                  ExUnlockUserBuffer when complete so the MDL can be freed.                 

Return Value:

    Returns one of the following status codes:

        STATUS_SUCCESS - Normal, successful completion.

        STATUS_ACCESS_VIOLATION - The buffer is not accessible with the
                specified LockMode.
               
        STATUS_INSUFFICIENT_RESOURCES - not enough memory to allocate the MDL.                                         
               

--*/

{
    PMDL Mdl;
    SIZE_T MdlSize;

    //
    // It is the caller's responsibility to ensure zero cannot be passed in.
    //

    ASSERT (Length != 0);

    *LockedBuffer = NULL;
    *LockVariable = NULL;

    //
    // Allocate an MDL to map the request.
    //

    MdlSize = MmSizeOfMdl( Buffer, Length );
    Mdl = ExAllocatePoolWithQuotaTag (NonPagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
                                      MdlSize,
                                      'ofnI');
    if (Mdl == NULL) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // Initialize MDL for request.
    //

    MmInitializeMdl(Mdl, Buffer, Length);

    try {

        MmProbeAndLockPages (Mdl, ProbeMode, 1);

    } _except (EXCEPTION_EXECUTE_HANDLER) {

        ExFreePool (Mdl);

        return GetExceptionCode();
    }

    Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
    *LockedBuffer = MmGetSystemAddressForMdl (Mdl);
    if (*LockedBuffer == NULL) {
        ExUnlockUserBuffer (Mdl);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    *LockVariable = Mdl;
    return STATUS_SUCCESS;
}

抱歉!评论已关闭.