首页
社区
课程
招聘
[转帖]hotpatch的参考文档
发表于: 2007-11-10 09:05 11163

[转帖]hotpatch的参考文档

2007-11-10 09:05
11163
Document Version: 1

MSPatching
----------
- Purpose: To fix the existing (faulty) functions by replacing them with the fixed ones.
- System restart is not the only option when module to update is in use.

ColdPatching
------------
- replacing functions by replacing their containers - files and sections.
   An image to patch is "atomically replaced" with the image that contains all code and data that contains
the the original one plus the fixed functions and the redirections to them (the embedded hooks).
The functions to update are statically hooked and the hooks transfer the execution to the fixed functions
in '.text_CP' section of a coldpatch module. This section and the following '.DBG_POR' section were added
when creating the coldpatch module from the updated module sources. '.DBG_POR' section contains module
imports, exports and a debug information. The debug information for the coldpatch module usually consits
of two entries. The first entry is of CODEVIEW type, the second is RESERVED10. RESERVED10 data contains
a coldpatch debug information that is comprised of HOTPATCH_DEBUG_HEADER structure followed by
HOTPATCH_DEBUG_DATA structure. HOTPATCH_DEBUG_HEADER.Type has value DEBUG_SIGNATURE_COLDPATCH.
The contents of HOTPATCH_DEBUG_DATA are used in a process called 'target module validation' when the
validation of the original module fails and hotpatch checks if there is a coldpatch present.
   The atomic file replacement is realized by filling the SYSTEM_HOTPATCH_CODE_INFORMATION.RenameInfo
structure and calling SYSTEM_HOTPATCH_CODE_INFORMATION.Flags.HOTP_RENAME_FILES sub-function of
ExApplyCodePatch (SystemHotpatchInformation class of Nt/ZwSetSystemInformation) function.
HOTP_RENAME_FILES sub-function is not implemented in the newer OS versions/builds.
   Replacing the image on a volume doesn't mean that all the newly created processes will load/contain the
updated image. For the system purposes, security or for increasing module loading speed, a sections can be
emplyed in the process of the image loading. The section for a system module (ntdll.dll, ...) is updated by
HOTP_UPDATE_SYSDLL sub-function (no structure required). The section for the loader (from \KnownDlls object
directory) is updated by calling HOTP_UPDATE_KNOWNDLL with AtomicSwap sub-structure filled. The old object's
name is swapped with newly created temporary object (update.exe names the section 'ColdPatchInstallationInProgres')
in the object directory.

HotPatching
------------
- replacing functions by replacing their code in the memory. Available since Server 2003 SP0, XP SP2 x86,
ia64, x64.
   Functions were successfully fixed on the volume. Now they should be changed in the memory - in the kernel
memory for kernel modules or in the memory of user processes that contain the module to update. The functions
to patch are dynamically hooked - _one_ sufficiently long CPU instruction or data (pointer, RVA) of the function
to fix is replaced with a branch instruction (pointer, RVA) that redirects an execution flow to a fixed function
in the hotpatch module. After applying the hooks, the patched module in memory looks like the coldpatch module,
just the targets of the branch instructions do not lie within '.text_CP' section but in the code section(s) of
the hotpatch module.
   The hotpatch module may contain the debug information similar to the coldpatch's one, just RESERVED10 data
consists of HOTPATCH_DEBUG_HEADER only and HOTPATCH_DEBUG_HEADER.Type has value DEBUG_SIGNATURE_HOTPATCH.
   The hotpatch module must contain a section named '.hotp1   ' that is at least 80 bytes (sizeof(HOTPATCH_HEADER))
long and that must begin with a HOTPATCH_HEADER structure. The structure is used for validating the target
module, fixing relocations and creating intermediate RTL_PATCH_HEADER structure.
   When applying the hotpatch to a user module, an updating agent enumerates the processes and creates remote
threads into them that execute ntdll.LdrHotPatchRoutine. Newer OS versions/builds allow the remote thread creation
from the kernel mode when HOTP_INJECT_THREAD sub-function is called and InjectInfo sub-structure is correctly
filled.
   LdrHotPatchRoutine checks if HOTP_USE_MODULE flag is set and the target module, whose base name is specified
in UserModeInfo.TargetNameOffset, is present in the process. When applying the hotpatch to a kernel module,
(ntoskrnl.MmHotPatchRoutine) both HOTP_USE_MODULE and HOTP_KERNEL_MODULE flags must be set and KernelInfo
sub-structure must be filled.
   The Source (hotpatch) module is loaded and checked for the presence of '.hotp1   ' section,
HOTPATCH_HEADER.Signature and Version. If RTL_PATCH_HEADER for the source module already exists, hooks were
successfully applied and HOTP_PATCH_APPLY flag is clear, the hooks are removed. Otherwise RTL_PATCH_HEADER is
created, the target module whose name is in HOTPATCH_HEADER.TargetNameRva is checked for presence and validated
according to ModuleIdMethod using TargetModuleIdValue. If there's a validation mismatch, system checks whether
the target module is the coldpatch according to the coldpatch debug info. If it is the coldpatch,
PATCHFLAG_COLDPATCH_VALID flag is set in RTL_PATCH_HEADER.PatchFlags.
   The functions to fix may access the target image, they can call its functions and use its variables (it means
pointers and call and jump targets do not have to be in the hotpatch module because they point directly to the
target module). Such codes must be fixed using special relocation fixups from HOTPATCH_HEADER.FixupRgnRva with
respect to HOTPATCH_HEADER.OrigHotpBaseAddress and HOTPATCH_HEADER.OrigTargetBaseAddress. Then the functions
function as they would be called from the original module. Number of the HOTPATCH_FIXUP_ENTRY structures in the
HOTPATCH_FIXUP_REGION must be even number. If the hotpatch contains standard base relocations, they usually apply
only to a pointers to hotpatch's import table (APIs).
   Various places of the target module can be validated according to HOTPATCH_VALIDATION structures in
HOTPATCH_HEADER.ValidationArrayRva. Validations with option HOTP_Valid_Hook_Target are skipped (those are
the places to patch).
   HOTPATCH_HOOK_DESCRIPTOR structures are prepared according to HOTPATCH_HOOK structures in
HOTPATCH_HEADER.HookArrayRva. HOTPATCH_HOOK.HookOptions contain in their first 5 bits the length of the
instruction to replace and it must be at least as long as the length of the branch instruction - the rest is,
for some hook types, padded with bytes of value 0xCC.
   Again there's possibility to validate the bytes that will be replaced (HOTP_Valid_Hook_Target has now no
effect). If there's a mismatch and the patch place already contains the adequate branch instruction, a list of
RTL_PATCH_HEADER structures in TargetModule.LDR_DATA_TABLE_ENTRY.PatchInformation is traversed and bytes at
HOTPATCH_HOOK_DESCRIPTOR.CodeOffset are compared with the prepared branch instruction. If there's mismatch and
the target module is the coldpatch, the validation succeeds for some hook types, for the other ones is checked
whether the branch instruction points into the coldpatch.
   Upon succesfull validation and hook preparation are the remaining members of RTL_PATCH_HEADER filled in,
the sections of the target module are made writable and the hooks are written by calling ExApplyCodePatch with
RTL_PATCH_HEADER.CodeInfo and HOTP_PATCH flag set. If the patch application succeeds, RTL_PATCH_HEADER is linked
to TargetModule.LDR_DATA_TABLE_ENTRY.PatchInformation list.

* There's no security issue: Debug and LoadDriver privileges must be enabled for all Cold/HotPatch operations
   except for user mode hotpatching or when applying CodeInfo directly. CodeInfo cannot be directly applied to
   kernel when calling ExApplyCodePatch from user mode.
* CodeInfo is applied "os-atomically" - the preemption is unlikely.
* Function to fix doesn't have to be compiled (/linked) with /hotpatch (/functionpadmin) option.
* There's no public tool (special version of C compiler, linker?) for creating the cold/hotpatches. It is possible
   to write a tool that will add/write to '.hotp1   ' section of image created by normal compiling/linking but there
   are 2 problems: 1) How to write the new function with instructions pointing to target module and with this
   conjuncted 2) Fixup handling. Anyway, one doesn't have to use the target module functions/data so there's no
   need for the hotpatch fixups.

* Hook types
   HOTP_Hook_None

   HOTP_Hook_VA32
     32 bit value/pointer, 4 bytes

   HOTP_Hook_X86_JMP
     x86/64 long relative jump, E9 Rel32, <-2GB..2GB-1>,
     Rel32 constructed according to Hook/HotpRva,
     >= 5 bytes, padded with 0xCC

   HOTP_Hook_PCREL32
     not yet implemented,
     for fixing Rel32 of x86/64 call or jump, 4 bytes

   HOTP_Hook_X86_JMP2B
     x86/64 short relative jump, EB Rel8 <-128B..127B>,
     Rel8 is in HotpRva,
     >= 2 bytes, padded with 0xCC

   HOTP_Hook_VA64
     64 bit value/pointer, 8 bytes

   HOTP_Hook_IA64_BRL
     ia64 branch, at HookRva must be a supported template type
     >= 16 bytes

   HOTP_Hook_IA64_BR
     not yet implemented

   HOTP_Hook_AMD64_IND
     x86/64 absolute indirect jump,   FF 25 [Offset32 / Rip+Rel32]
     HotpRva (+Rip) must point to a variable that contains a pointer to fixed function,
     >= 6 bytes, padded with 0xCC

   HOTP_Hook_AMD64_CNT
     16bit value/pointer, 2 bytes

  
   Hook combinations are allowed - HOTP_Hook_X86_JMP2B + HOTP_Hook_X86_JMP is typical.
   When the distance hotpatch-target exceeds 2GB, HOTP_Hook_AMD64_IND must be employed on x86/64.
   One then needs a place to store the pointer specified in [Offset32 / Rip+Rel32]. For x86
   it can be inside the hotpach module but for x64 not. HOTP_Hook_AMD64_IND + HOTP_Hook_VA64 is
   the solution. /hotpatch option for x64 is not yet implemented but I would suggest:
   Buffer: //for HOTP_Hook_VA64
     8x nop
   FnStart:
     48 8D A4 24 00 00 00 00   lea rsp, [rsp + 0]   - 2 bytes more than required
    or
     0F 8x 00 00 00 00    j?? $+6 - as long as required but slower

   In Colpatch/After Hotpatching it could look like:
   Buffer:
     Ptr64FnContinue
   FnStart:
     FF 25 F2 FF FF FF   jmp qword ptr [Buffer] //[Rip-14]
     CC
     CC

   Of course there's possibility to make a triple patch: JMP2B -> IND -> VA64.

* x86 patch examples - function created with /hotpatch, "semi-hotpachable" function, "non-hotpatchable" function.
   You may notice there's replaced more than one CPU instruction (5x nop with long relative jmp) but the nops
   are not involved in the function - they serve as buffer.

Original function                  ColdPatch/After HotPatching         In Cold/HotPatch

5x 90          5x    nop             E9 Rel32       jmp   FnContinue       FnStart:
FnStart:                           FnStart:                            FnContinue:
8B FF          mov   edi, edi        EB F9          jmp   $-5              55             push ebp
55             push ebp             55             push ebp              8B EC          mov   ebp, esp
8B EC          mov   ebp, esp        8B EC          mov   ebp, esp         56             push esi
56             push esi             56             push esi              57             push edi
57             push edi             57             push edi              8B 35 g_Data   mov   esi, g_Data ;fixup required
8B 35 g_Data   mov   esi, g_Data     8B 35 g_Data   mov   esi, g_Data            

5x 90          5x    nop             E9 Rel32       jmp   FnContinue       FnStart:
FnStart:                           FnStart:                            55             push ebp
55             push ebp             55             push ebp              FnContinue:
8B EC          mov   ebp, esp        EB F8          jmp   $-6              8B EC          mov   ebp, esp
56             push esi             56             push esi              56             push esi
57             push edi             57             push edi              57             push edi
8B 35 g_Data   mov   esi, g_Data     8B 35 g_Data   mov   esi, g_Data      8B 35 g_Data   mov   esi, g_Data ;fixup required

FnStart:                           FnStart:                            FnStart:
55             push ebp             55             push ebp              55             push ebp
8B EC          mov   ebp, esp        8B EC          mov   ebp, esp         8B EC          mov   ebp, esp
56             push esi             56             push esi              56             push esi
57             push edi             57             push edi              57             push edi
8B 35 g_Data   mov   esi, g_Data     E9 Rel32       jmp   FnContinue       FnContinue:
                                   CC             int   3                8B 35 g_Data   mov   esi, g_Data ;fixup required

* Sources
- Inside Update.exe - 5e9K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3#2A6j5%4u0G2M7$3!0X3N6q4)9J5k6h3y4G2L8g2)9J5c8Y4c8W2j5$3S2F1k6i4c8Q4x3V1k6H3M7X3!0V1N6r3g2U0K9r3&6G2L8q4)9J5c8Y4N6A6L8X3c8G2N6%4y4K6k6i4u0$3k6i4t1J5x3o6l9K6i4K6u0r3k6r3g2H3L8r3!0&6L8h3g2F1N6q4)9J5c8Y4N6A6L8Y4g2H3k6s2c8W2i4K6u0W2L8i4y4H3P5l9`.`.
- KB packages for Server2003 x86 that contain the cold/hotpatches:
   819696, 823182, 888113, 893086, 899588, 901190

==============================================

(原文转载)

Throwing a Windows server off track isn't as easy as it used to be, but patching a Windows Server 2003 can still often require a reboot. Save yourself trouble and time by stopping processes with hotpatching.

In the early days, it seemed like breathing on a Windows server resulted in the need for an administrator to reboot the server. Over the years, Microsoft has made great strides in reducing the number of reboots necessary to manage a Windows server, including Windows Server 2003. However, patching a Windows server can still result in a required reboot, thus dashing the "the five nines" goal of many organizations (i.e., 99.999 percent availability). Enter hotpatching.

Although hotpatching will not completely eliminate server reboots, the services provide a mechanism to update system files without rebooting and without stopping services and processes. Hotpatching has some limitations, which include:

    * Hotpatching currently works only on 32-bit versions of Windows.
    * Hotpatching has some compatibility issues with some non-Microsoft applications. See Microsoft Knowledge Base article 922612 for more information.

A hotpatch contains two versions of an update -- what Microsoft calls a "cold patch" and a "hot patch" bits. You can hotpatch a file by following this three-step process:

   1. The coldpatch portion of the update replaces the old binary file.
   2. The hotpatch portion of the update is then loaded into the image of the defective binary file.
   3. An instruction above the defective function is inserted, which redirects subsequent calls to the updated function

Microsoft Hotpatching Beta

a2aK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3#2K6j5X3I4G2k6#2)9J5k6h3!0J5k6#2)9J5c8X3W2F1k6r3g2^5i4K6u0W2M7r3S2H3i4K6u0r3x3U0l9H3y4W2)9J5c8U0l9K6i4K6u0r3x3U0N6Q4x3V1k6E0K9h3y4J5L8%4y4G2k6Y4c8Q4x3X3c8Z5L8%4c8H3j5i4c8Z5j5$3W2F1k6#2)9J5k6r3u0W2N6r3q4Q4x3V1j5`.
Lately, I have been playing with the new Microsoft hotpatch technology and my job consists on deploying hotpatch enabled fixes on test systems.    The hotpatching technology is intended to eliminate system downtime when installing critical security fixes onto systems. Currently this technology is available on 32-bit versions of Windows Server 2003 SP1. The idea is to extend support for the X64 and Itanium platforms. Hotpatching technology is planned to be part of Longhorn Sever and Vista SP1. Unfortunately this technology has its limitations; hotpatching cannot be applied to fixes that update the following components of the Windows OS:      

Win32k.sys: (kernel mode)

·           Exports windows “native” entry points

·           Implements Windows User & GDI    “native” functions; calls routines in GDI drivers

Ntoskrnl.exe: executive and kernel (both are in kernel mode)

The Executive includes:

·           base operating system services

·           memory management, process and thread management

·           security, I/O, interprocess communication

The kernel includes:

·           low-level operating system functions

·           thread scheduling, interrupt and exception dispatching

·           multiprocessor synchronization

·           provides a set of routines and basic objects that the rest of the executive uses

            to implement higher-level constructs

Both are contained in file Ntoskrnl.exe

Kernel32.dll: One of the WINAPI DLLs (user mode)

·           Exports the APIs defined by the subsystem

Managed code (user mode)

According to Microsoft this is how a hotpatch package works:

The hotpatch package contains coldpatch and hotpatch binaries for the fix. The hotpatch binary only contains the updated function, function that needs to change to address critical OS flaw. The updated function, as a hotpatch binary, gets inserted into the loaded image of the defective binary. A jump instruction is inserted above the defective function to redirect all subsequent calls to the updated function.

The coldpatch contains the old binary with the fixed function appended to it and a jump instruction instrumented bypassing the flawed function to the fixed function. Hotpatch application addresses currently running instances of the critical flaws in all the process and the complementing cold patch secures the new instances of the process and persists the patch beyond reboot.

Thus the package containing a hotpatch enabled fix will have two binaries related to file being serviced. One with the “.hp.” in its name is the hotpatch binary and the other one is the coldpatch binary.

实例:
KSPIN_LOCK SDTSpinLock;
void WPOFF();
VOID WPON();
ULONG g_uCr0 = 0;

void WPOFF()
{
   
    ULONG uAttr;
   
    _asm
    {
        push eax;
        mov eax, cr0;
        mov uAttr, eax;
        and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
        mov cr0, eax;
        pop eax;
        cli
    };
   
    g_uCr0 = uAttr; //保存原有的 CRO 屬性
   
}

VOID WPON()
{
   
    _asm
    {
        sti
            push eax;
        mov eax, g_uCr0; //恢復原有 CR0 屬性
        mov cr0, eax;
        pop eax;
    };
   
}
NTSTATUS InlineHookFuncXP(IN PVOID FuncAddress,
                         IN PVOID NewFuncAddress)
{
//FuncAddress:orignal function address
//NewFuncAddress:new function address to hook
//if function successed,the old function which the hook function will jump to
//is the FuncAddress+2

KIRQL OldIrql ;
NTSTATUS stat;

    KeAcquireSpinLock( &SDTSpinLock, &OldIrql );

    WPOFF();
    //进dpc

    __asm
    {
        push eax
        push ecx
        lea eax,[FuncAddress]
        mov eax,[eax]
        cmp byte ptr[eax],0x8b
        jnz failtohook
        cmp byte ptr[eax+1],0xff
        jnz failtohook
        mov ecx,0xffffffff
loopcheck:
        cmp byte ptr[eax+ecx],0x90
        jnz failtohook
        dec ecx
        cmp ecx,0xfffffffa
        jnz loopcheck
      
        ;check function header if "mov edi,edi"
        mov byte ptr[eax],0xeb
        mov byte ptr[eax+1],0xf9
        ;write the new function header:jmp short funcaddr-5(0x00-0x07)
        mov byte ptr[eax-5],0xe9
        ;write 1 byte :jmp xxxxx
        mov ecx,[NewFuncAddress]
        sub ecx,eax
        mov dword ptr[eax-4],ecx
        jmp hookok
failtohook:
        mov stat,0xc0000001
        jmp end
hookok:
        mov stat,0
end:
        pop ecx
        pop eax

    }
    WPON();
            KeReleaseSpinLock( &SDTSpinLock, OldIrql );

    return stat;
}

[培训]科锐逆向工程师培训第53期2025年7月8日开班!

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
2
这个要顶~~ 目前过主动地相对完美方法。
2007-11-11 16:57
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
好东西 学习!
2007-11-11 18:21
0
游客
登录 | 注册 方可回帖
返回