HotPatch.c
#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 ;
}