├── .gitattributes ├── .gitignore ├── HotPatch.h ├── patch.cpp ├── patch1.cpp └── patch1.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /HotPatch.h: -------------------------------------------------------------------------------- 1 | #ifndef HOTPATCH_H 2 | #define HOTPATCH_H 3 | #include 4 | 5 | 6 | //Alignment of all structures (if not explicitly written) 7 | //must be 8 for x86 and 16 for the others 8 | 9 | //////////////////////////////////////////////////////////// 10 | typedef enum _HOTPATCH_FIXUP_TYPE { 11 | HOTP_Fixup_None = 0, 12 | HOTP_Fixup_VA32 = 1, 13 | HOTP_Fixup_PC32 = 2, 14 | HOTP_Fixup_VA64 = 3, 15 | HOTP_Fixup_PC64 = 4 //? 16 | } HOTPATCH_FIXUP_TYPE; 17 | 18 | //sizeof(HOTPATCH_FIXUP_ENTRY) must be 2 19 | typedef struct _HOTPATCH_FIXUP_ENTRY { 20 | WORD RvaOffset : 12; 21 | WORD /*HOTPATCH_FIXUP_TYPE*/ FixupType : 4; 22 | } HOTPATCH_FIXUP_ENTRY, *PHOTPATCH_FIXUP_ENTRY; 23 | 24 | typedef struct _HOTPATCH_FIXUP_REGION { 25 | unsigned int RvaHi : 20; 26 | unsigned int Count : 12; 27 | WORD /*HOTPATCH_FIXUP_ENTRY*/ Fixup[2]; //count always even 28 | } HOTPATCH_FIXUP_REGION, *PHOTPATCH_FIXUP_REGION; 29 | 30 | //////////////////////////////////////////////////////////// 31 | typedef enum _HOTPATCH_VALIDATION_OPTIONS { 32 | HOTP_Valid_Hook_Target = 1 //skip 33 | } HOTPATCH_VALIDATION_OPTIONS; 34 | 35 | typedef struct _HOTPATCH_VALIDATION { 36 | DWORD SourceRva; 37 | DWORD TargetRva; 38 | WORD ByteCount; 39 | WORD /*HOTPATCH_VALIDATION_OPTIONS*/ OptionFlags; 40 | } HOTPATCH_VALIDATION, *PHOTPATCH_VALIDATION; 41 | 42 | //////////////////////////////////////////////////////////// 43 | typedef enum _HOTPATCH_HOOK_TYPE { 44 | HOTP_Hook_None = 0, 45 | HOTP_Hook_VA32 = 1, 46 | HOTP_Hook_X86_JMP = 2, 47 | HOTP_Hook_PCREL32 = 3, //not yet implemented 48 | HOTP_Hook_X86_JMP2B = 4, 49 | HOTP_Hook_VA64 = 16, 50 | HOTP_Hook_IA64_BRL = 32, 51 | HOTP_Hook_IA64_BR = 33, //not yet implemented 52 | HOTP_Hook_AMD64_IND = 48, 53 | HOTP_Hook_AMD64_CNT = 49 54 | } HOTPATCH_HOOK_TYPE; 55 | 56 | typedef struct _HOTPATCH_HOOK { 57 | WORD /*HOTPATCH_HOOK_TYPE*/ HookType; 58 | WORD HookOptions; //0..5 - size of available space 59 | DWORD HookRva; 60 | DWORD HotpRva; 61 | DWORD ValidationRva; 62 | } HOTPATCH_HOOK, *PHOTPATCH_HOOK; 63 | 64 | //////////////////////////////////////////////////////////// 65 | typedef enum _HOTPATCH_MODULE_ID_METHOD { 66 | HOTP_ID_None = 0, 67 | HOTP_ID_PeHeaderHash1 = 1, //not yet supported 68 | HOTP_ID_PeHeaderHash2 = 2, 69 | HOTP_ID_PeChecksum = 3, 70 | HOTP_ID_PeDebugSignature = 16 //not yet supported 71 | } HOTPATCH_MODULE_ID_METHOD; 72 | 73 | 74 | #define DEBUG_SIGNATURE_HOTPATCH 0xD201 75 | #define DEBUG_SIGNATURE_COLDPATCH 0xD202 76 | 77 | typedef struct _HOTPATCH_DEBUG_SIGNATURE { 78 | WORD HotpatchVersion; 79 | WORD Signature; 80 | } HOTPATCH_DEBUG_SIGNATURE, *PHOTPATCH_DEBUG_SIGNATURE; 81 | 82 | typedef struct _HOTPATCH_DEBUG_DATA { 83 | ULONGLONG PEHashData; 84 | ULONGLONG ChecksumData; 85 | } HOTPATCH_DEBUG_DATA, *PHOTPATCH_DEBUG_DATA; 86 | 87 | //////////////////////////////////////////////////////////// 88 | #define HOTP_SECTION_NAME ".hotp1 " 89 | #define HOTP_SECTION_NAMELL 0x20203170746F682ELL 90 | #define HOTP_SECTION_MIN_SIZE 80 91 | 92 | #define HOTP_SIGNATURE 0x31544F48 //'HOT1' 93 | #define HOTP_VERSION_1 0x00010000 94 | 95 | typedef struct _HOTPATCH_HEADER { 96 | DWORD Signature; 97 | DWORD Version; 98 | DWORD FixupRgnCount; 99 | DWORD FixupRgnRva; 100 | DWORD ValidationCount; 101 | DWORD ValidationArrayRva; 102 | DWORD HookCount; 103 | DWORD HookArrayRva; 104 | ULONGLONG OrigHotpBaseAddress; 105 | ULONGLONG OrigTargetBaseAddress; 106 | DWORD TargetNameRva; 107 | DWORD ModuleIdMethod; 108 | union { 109 | ULONGLONG Quad; 110 | GUID Guid; 111 | struct { 112 | GUID Guid; 113 | DWORD Age; 114 | } PdbSig; 115 | BYTE Hash128[16]; 116 | BYTE Hash160[20]; 117 | } TargetModuleIdValue; 118 | } HOTPATCH_HEADER, *PHOTPATCH_HEADER; 119 | 120 | //////////////////////////////////////////////////////////// 121 | #define SystemHotpatchInformation 0x45 122 | 123 | //coldpatch sub-functions 124 | #define HOTP_RENAME_FILES 0x10000000 //RenameInfo //pre-Vista 125 | #define HOTP_UPDATE_SYSDLL 0x40000000 //no info requred 126 | #define HOTP_UPDATE_KNOWNDLL 0x08000000 //AtomicSwap 127 | 128 | //hotpatch sub-functions 129 | #define HOTP_USE_MODULE 0x20000000 //KernelInfo or InjectionInfo when calling Nt/ZwSetSystemInformation 130 | //UserModeInfo when calling LdrHotPatchRoutine 131 | #define HOTP_INJECT_THREAD 0x01000000 //InjectionInfo, HOTPATCH_USE_MODULE must be set //Vista 132 | #define HOTP_KERNEL_MODULE 0x80000000 //KernelInfo, HOTPATCH_USE_MODULE must be set 133 | //if none of the three flags above is set, CodeInfo is evaluated and applied directly 134 | 135 | //hotpatch commands/states 136 | #define HOTP_PATCH_APPLY 0x00000001 //command for KernelInfo or UserModeInfo (HOTPATCH_USE_MODULE is set) 137 | //0 - remove, 1 - apply the patch 138 | #define HOTP_PATCH_STATUS 0x00000001 //command for CodeInfo: 0 - apply, 1 - remove the patch 139 | //status for CodeInfo: after CodeInfo ^ before CodeInfo ? success : failure 140 | #define HOTP_PATCH_FAILURE 0x00800000 //intermediate flag 141 | 142 | typedef struct _HOTPATCH_HOOK_DESCRIPTOR { 143 | ULONG_PTR TargetAddress; 144 | LPVOID MappedAddress; 145 | DWORD CodeOffset; 146 | DWORD CodeSize; 147 | DWORD OrigCodeOffset; 148 | DWORD ValidationOffset; 149 | DWORD ValidationSize; 150 | } HOTPATCH_HOOK_DESCRIPTOR, *PHOTPATCH_HOOK_DESCRIPTOR; 151 | 152 | //typedef struct _IO_STATUS_BLOCK { 153 | // union { 154 | // LONG Status; 155 | // PVOID Pointer; 156 | // }; 157 | // ULONG_PTR Information; 158 | //} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; 159 | 160 | typedef struct _FILE_RENAME_INFORMATION { 161 | BOOLEAN ReplaceIfExists; 162 | HANDLE RootDirectory; 163 | ULONG FileNameLength; 164 | WCHAR FileName[1]; 165 | } FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; 166 | 167 | typedef struct _SYSTEM_HOTPATCH_CODE_INFORMATION { 168 | DWORD Flags; 169 | DWORD InfoSize; 170 | union { 171 | struct { 172 | DWORD DescriptorsCount; 173 | HOTPATCH_HOOK_DESCRIPTOR CodeDescriptors[1]; 174 | } CodeInfo; 175 | 176 | struct { 177 | WORD NameOffset; 178 | WORD NameLegth; 179 | } KernelInfo; 180 | 181 | struct { 182 | WORD NameOffset; 183 | WORD NameLegth; 184 | WORD TargetNameOffset; 185 | WORD TargetNameLegth; 186 | BOOLEAN PatchingFinished; 187 | } UserModeInfo; 188 | 189 | struct { 190 | WORD NameOffset; 191 | WORD NameLegth; 192 | WORD TargetNameOffset; 193 | WORD TargetNameLegth; 194 | BOOLEAN PatchingFinished; 195 | DWORD ReturnCode; 196 | HANDLE TargetProcess; 197 | } InjectionInfo; 198 | 199 | struct { 200 | HANDLE FileHandle1; 201 | PIO_STATUS_BLOCK IoStatusBlock1; 202 | PVOID /*PFILE_RENAME_INFORMATION*/ RenameInformation1; 203 | DWORD RenameInformationLength1; 204 | HANDLE FileHandle2; 205 | PIO_STATUS_BLOCK IoStatusBlock2; 206 | PVOID /*PFILE_RENAME_INFORMATION*/ RenameInformation2; 207 | DWORD RenameInformationLength2; 208 | } RenameInfo; 209 | 210 | struct { 211 | HANDLE ParentDirectory; 212 | HANDLE ObjectHandle1; 213 | HANDLE ObjectHandle2; 214 | } AtomicSwap; 215 | }; 216 | } SYSTEM_HOTPATCH_CODE_INFORMATION, *PSYSTEM_HOTPATCH_CODE_INFORMATION; 217 | 218 | #define PATCHFLAG_COLDPATCH_VALID 0x00010000 219 | 220 | #include 221 | 222 | typedef struct _RTL_PATCH_HEADER { 223 | LIST_ENTRY PatchList; 224 | HMODULE PatchImageBase; //8 225 | struct _RTL_PATCH_HEADER * NextPatch; //12 226 | ULONG PatchFlags; 227 | LONG PatchRefCount; 228 | PHOTPATCH_HEADER HotpatchHeader; 229 | UNICODE_STRING TargetDllName; //28 230 | HMODULE TargetDllBase; //36 231 | PLDR_DATA_TABLE_ENTRY TargetLdrDataTableEntry; //40 232 | PLDR_DATA_TABLE_ENTRY PatchLdrDataTableEntry; //44 233 | PSYSTEM_HOTPATCH_CODE_INFORMATION CodeInfo; //48 234 | } RTL_PATCH_HEADER, *PRTL_PATCH_HEADER; 235 | 236 | 237 | #endif HOTPATCH_H -------------------------------------------------------------------------------- /patch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "HotPatch.h" 3 | #include 4 | #include "patch1.h" 5 | 6 | 7 | extern LIST_ENTRY _PsLoadedModuleList ; 8 | extern NTSTATUS RtlEnterCriticalSection(RTL_CRITICAL_SECTION* crit); 9 | extern NTSTATUS RtlLeaveCriticalSection(RTL_CRITICAL_SECTION* crit); 10 | extern NTSTATUS LdrUnloadDll(HANDLE module); 11 | RTL_CRITICAL_SECTION LdrpLoaderLock; 12 | #define FLG_HOTPATCH_ACTIVE 1 13 | 14 | LIST_ENTRY LdrpHotPatchList; 15 | ULONG LdrpHotpatchCount; 16 | LIST_ENTRY LdrpHotpatchModuleInfoList; //todo : check the type 17 | 18 | //TODO check it 19 | LIST_ENTRY* RtlFindRtlPatchHeader(LIST_ENTRY LdrpHotPatchList, PLDR_DATA_TABLE_ENTRY LdrData) 20 | { 21 | LIST_ENTRY* HotPatchList1 ; 22 | HotPatchList1 = LdrpHotPatchList.Blink ; 23 | while (HotPatchList1 != &LdrpHotPatchList) 24 | { 25 | if (*(ULONG*)HotPatchList1 + 0x2c == (ULONG)LdrData) 26 | { 27 | return HotPatchList1 ; 28 | } 29 | HotPatchList1 = HotPatchList1->Blink; 30 | } 31 | return NULL; 32 | } 33 | 34 | BOOLEAN LdrpHotpatchModuleInfoRemoveCallback(void* arg1, void* arg2) 35 | { 36 | return RtlFreeHotPatchData((PRTL_PATCH_HEADER)((DWORD*)arg2 - 0x38)); 37 | } 38 | 39 | void RtlTripleListInitialize(LIST_ENTRY* list, void*, int flags) 40 | { 41 | //todo: not implement 42 | } 43 | 44 | NTSTATUS LdrHotPatchRoutine(hotpatch_param param) 45 | { 46 | NTSTATUS status; 47 | RtlEnterCriticalSection(&LdrpLoaderLock); 48 | bool entered = true; 49 | bool patched = false; 50 | 51 | PTEB teb = (PTEB)__readfsbyte(0x18); 52 | DWORD hotpatch_info = *((DWORD*)teb->ProcessEnvironmentBlock + 0x50); 53 | if ( !hotpatch_info ) 54 | { 55 | RtlTripleListInitialize(&LdrpHotpatchModuleInfoList, LdrpHotpatchModuleInfoRemoveCallback, 0); 56 | *((DWORD*)teb->ProcessEnvironmentBlock + 0x50) = (DWORD)&LdrpHotpatchModuleInfoList; 57 | } 58 | //check new.dll is loaded or not ? old.dll? 59 | LIST_ENTRY* ModuleList = teb->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList.Flink; 60 | LIST_ENTRY* temp = ModuleList; 61 | bool find = false; 62 | while(temp != &teb->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList) 63 | { 64 | if( temp->Flink != NULL && RtlEqualUnicodeString(¶m.TargetName, &((LDR_DATA_TABLE_ENTRY*)temp)->FullDllName, true) ) 65 | { 66 | find = true; 67 | } 68 | temp = temp->Flink; 69 | } 70 | if ( find == false ) 71 | { 72 | status = STATUS_DLL_NOT_FOUND; 73 | goto end; 74 | } 75 | 76 | if ( !LdrpHotpatchCount ) 77 | { 78 | LdrpHotPatchList.Blink = &LdrpHotPatchList; // ? 79 | } 80 | 81 | HANDLE new_dll; 82 | status = LdrLoadDll(NULL, 0, ¶m.SourceName, &new_dll);// load new dll, new_module is the start address of new.dll 83 | #define STATUS_UNSUCCESSFUL 0xC0000001 84 | PLDR_DATA_TABLE_ENTRY new_module_info = NULL; 85 | if ( (status & 0x80000000u) == 0 ) 86 | { 87 | LIST_ENTRY* temp = ModuleList; 88 | while(temp != &teb->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList) 89 | { 90 | PLDR_DATA_TABLE_ENTRY temp2 = (PLDR_DATA_TABLE_ENTRY)temp; 91 | if( temp->Flink != NULL && new_dll == temp2->DllBase ) 92 | { 93 | new_module_info = temp2; 94 | break; 95 | } 96 | temp = temp->Flink; 97 | } 98 | if( !new_module_info ) 99 | { 100 | status = STATUS_UNSUCCESSFUL; 101 | goto end; 102 | } 103 | 104 | PHOTPATCH_HEADER section_data = RtlGetHotpatchHeader(new_dll);// point to hot section in new.dll 105 | if ( !section_data ) // not find 106 | { 107 | status = 0xC000007Bu; 108 | goto end; 109 | } 110 | 111 | PRTL_PATCH_HEADER patch_header = (PRTL_PATCH_HEADER)RtlFindRtlPatchHeader(LdrpHotPatchList, new_module_info); 112 | if ( patch_header )//the patch is already installed 113 | { 114 | if ( !patch_header->CodeInfo->Flags & FLG_HOTPATCH_ACTIVE ) //patch is not active 115 | { 116 | status = RtlReadHookInformation(patch_header); 117 | if ( (status & 0x80000000u) != 0 ) 118 | goto end; 119 | } 120 | } 121 | else 122 | { 123 | status = RtlCreateHotPatch(patch_header,section_data,new_module_info,param.shci.Flags); 124 | if ( (status & 0x80000000u) != 0 ) 125 | goto end; 126 | status = LdrpSetupHotpatch(patch_header); 127 | if ( (status & 0x80000000u) != 0 ) 128 | { 129 | RtlFreeHotPatchData(patch_header); 130 | goto end; 131 | } 132 | //TOdo has call NTopenfile 133 | 134 | //apply hotpatch 135 | status = LdrpApplyHotPatch(patch_header, param.shci.Flags); 136 | if ( patched ) 137 | { 138 | if ( (status & 0x80000000u) != 0 ) 139 | { 140 | RtlFreeHotPatchData(patch_header); 141 | patched = false; 142 | } 143 | else 144 | { 145 | // add into patch list 146 | /*patch_header->NextPatch->PatchList.Flink = patch_header->TargetLdrDataTableEntry->PatchInformation = patch_header; 147 | patch_header->PatchList.Flink = &LdrpHotPatchList; 148 | patch_header->PatchList.Blink = LdrpHotPatchList; 149 | LdrpHotPatchList->PatchList.Flink = patch_header; 150 | LdrpHotPatchList = patch_header; 151 | ++LdrpHotpatchCount;*/ 152 | //RtlTripleListInsert(&LdrpHotpatchModuleInfoList, patch_header->); 153 | } 154 | } 155 | } 156 | 157 | } 158 | end: 159 | if ( entered ) 160 | RtlLeaveCriticalSection(&LdrpLoaderLock); 161 | if ( !patched && new_dll ) 162 | LdrUnloadDll(new_dll); 163 | ULONG RegionSize = 0; 164 | return NtFreeVirtualMemory(GetCurrentProcess(), (PVOID*)¶m, &RegionSize, MEM_RELEASE); 165 | } 166 | -------------------------------------------------------------------------------- /patch1.cpp: -------------------------------------------------------------------------------- 1 | #include "patch1.h" 2 | #include 3 | 4 | 5 | NTSTATUS LdrpSetHotpatchProtection(PVOID Dllbase, int flags) 6 | { 7 | //TODO: implement later 8 | return 0; 9 | } 10 | BOOLEAN RtlpValidatePeHeaderHash2(PRTL_PATCH_HEADER PatchHeader, 11 | PVOID DllBase) 12 | { 13 | //TODO implement later 14 | return FALSE ; 15 | } 16 | 17 | NTSTATUS RtlpApplyRelocationFixups(PRTL_PATCH_HEADER patch_header, int flags) 18 | { 19 | //todo implement later 20 | return 0; 21 | } 22 | 23 | BOOLEAN RtlpValidatePeChecksum(PRTL_PATCH_HEADER PatchHeader, 24 | PVOID DllBase) 25 | 26 | { 27 | //TODO implement later 28 | return FALSE; 29 | } 30 | 31 | BOOLEAN RtlpFreeAtom(PVOID address) 32 | { 33 | return RtlFreeHeap(GetProcessHeap(), 0, address); 34 | } 35 | 36 | PVOID RtlpAllocateHotpatchMemory(SIZE_T Size,ULONG Flags) 37 | { 38 | RtlAllocateHeap(GetProcessHeap(),0,Size); 39 | } 40 | 41 | NTSTATUS RtlCreateHotPatch(PRTL_PATCH_HEADER patch_header_out , //out 42 | PHOTPATCH_HEADER hotpatch_data , 43 | PLDR_DATA_TABLE_ENTRY LdrData, 44 | DWORD Flags) //check about the last param 45 | { 46 | NTSTATUS ret; 47 | PRTL_PATCH_HEADER patch_header = (PRTL_PATCH_HEADER)RtlpAllocateHotpatchMemory(sizeof(RTL_PATCH_HEADER),0); 48 | if( patch_header) 49 | { 50 | memset(patch_header, 0, sizeof(RTL_PATCH_HEADER)); 51 | 52 | patch_header->HotpatchHeader = hotpatch_data; 53 | patch_header->PatchLdrDataTableEntry = LdrData; 54 | patch_header->PatchImageBase = (HMODULE)LdrData->DllBase; 55 | //patch_header->Hash128 = 0x8; 56 | patch_header->PatchList.Blink = (LIST_ENTRY*)patch_header ; 57 | patch_header->PatchList.Flink = (LIST_ENTRY*)patch_header ; 58 | patch_header->PatchFlags = Flags & 0xFFFFFFFE; 59 | PANSI_STRING target_dll; 60 | RtlInitAnsiString(target_dll, (PCSZ)((DWORD)LdrData->DllBase + hotpatch_data->TargetNameRva)); 61 | NTSTATUS status = RtlAnsiStringToUnicodeString(&patch_header->TargetDllName, target_dll, 1); 62 | 63 | if ( (status & 0x80000000u) != 0 ) 64 | RtlFreeHotPatchData(patch_header); 65 | else 66 | patch_header_out = patch_header; 67 | ret = status; 68 | } 69 | else 70 | { 71 | ret = STATUS_NO_MEMORY; 72 | } 73 | return ret; 74 | 75 | } 76 | 77 | 78 | NTSTATUS LdrpSetupHotpatch(PRTL_PATCH_HEADER patch_header) 79 | { 80 | //seems the code has no meaning here 81 | /* PTEB teb = (PTEB)__readfsbyte(0x18); 82 | 83 | LIST_ENTRY* ModuleList = teb->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList.Flink; 84 | LIST_ENTRY* temp = ModuleList; 85 | bool find = false; 86 | while(temp != &teb->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList) 87 | { 88 | if( temp->Flink != NULL && RtlpIsSameImage(patch_header, (PLDR_DATA_TABLE_ENTRY)temp) ) 89 | { 90 | find = true; 91 | break; 92 | } 93 | temp = temp->Flink; 94 | }*/ 95 | 96 | NTSTATUS result; 97 | 98 | if ( patch_header->TargetDllBase ) 99 | { 100 | result = LdrpSetHotpatchProtection(patch_header->PatchLdrDataTableEntry->DllBase,0 ); 101 | if ( (result & 0x80000000u) == 0 ) 102 | { 103 | result = RtlInitializeHotPatch(patch_header, 0); 104 | LdrpSetHotpatchProtection(patch_header->PatchLdrDataTableEntry->DllBase,1 ); 105 | } 106 | } 107 | else 108 | { 109 | result = STATUS_DLL_NOT_FOUND; 110 | } 111 | return result; 112 | 113 | } 114 | 115 | NTSTATUS LdrpApplyHotPatch(PRTL_PATCH_HEADER patch_header, int flags) 116 | { 117 | NTSTATUS result; 118 | 119 | if ( patch_header->TargetDllBase ) 120 | { 121 | result = LdrpSetHotpatchProtection(patch_header->PatchLdrDataTableEntry->DllBase,0 ); 122 | if ( (result & 0x80000000u) == 0 ) 123 | { 124 | result = RtlInitializeHotPatch(patch_header, 0); 125 | LdrpSetHotpatchProtection(patch_header->PatchLdrDataTableEntry->DllBase,1 ); 126 | } 127 | } 128 | else 129 | { 130 | result = STATUS_DLL_NOT_FOUND; 131 | } 132 | return result; 133 | } 134 | 135 | 136 | NTSTATUS RtlInitializeHotPatch(PRTL_PATCH_HEADER patch_header, int flags) 137 | { 138 | NTSTATUS result; 139 | 140 | result = RtlpApplyRelocationFixups(patch_header, flags); 141 | if ( result >= 0 ) 142 | { 143 | result = RtlpValidateTargetRanges(patch_header, 1); 144 | if ( result >= 0 ) 145 | result = RtlReadHookInformation(patch_header); 146 | } 147 | return result; 148 | } 149 | 150 | bool RtlpValidateTargetModule(PRTL_PATCH_HEADER patch_header, PLDR_DATA_TABLE_ENTRY Ldrdata) 151 | { 152 | ULONG method = patch_header->HotpatchHeader->ModuleIdMethod; 153 | char* message = NULL; 154 | switch(method) 155 | { 156 | case HOTP_ID_None: 157 | DbgPrintEx(85, 2, "HOTP_ID_None\n"); //not support 158 | return true; 159 | case HOTP_ID_PeHeaderHash1: 160 | DbgPrintEx(85, 2, "HOTP_ID_PeHeaderHash1"); //not support 161 | return false; 162 | case HOTP_ID_PeHeaderHash2: 163 | DbgPrintEx(85, 2, "HOTP_ID_PeHeaderHash2"); 164 | return RtlpValidatePeHeaderHash2(patch_header, Ldrdata->DllBase); 165 | case HOTP_ID_PeChecksum: 166 | return RtlpValidatePeChecksum(patch_header, Ldrdata->DllBase); 167 | case HOTP_ID_PeDebugSignature: 168 | DbgPrintEx(85, 2, "HOTP_ID_PeDebugSignature"); //not support 169 | return false; 170 | default: 171 | DbgPrintEx(85, 2, "Unrecognized"); //not support 172 | return false; 173 | 174 | } 175 | } 176 | 177 | bool RtlpIsSameImage(PRTL_PATCH_HEADER patch_header, PLDR_DATA_TABLE_ENTRY Ldrdata) 178 | { 179 | bool ret = false; 180 | if ( RtlImageNtHeader((HANDLE)Ldrdata->DllBase) ) 181 | { 182 | if ( RtlEqualUnicodeString(&patch_header->TargetDllName, &Ldrdata->FullDllName, true) 183 | && RtlpValidateTargetModule(patch_header, Ldrdata) ) 184 | { 185 | patch_header->PatchLdrDataTableEntry = Ldrdata; 186 | patch_header->TargetDllBase = (HMODULE)Ldrdata->DllBase; 187 | ret = true; 188 | } 189 | } 190 | return ret; 191 | } 192 | 193 | 194 | BOOLEAN RtlFreeHotPatchData(PRTL_PATCH_HEADER patch_header) 195 | { 196 | if ( patch_header->CodeInfo ) 197 | RtlpFreeAtom(patch_header->CodeInfo); 198 | if ( patch_header->TargetDllBase ) 199 | NtClose(patch_header->TargetDllBase); 200 | RtlFreeUnicodeString(&patch_header->TargetDllName); 201 | return RtlpFreeAtom(patch_header); 202 | } 203 | 204 | 205 | NTSTATUS RtlReadHookInformation(PRTL_PATCH_HEADER patch_header) 206 | { 207 | PHOTPATCH_HEADER hotpatch_header = patch_header->HotpatchHeader; 208 | DWORD HookCount = hotpatch_header->HookCount; 209 | DWORD HookArrayRva = hotpatch_header->HookArrayRva; 210 | IMAGE_NT_HEADERS* NtHaader = RtlImageNtHeader(patch_header->PatchImageBase); 211 | if ( !HookCount ) 212 | { 213 | DbgPrintEx(85, 0, "No hooks defined in hotpatch\n"); 214 | return 0xC000007B; 215 | } 216 | DWORD image_size = NtHaader->OptionalHeader.SizeOfImage; 217 | if ( !HookArrayRva 218 | || HookArrayRva >= image_size 219 | || HookArrayRva + sizeof(HOTPATCH_HOOK) * HookCount >= image_size ) 220 | { 221 | DbgPrintEx(85, 0, "Invalid hotpatch hook array pointer\n"); 222 | return 0xC000007B; 223 | } 224 | PHOTPATCH_HOOK HookArray = (PHOTPATCH_HOOK)(HookArrayRva + (DWORD)patch_header->PatchImageBase); 225 | DbgPrintEx(85, 2, "Inserting %u hooks into target image\n", HookCount); 226 | DWORD totalMemory = 40 * (HookCount - 1) + 56; 227 | size_t Size; 228 | NTSTATUS status; 229 | int index = 0; 230 | if ( HookCount ) 231 | { 232 | while ( 1 ) 233 | { 234 | status = RtlpReadSingleHookInformation(patch_header, HookArray, 0, &Size, 0); 235 | if ( status < 0 ) 236 | break; 237 | totalMemory += 2 * Size; 238 | if ( HookArray->ValidationRva ) 239 | { 240 | /* status = RtlReadSingleHookValidation(patch_header, HookArray, 0, &Size, 0, 0, 0); 241 | if ( status < 0 ) 242 | return status; 243 | totalMemory += Size;*/ 244 | } 245 | ++index; 246 | ++HookArray; 247 | if ( index >= HookCount ) 248 | goto LABEL1; 249 | } 250 | } 251 | else 252 | { 253 | LABEL1: 254 | //TODO not finished 255 | PVOID hotpatch_addr = RtlpAllocateHotpatchMemory(totalMemory, 1); 256 | if ( hotpatch_addr ) 257 | { 258 | //init the value 259 | if ( HookCount ) 260 | { 261 | DWORD hookaddr = (DWORD)patch_header->TargetDllBase + HookArray->HookRva; 262 | int index = 0; 263 | /*while(1) 264 | { 265 | index++; 266 | }*/ 267 | } 268 | } 269 | else 270 | { 271 | status = STATUS_NO_MEMORY; 272 | } 273 | } 274 | return status; 275 | } 276 | 277 | NTSTATUS RtlpValidateTargetRanges(PRTL_PATCH_HEADER patch_header, bool flags) 278 | { 279 | PHOTPATCH_HEADER hotpatch_header = patch_header->HotpatchHeader; 280 | DWORD ValidationCount = hotpatch_header->ValidationCount; 281 | DWORD ValidationArrayRva = hotpatch_header->ValidationArrayRva; 282 | IMAGE_NT_HEADERS* NtHaader = RtlImageNtHeader(patch_header->PatchImageBase); 283 | NTSTATUS status; 284 | if ( ! ValidationCount ) 285 | return 0; 286 | if ( ValidationArrayRva ) 287 | { 288 | DWORD image_size = NtHaader->OptionalHeader.SizeOfImage; 289 | if ( ValidationArrayRva < image_size ) 290 | { 291 | if ( ValidationArrayRva + sizeof(HOTPATCH_VALIDATION) * ValidationCount < image_size ) 292 | { 293 | PHOTPATCH_VALIDATION ValidatationArray = (PHOTPATCH_VALIDATION)(ValidationArrayRva + (DWORD)patch_header->PatchImageBase); 294 | int index = 0; 295 | PHOTPATCH_VALIDATION array = ValidatationArray; 296 | if ( ValidationCount ) 297 | { 298 | do { 299 | if ( flags && array->OptionFlags == 1 ) 300 | { 301 | DbgPrintEx(85, 2, "Skipping hook-specific validation range during global validation\n"); 302 | } 303 | else 304 | { 305 | status = RtlpSingleRangeValidate(patch_header, array); 306 | if ( status < 0 ) 307 | { 308 | DbgPrintEx(85, 0, "Validation failed for global range %u of %u\n", index + 1, ValidationCount); 309 | return status; 310 | } 311 | } 312 | array++; 313 | ++index; 314 | }while(index < ValidationCount ); 315 | } 316 | return 0; 317 | } 318 | } 319 | } 320 | DbgPrintEx(85, 0, "Invalid hotpatch validation array pointer\n"); 321 | return 0xC000007B; //STATUS_INVALID_IMAGE_FORMAT 322 | } 323 | 324 | 325 | NTSTATUS RtlpSingleRangeValidate(PRTL_PATCH_HEADER patch_header, PHOTPATCH_VALIDATION valarray) 326 | { 327 | DWORD SourceRva = valarray->SourceRva; 328 | WORD bytecount = valarray->ByteCount; 329 | DWORD targetrva = valarray->TargetRva; 330 | PIMAGE_NT_HEADERS nthead1 = RtlImageNtHeader(patch_header->PatchImageBase); 331 | PIMAGE_NT_HEADERS nthead2 = RtlImageNtHeader(patch_header->TargetDllBase); 332 | DWORD image_size = nthead1->OptionalHeader.SizeOfImage; 333 | NTSTATUS status; 334 | char* message = NULL; 335 | if ( SourceRva >= image_size || SourceRva + bytecount >= image_size ) 336 | { 337 | message = "Invalid source hotpatch validation range\n"; 338 | goto err_exit; 339 | } 340 | if ( RtlCompareMemory(SourceRva + patch_header->PatchImageBase, targetrva + patch_header->TargetDllBase, bytecount) == bytecount ) 341 | { 342 | status = 0; 343 | } 344 | else 345 | { 346 | DbgPrintEx( 347 | 85, 348 | 2, 349 | "Validation failure. Source = %p, Target = %p, Size = %x\n", 350 | SourceRva + patch_header->PatchImageBase, 351 | targetrva + patch_header->TargetDllBase, 352 | bytecount); 353 | status = 0xC000003E; 354 | } 355 | 356 | err_exit: 357 | DbgPrintEx(85, 0, message); 358 | return 0xC000007B; 359 | } 360 | 361 | NTSTATUS RtlpReadSingleHookInformation(PRTL_PATCH_HEADER patch_header, HOTPATCH_HOOK* HookArray,int flags1, size_t* pSize, DWORD* pHotpAddr) 362 | { 363 | PIMAGE_NT_HEADERS ntheader_patch = RtlImageNtHeader(patch_header->PatchImageBase); 364 | if ( !ntheader_patch ) 365 | { 366 | DbgPrintEx(85, 0, "Invalid hotpatch base address\n"); 367 | return 0xC000007B; 368 | } 369 | PIMAGE_NT_HEADERS ntheader_target = RtlImageNtHeader(patch_header->TargetDllBase); 370 | if ( !ntheader_target ) 371 | { 372 | DbgPrintEx(85, 0, "Invalid target base address\n"); 373 | return 0xC000007B; 374 | } 375 | DWORD targetimagesize = ntheader_target->OptionalHeader.SizeOfImage; 376 | if ( HookArray->HookRva >= targetimagesize ) 377 | { 378 | DbgPrintEx(85, 0, "Invalid hotpatch hook pointer\n"); 379 | return 0xC000007B; 380 | } 381 | if ( HookArray->HookOptions & 0x8000 ) 382 | { 383 | size_t size1 = patch_header->TargetDllBase < patch_header->PatchImageBase? \ 384 | patch_header->PatchImageBase + ntheader_patch->OptionalHeader.SizeOfImage - patch_header->TargetDllBase :\ 385 | patch_header->TargetDllBase + targetimagesize - patch_header->PatchImageBase; 386 | if ( size1 > 0x80000000 ) 387 | { 388 | DbgPrintEx(85, 0, "Hotpatch loaded > 2GB from target image\n"); 389 | return 0xC0000018u; 390 | } 391 | } 392 | DWORD Hookaddr = HookArray->HookRva + (DWORD)patch_header->TargetDllBase; 393 | DWORD Hotpaddr = HookArray->HotpRva + (DWORD)patch_header->PatchImageBase; 394 | size_t size = 0; 395 | WORD options = 0; 396 | switch(HookArray->HookOptions) 397 | { 398 | case HOTP_Hook_VA32: 399 | *pSize = 4; 400 | if ( HookArray->HotpRva < ntheader_patch->OptionalHeader.SizeOfImage ) 401 | { 402 | if ( !pHotpAddr ) 403 | return 0; 404 | if ( flags1 >= 4 ) 405 | { 406 | *pHotpAddr = Hotpaddr; 407 | return 0; 408 | } 409 | return 0xC0000023u; 410 | } 411 | 412 | DbgPrintEx(85, 0, "Invalid hotpatch relative address\n"); 413 | return 0xC000007B; 414 | case HOTP_Hook_X86_JMP: 415 | options = HookArray->HookOptions & 0x1F; 416 | size = 5; 417 | if ( options > 5 ) 418 | size = options; 419 | *pSize = size; 420 | if ( HookArray->HotpRva < ntheader_patch->OptionalHeader.SizeOfImage ) 421 | { 422 | if ( !pHotpAddr ) 423 | return 0; 424 | if ( flags1 >= size ) 425 | { 426 | *pHotpAddr = 0xE9; //? 427 | *(pHotpAddr + 1) = Hotpaddr - Hookaddr - 5; 428 | if ( *pSize > 5 ) 429 | { //todo check it 430 | size_t v28 = *pSize - 5; 431 | DWORD* v29 = pHotpAddr + 5; 432 | do 433 | { 434 | *v29++ = -52; 435 | --v28; 436 | } 437 | while ( v28 ); 438 | } 439 | DbgPrintEx( 440 | 85, 441 | 2, 442 | "\t%08I64X: jmp %08X (PC+%08X) {", 443 | Hookaddr, 444 | Hookaddr >> 32, 445 | Hotpaddr, 446 | Hotpaddr - Hookaddr - 5); 447 | int index = 0; 448 | if ( *pSize ) 449 | { 450 | do{ 451 | // DbgPrintEx(85, 2, " %02X", *((DWORD)(index + Hookaddr))); 452 | index++; 453 | } 454 | while ( index < *pSize ); 455 | } 456 | DbgPrintEx(85, 2, " }\n"); 457 | return 0; 458 | } 459 | return 0xC0000023u; 460 | } 461 | DbgPrintEx(85, 0, "Invalid hotpatch relative address\n"); 462 | return 0xC000007B; 463 | case HOTP_Hook_X86_JMP2B: 464 | options = HookArray->HookOptions & 0x1F; 465 | size = options; 466 | if ( options <= 2 ) 467 | size = 2; 468 | *pSize = size; 469 | if ( !pHotpAddr ) 470 | return 0; 471 | if ( flags1 >= size ) 472 | {//todo: check what it means 473 | *pHotpAddr = 0xEB; //? 474 | *(pHotpAddr + 1) = HookArray->HotpRva & 0x0000FFFF; 475 | DWORD* v24 = pHotpAddr + 2; 476 | if ( *pSize > 2u ) 477 | { 478 | DWORD v25 = *pSize - 2; 479 | do 480 | { 481 | *v24++ = -52; 482 | --v25; 483 | } 484 | while ( v25 ); 485 | } 486 | return 0; 487 | } 488 | return 0xC0000023u; 489 | case HOTP_Hook_VA64: 490 | *pSize = 8; 491 | if ( !pHotpAddr ) 492 | return 0; 493 | if ( flags1 >= 8 ) 494 | { 495 | *pHotpAddr = Hotpaddr; 496 | return 0; 497 | } 498 | return 0xC0000023u; 499 | case HOTP_Hook_IA64_BRL: 500 | //TODO : not finished 501 | break; 502 | case HOTP_Hook_AMD64_IND: 503 | //TODO : not finished 504 | break; 505 | case HOTP_Hook_AMD64_CNT: 506 | //TODO : not finished 507 | break; 508 | default: 509 | DbgPrintEx(85, 0, "Invalid hook type specified\n"); 510 | return 0xC0000002u; 511 | } 512 | *pSize = 2; 513 | if ( !pHotpAddr ) 514 | return 0; 515 | if ( flags1 < 2 ) 516 | return 0xC0000023u; 517 | *pHotpAddr = HookArray->HotpRva & 0x0000FFFF; //low 4 byte 518 | return 0; 519 | } 520 | 521 | PIMAGE_SECTION_HEADER RtlpFindSectionHeader(PIMAGE_NT_HEADERS nt_header, void* section_name) 522 | { 523 | PIMAGE_SECTION_HEADER ret = NULL; 524 | PIMAGE_SECTION_HEADER section_start = (PIMAGE_SECTION_HEADER)(&nt_header->OptionalHeader + nt_header->FileHeader.SizeOfOptionalHeader); 525 | if ( nt_header->FileHeader.NumberOfSections <= 0 ) 526 | return NULL; 527 | for ( int i = 0; i < nt_header->FileHeader.NumberOfSections; i++) 528 | { 529 | 530 | if ( RtlCompareMemory(section_start, section_name, IMAGE_SIZEOF_SHORT_NAME) == IMAGE_SIZEOF_SHORT_NAME ) 531 | ret = section_start; 532 | else 533 | section_start += sizeof(IMAGE_SECTION_HEADER); 534 | } 535 | return ret; 536 | } 537 | 538 | 539 | HOTPATCH_HEADER *RtlGetHotpatchHeader(HANDLE module) 540 | { 541 | PIMAGE_NT_HEADERS nt_header = RtlImageNtHeader(module); 542 | PIMAGE_SECTION_HEADER section_start; 543 | HOTPATCH_HEADER* result = NULL; 544 | if( nt_header == NULL ) 545 | return NULL; 546 | section_start = (PIMAGE_SECTION_HEADER)RtlpFindSectionHeader(nt_header, ".hotp1 "); 547 | if ( section_start == 0 548 | || (result = (HOTPATCH_HEADER*)((DWORD)module + section_start->VirtualAddress), section_start->Misc.PhysicalAddress < 0x50) 549 | || result->Signature != HOTP_SIGNATURE 550 | || result->Version != HOTP_VERSION_1 ) 551 | result = NULL; 552 | return result; 553 | } -------------------------------------------------------------------------------- /patch1.h: -------------------------------------------------------------------------------- 1 | #ifndef PATCH_H 2 | #define PATCH_H 3 | 4 | #include 5 | #include "HotPatch.h" 6 | #include 7 | 8 | extern BOOLEAN RtlEqualUnicodeString( 9 | _In_ PCUNICODE_STRING String1, 10 | _In_ PCUNICODE_STRING String2, 11 | _In_ BOOLEAN CaseInSensitive 12 | ); 13 | 14 | extern PIMAGE_NT_HEADERS RtlImageNtHeader(HANDLE module); 15 | 16 | extern ULONG __cdecl DbgPrintEx( 17 | _In_ ULONG ComponentId, 18 | _In_ ULONG Level, 19 | _In_ PCSTR Format, 20 | ... 21 | ); 22 | 23 | 24 | 25 | NTSTATUS RtlCreateHotPatch(PRTL_PATCH_HEADER patch_header_out , //out 26 | PHOTPATCH_HEADER hotpatch_data , 27 | PLDR_DATA_TABLE_ENTRY LdrData, 28 | NTSTATUS Flags); 29 | 30 | NTSTATUS LdrpApplyHotPatch(PRTL_PATCH_HEADER patch_header, int flags); 31 | NTSTATUS LdrpSetupHotpatch(PRTL_PATCH_HEADER patch_header); 32 | NTSTATUS RtlInitializeHotPatch(PRTL_PATCH_HEADER patch_header, int flags); 33 | BOOLEAN RtlFreeHotPatchData(PRTL_PATCH_HEADER patch_header); 34 | NTSTATUS RtlReadHookInformation(PRTL_PATCH_HEADER patch_header); 35 | NTSTATUS RtlpSingleRangeValidate(PRTL_PATCH_HEADER patch_header, PHOTPATCH_VALIDATION valarray); 36 | NTSTATUS RtlpValidateTargetRanges(PRTL_PATCH_HEADER patch_header, bool flags); 37 | NTSTATUS RtlpReadSingleHookInformation(PRTL_PATCH_HEADER patch_header, HOTPATCH_HOOK* HookArray,int flags1, size_t* pSize, DWORD* pHotpAddr); 38 | PIMAGE_SECTION_HEADER RtlpFindSectionHeader(PIMAGE_NT_HEADERS nt_header, void* section_name); 39 | HOTPATCH_HEADER *RtlGetHotpatchHeader(HANDLE module); 40 | NTSTATUS RtlpValidateTargetRanges(PRTL_PATCH_HEADER patch_header, int flags); 41 | 42 | extern BOOLEAN RtlFreeHeap( 43 | _In_ PVOID HeapHandle, 44 | _In_opt_ ULONG Flags, 45 | _In_ PVOID HeapBase 46 | ); 47 | 48 | extern PVOID RtlAllocateHeap( 49 | _In_ PVOID HeapHandle, 50 | _In_opt_ ULONG Flags, 51 | _In_ SIZE_T Size 52 | ); 53 | 54 | 55 | NTSTATUS NtFreeVirtualMemory( 56 | _In_ HANDLE ProcessHandle, 57 | _Inout_ PVOID *BaseAddress, 58 | _Inout_ PSIZE_T RegionSize, 59 | _In_ ULONG FreeType 60 | ); 61 | 62 | 63 | typedef struct hotpatch_param{ 64 | SYSTEM_HOTPATCH_CODE_INFORMATION shci; 65 | UNICODE_STRING SourceName; 66 | UNICODE_STRING TargetName; 67 | } hotpatch_param; 68 | 69 | extern NTSYSAPI 70 | NTSTATUS 71 | NTAPI 72 | LdrLoadDll( 73 | IN PWCHAR PathToFile OPTIONAL, 74 | IN ULONG Flags OPTIONAL, 75 | IN PUNICODE_STRING ModuleFileName, 76 | OUT PHANDLE ModuleHandle ); 77 | 78 | 79 | NTSTATUS LdrHotPatchRoutine(hotpatch_param param); 80 | 81 | #endif PATCH_H --------------------------------------------------------------------------------