Removing kernel patching on the fly with the kernel debugger

Occasionally, you may find yourself in a situation where you need to “un-patch” the kernel in order to make forward progress with investigating a problem. This has often been the case with me and certain unnamed anti-virus programs that have the misguided intention to prevent the computer administrator from administering their computer, by denying everyone access to certain protected processes.

Normally, this is done by the use of a kernel driver that hooks various kernel system calls and prevents usermode from being able to access a protected process. While this may be done in the name of preventing malware from interfering with anti-virus software, it also has the unfortunate side effect of preventing legitimate troubleshooting of software issues.

Fortunately, with WinDbg installed and a little knowledge of the debugger, it is easy to reverse these abusive kernel patches that undermine the ability of a system administrator to do his or her job.

Now, normally, you might think that one would be stuck reverse engineering large sections of code in order to disable such kinds of protection mechanisms. However, in the vast majority of cases like these, you can simply have the kernel debugger perform a comparison of the kernel memory image with the image retrieved from the symbol server, and fix up any differences (accounting for relocations). This may be done with the !chkimg -f nt command. Using !chkimg in this fashion allows you to quickly remove unwanted kernel patches without having to dig through third party code that has injected itself into the system.

If you are feeling particularly adventurerous, you can even do this in local kernel debugger mode on Windows XP or later, without having to boot the system with /DEBUG. Be warned that this does carry an inherent race condition, though very unlikely in most cases with system service patching, that you might crash the system if someone makes a call to one of the regions of the kernel that you are unpatching while the kernel is being restored to its pristine state.

You should also be aware that depending on how the third party software that has patched the kernel is written, removing the patches out from under it may have varying negative side effects; be careful. As a result, if you are working on a critical or production system, you may want to pick a different approach. If you are just working on a throw-away repro environment in a VM, though, this can be a good quick-n-dirty way to get the job done.

Despite these potential problems, I’ve successfully used this trick in a pinch several times successfully. If you are running into a brick wall with debugging malfunctioning anti-virus software interactions with your product because of anti-debug protection mechanisms, you might give this technique a try.

One Response to “Removing kernel patching on the fly with the kernel debugger”

  1. weiss says:

    Hi Skywing.

    I had problems using this method. First i check a shadow
    copy of the SDT with current system.(using command from your article about KAV)
    Then, !chkimg -f nt, which detects errors, but is unable to fix them.

    How can i resolve this?
    thanks in advance & keep digging!

    Kevin

    Microsoft (R) Windows Debugger Version 6.5.0003.7
    Copyright (c) Microsoft Corporation. All rights reserved.

    Unable to read head of debugger data list
    Connected to Windows XP 2600 x86 compatible target, ptr64 FALSE
    Symbol search path is: G:\WINDOWS\Symbols
    Executable search path is: G:\WINDOWS;G:\WINDOWS\system32
    *******************************************************************************
    WARNING: Local kernel debugging requires booting with /debug to work optimally.
    *******************************************************************************
    Windows XP Kernel Version 2600 (Service Pack 2) UP Free x86 compatible
    Product: WinNt, suite: TerminalServer SingleUserTS
    Built by: 2600.xpsp_sp2_rtm.040803-2158
    Kernel base = 0x80800000 PsLoadedModuleList = 0x8087c1a0
    Debug session time: Fri Nov 10 15:04:27.375 2006 (GMT+0)
    System Uptime: 0 days 0:01:07.968

    lkd> dps poi ( nt!KeServiceDescriptorTableShadow ) l dwo ( nt!KeServiceDescriptorTableShadow + 8 )

    8082a030 808c149a nt!NtAcceptConnectPort
    8082a034 8090e666 nt!NtAccessCheck
    8082a038 80911ec4 nt!NtAccessCheckAndAuditAlarm
    8082a03c 8090e698 nt!NtAccessCheckByType
    8082a040 80911efe nt!NtAccessCheckByTypeAndAuditAlarm
    8082a044 8090e6ce nt!NtAccessCheckByTypeResultList
    8082a048 80911f42 nt!NtAccessCheckByTypeResultListAndAuditAlarm
    8082a04c 80911f86 nt!NtAccessCheckByTypeResultListAndAuditAlarmByHandle
    8082a050 809335da nt!NtAddAtom
    8082a054 8093484e nt!NtQueryBootOptions
    8082a058 80909a08 nt!NtAdjustGroupsToken
    8082a05c 80909660 nt!NtAdjustPrivilegesToken
    8082a060 808f2684 nt!NtAlertResumeThread
    8082a064 808f2634 nt!NtAlertThread
    8082a068 80933c00 nt!NtAllocateLocallyUniqueId
    8082a06c 808d3088 nt!NtAllocateUserPhysicalPages
    8082a070 80933218 nt!NtAllocateUuids
    8082a074 808c5910 nt!NtAllocateVirtualMemory
    8082a078 808cd4da nt!NtAreMappedFilesTheSame
    8082a07c 808f4162 nt!NtAssignProcessToJobObject
    8082a080 80827d04 nt!NtCallbackReturn
    8082a084 808e5e0e nt!NtModifyBootEntry
    8082a088 80893be6 nt!NtCancelIoFile
    8082a08c 8085d1dc nt!NtCancelTimer
    8082a090 8092c8ea nt!NtClearEvent
    8082a094 808d9714 nt!NtClose
    8082a098 809123fe nt!NtCloseObjectAuditAlarm
    8082a09c 809417a2 nt!NtCompactKeys
    8082a0a0 809168f0 nt!NtCompareTokens
    8082a0a4 808c1b88 nt!NtCompleteConnectPort
    8082a0a8 809419f6 nt!NtCompressKey
    8082a0ac 808c143a nt!NtConnectPort
    8082a0b0 80868fd0 nt!NtContinue
    8082a0b4 8095f9e8 nt!NtCreateDebugObject
    8082a0b8 808db610 nt!NtCreateDirectoryObject
    8082a0bc 8092c93a nt!NtCreateEvent
    8082a0c0 80934b94 nt!NtCreateEventPair
    8082a0c4 8089614c nt!NtCreateFile
    8082a0c8 808949de nt!NtCreateIoCompletion
    8082a0cc 808f3126 nt!NtCreateJobObject
    8082a0d0 808f2e5e nt!NtCreateJobSet
    8082a0d4 b9edbc04
    8082a0d8 8089625a nt!NtCreateMailslotFile
    8082a0dc 80934f8c nt!NtCreateMutant
    8082a0e0 80896186 nt!NtCreateNamedPipeFile
    8082a0e4 808c88fa nt!NtCreatePagingFile
    8082a0e8 808c1f56 nt!NtCreatePort
    8082a0ec 808eece8 nt!NtCreateProcess
    8082a0f0 808eec32 nt!NtCreateProcessEx
    8082a0f4 809353ac nt!NtCreateProfile
    8082a0f8 808c823e nt!NtCreateSection
    8082a0fc 80932936 nt!NtCreateSemaphore
    8082a100 808e2410 nt!NtCreateSymbolicLinkObject
    8082a104 808eead0 nt!NtCreateThread
    8082a108 8093485c nt!NtCreateTimer
    8082a10c 80916c98 nt!NtCreateToken
    8082a110 808c1f7a nt!NtCreateWaitablePort
    8082a114 80960ac4 nt!NtDebugActiveProcess
    8082a118 80960c14 nt!NtDebugContinue
    8082a11c 8093426e nt!NtDelayExecution
    8082a120 80933a90 nt!NtDeleteAtom
    8082a124 808e5e0e nt!NtModifyBootEntry
    8082a128 80893d2c nt!NtDeleteFile
    8082a12c 80942062 nt!NtDeleteKey
    8082a130 8091250a nt!NtDeleteObjectAuditAlarm
    8082a134 80942232 nt!NtDeleteValueKey
    8082a138 80896312 nt!NtDeviceIoControlFile
    8082a13c 809308aa nt!NtDisplayString
    8082a140 808db1f0 nt!NtDuplicateObject
    8082a144 8090a8a6 nt!NtDuplicateToken
    8082a148 8093484e nt!NtQueryBootOptions
    8082a14c b9edbd48
    8082a150 80934310 nt!NtEnumerateSystemEnvironmentValuesEx
    8082a154 b9edc0c0
    8082a158 808d0c00 nt!NtExtendSection
    8082a15c 8090aa52 nt!NtFilterToken
    8082a160 80933844 nt!NtFindAtom
    8082a164 80893df8 nt!NtFlushBuffersFile
    8082a168 808d3912 nt!NtFlushInstructionCache
    8082a16c 809428e6 nt!NtFlushKey
    8082a170 808c960a nt!NtFlushVirtualMemory
    8082a174 808d38b4 nt!NtFlushWriteBuffer
    8082a178 808d3424 nt!NtFreeUserPhysicalPages
    8082a17c 808cfeda nt!NtFreeVirtualMemory
    8082a180 80896346 nt!NtFsControlFile
    8082a184 808eefe2 nt!NtGetContextThread
    8082a188 808e5e30 nt!NtGetDevicePowerState
    8082a18c 808b631e nt!NtGetPlugPlayEvent
    8082a190 80845c4e nt!NtGetWriteWatch
    8082a194 809165e4 nt!NtImpersonateAnonymousToken
    8082a198 808c1fe4 nt!NtImpersonateClientOfPort
    8082a19c 808f52fa nt!NtImpersonateThread
    8082a1a0 8093fbaa nt!NtInitializeRegistry
    8082a1a4 808e5c08 nt!NtInitiatePowerAction
    8082a1a8 808f2d22 nt!NtIsProcessInJob
    8082a1ac 808e5e1c nt!NtIsSystemResumeAutomatic
    8082a1b0 808c21f0 nt!NtListenPort
    8082a1b4 808a132a nt!NtLoadDriver
    8082a1b8 80943902 nt!NtLoadKey
    8082a1bc 8094354c nt!NtLoadKey2
    8082a1c0 8089637a nt!NtLockFile
    8082a1c4 80930e0c nt!NtLockProductActivationKeys
    8082a1c8 80941aa2 nt!NtLockRegistryKey
    8082a1cc 808d3a1a nt!NtLockVirtualMemory
    8082a1d0 808dca90 nt!NtMakePermanentObject
    8082a1d4 808d97b8 nt!NtMakeTemporaryObject
    8082a1d8 808d237c nt!NtMapUserPhysicalPages
    8082a1dc 808d2954 nt!NtMapUserPhysicalPagesScatter
    8082a1e0 808cef5a nt!NtMapViewOfSection
    8082a1e4 808e5e0e nt!NtModifyBootEntry
    8082a1e8 80896faa nt!NtNotifyChangeDirectoryFile
    8082a1ec 809438cc nt!NtNotifyChangeKey
    8082a1f0 809429e8 nt!NtNotifyChangeMultipleKeys
    8082a1f4 808db6e2 nt!NtOpenDirectoryObject
    8082a1f8 8092ca3a nt!NtOpenEvent
    8082a1fc 80934c6c nt!NtOpenEventPair
    8082a200 8089726a nt!NtOpenFile
    8082a204 80894ab6 nt!NtOpenIoCompletion
    8082a208 808f32ac nt!NtOpenJobObject
    8082a20c b9edbae2
    8082a210 80935064 nt!NtOpenMutant
    8082a214 80911fcc nt!NtOpenObjectAuditAlarm
    8082a218 808e8b78 nt!NtOpenProcess
    8082a21c 8090b29e nt!NtOpenProcessToken
    8082a220 8090aea4 nt!NtOpenProcessTokenEx
    8082a224 808c7274 nt!NtOpenSection
    8082a228 80932a30 nt!NtOpenSemaphore
    8082a22c 808e25f6 nt!NtOpenSymbolicLinkObject
    8082a230 808e8e04 nt!NtOpenThread
    8082a234 8090b2bc nt!NtOpenThreadToken
    8082a238 8090b014 nt!NtOpenThreadTokenEx
    8082a23c 8093497e nt!NtOpenTimer
    8082a240 80962cb6 nt!NtPlugPlayControl
    8082a244 808e6c64 nt!NtPowerInformation
    8082a248 80915696 nt!NtPrivilegeCheck
    8082a24c 809112de nt!NtPrivilegeObjectAuditAlarm
    8082a250 809114ca nt!NtPrivilegedServiceAuditAlarm
    8082a254 808d54e2 nt!NtProtectVirtualMemory
    8082a258 8092caf2 nt!NtPulseEvent
    8082a25c 80893fde nt!NtQueryAttributesFile
    8082a260 8093484e nt!NtQueryBootOptions
    8082a264 8093484e nt!NtQueryBootOptions
    8082a268 80864206 nt!NtQueryDebugFilterState
    8082a26c 8092e65e nt!NtQueryDefaultLocale
    8082a270 8092f2be nt!NtQueryDefaultUILanguage
    8082a274 80896f44 nt!NtQueryDirectoryFile
    8082a278 808db782 nt!NtQueryDirectoryObject
    8082a27c 8089729a nt!NtQueryEaFile
    8082a280 8092cbba nt!NtQueryEvent
    8082a284 80894116 nt!NtQueryFullAttributesFile
    8082a288 80933ab8 nt!NtQueryInformationAtom
    8082a28c 80897b16 nt!NtQueryInformationFile
    8082a290 808f377e nt!NtQueryInformationJobObject
    8082a294 808c224e nt!NtQueryInformationPort
    8082a298 808ea4de nt!NtQueryInformationProcess
    8082a29c 808e90aa nt!NtQueryInformationThread
    8082a2a0 8090b39c nt!NtQueryInformationToken
    8082a2a4 8092ea5c nt!NtQueryInstallUILanguage
    8082a2a8 8093582e nt!NtQueryIntervalProfile
    8082a2ac 80894b5e nt!NtQueryIoCompletion
    8082a2b0 b9edc18a
    8082a2b4 80940da0 nt!NtQueryMultipleValueKey
    8082a2b8 8093510c nt!NtQueryMutant
    8082a2bc 808e1ad8 nt!NtQueryObject
    8082a2c0 80941406 nt!NtQueryOpenSubKeys
    8082a2c4 809358bc nt!NtQueryPerformanceCounter
    8082a2c8 80898960 nt!NtQueryQuotaInformationFile
    8082a2cc 808d56a4 nt!NtQuerySection
    8082a2d0 808dd45c nt!NtQuerySecurityObject
    8082a2d4 80932ae8 nt!NtQuerySemaphore
    8082a2d8 808e2696 nt!NtQuerySymbolicLinkObject
    8082a2dc 8093432c nt!NtQuerySystemEnvironmentValue
    8082a2e0 80934302 nt!NtSetSystemEnvironmentValueEx
    8082a2e4 8092f33e nt!NtQuerySystemInformation
    8082a2e8 809311c0 nt!NtQuerySystemTime
    8082a2ec 80934a36 nt!NtQueryTimer
    8082a2f0 80930a78 nt!NtQueryTimerResolution
    8082a2f4 b9edc022
    8082a2f8 808d5d2a nt!NtQueryVirtualMemory
    8082a2fc 80898e50 nt!NtQueryVolumeInformationFile
    8082a300 808eed2e nt!NtQueueApcThread
    8082a304 80869018 nt!NtRaiseException
    8082a308 8093275a nt!NtRaiseHardError
    8082a30c 80899618 nt!NtReadFile
    8082a310 80899ba6 nt!NtReadFileScatter
    8082a314 808c2cd6 nt!NtReadRequestData
    8082a318 808d11ec nt!NtReadVirtualMemory
    8082a31c 808f027e nt!NtRegisterThreadTerminatePort
    8082a320 80935244 nt!NtReleaseMutant
    8082a324 80932c18 nt!NtReleaseSemaphore
    8082a328 80894e56 nt!NtRemoveIoCompletion
    8082a32c 80960b94 nt!NtRemoveProcessDebug
    8082a330 809415f8 nt!NtRenameKey
    8082a334 809437b2 nt!NtReplaceKey
    8082a338 808c2356 nt!NtReplyPort
    8082a33c 808c331e nt!NtReplyWaitReceivePort
    8082a340 808c2d26 nt!NtReplyWaitReceivePortEx
    8082a344 808c2640 nt!NtReplyWaitReplyPort
    8082a348 808e5da0 nt!NtRequestDeviceWakeup
    8082a34c 808bf8b4 nt!NtRequestPort
    8082a350 808bfbe0 nt!NtRequestWaitReplyPort
    8082a354 808e5bae nt!NtRequestWakeupLatency
    8082a358 8092cccc nt!NtResetEvent
    8082a35c 8084612e nt!NtResetWriteWatch
    8082a360 8093ffda nt!NtRestoreKey
    8082a364 808f25de nt!NtResumeProcess
    8082a368 808f24c0 nt!NtResumeThread
    8082a36c 8094007c nt!NtSaveKey
    8082a370 8094010c nt!NtSaveKeyEx
    8082a374 809401d8 nt!NtSaveMergedKeys
    8082a378 808c0bce nt!NtSecureConnectPort
    8082a37c 8093484e nt!NtQueryBootOptions
    8082a380 8093484e nt!NtQueryBootOptions
    8082a384 808ef1f2 nt!NtSetContextThread
    8082a388 8096384c nt!NtSetDebugFilterState
    8082a38c 80932604 nt!NtSetDefaultHardErrorPort
    8082a390 8092e7ae nt!NtSetDefaultLocale
    8082a394 8092f020 nt!NtSetDefaultUILanguage
    8082a398 808977b6 nt!NtSetEaFile
    8082a39c 8092cd8c nt!NtSetEvent
    8082a3a0 8092ce56 nt!NtSetEventBoostPriority
    8082a3a4 80934f28 nt!NtSetHighEventPair
    8082a3a8 80934e58 nt!NtSetHighWaitLowEventPair
    8082a3ac 8096055e nt!NtSetInformationDebugObject
    8082a3b0 8089811a nt!NtSetInformationFile
    8082a3b4 808f448e nt!NtSetInformationJobObject
    8082a3b8 8094096c nt!NtSetInformationKey
    8082a3bc 808e0f1c nt!NtSetInformationObject
    8082a3c0 808eb636 nt!NtSetInformationProcess
    8082a3c4 808e95f6 nt!NtSetInformationThread
    8082a3c8 80917a12 nt!NtSetInformationToken
    8082a3cc 80935390 nt!NtSetIntervalProfile
    8082a3d0 80894df4 nt!NtSetIoCompletion
    8082a3d4 808f140a nt!NtSetLdtEntries
    8082a3d8 80934ec4 nt!NtSetLowEventPair
    8082a3dc 80934dec nt!NtSetLowWaitHighEventPair
    8082a3e0 8089893e nt!NtSetQuotaInformationFile
    8082a3e4 808dd390 nt!NtSetSecurityObject
    8082a3e8 809345b0 nt!NtSetSystemEnvironmentValue
    8082a3ec 80934302 nt!NtSetSystemEnvironmentValueEx
    8082a3f0 8092d68c nt!NtSetSystemInformation
    8082a3f4 8096fde8 nt!NtSetSystemPowerState
    8082a3f8 80931d80 nt!NtSetSystemTime
    8082a3fc 808e5ac2 nt!NtSetThreadExecutionState
    8082a400 8085d318 nt!NtSetTimer
    8082a404 80931252 nt!NtSetTimerResolution
    8082a408 809330ce nt!NtSetUuidSeed
    8082a40c b9edc212
    8082a410 80899274 nt!NtSetVolumeInformationFile
    8082a414 8093086e nt!NtShutdownSystem
    8082a418 8084aed6 nt!NtSignalAndWaitForSingleObject
    8082a41c 809355da nt!NtStartProfile
    8082a420 80935784 nt!NtStopProfile
    8082a424 808f2588 nt!NtSuspendProcess
    8082a428 808f23fa nt!NtSuspendThread
    8082a42c 809359a8 nt!NtSystemDebugControl
    8082a430 808f4ff8 nt!NtTerminateJobObject
    8082a434 808f04c8 nt!NtTerminateProcess
    8082a438 808f06c2 nt!NtTerminateThread
    8082a43c 808f2748 nt!NtTestAlert
    8082a440 808599e4 nt!NtTraceEvent
    8082a444 8093431e nt!NtTranslateFilePath
    8082a448 808a14be nt!NtUnloadDriver
    8082a44c 8094055a nt!NtUnloadKey
    8082a450 80940748 nt!NtUnloadKeyEx
    8082a454 80896726 nt!NtUnlockFile
    8082a458 808d3fa8 nt!NtUnlockVirtualMemory
    8082a45c 808cfd70 nt!NtUnmapViewOfSection
    8082a460 80918dca nt!NtVdmControl
    8082a464 809602c6 nt!NtWaitForDebugEvent
    8082a468 808ddac8 nt!NtWaitForMultipleObjects
    8082a46c 808dd9de nt!NtWaitForSingleObject
    8082a470 80934d88 nt!NtWaitHighEventPair
    8082a474 80934d24 nt!NtWaitLowEventPair
    8082a478 8089a0b6 nt!NtWriteFile
    8082a47c 8089a6c6 nt!NtWriteFileGather
    8082a480 808c2cfe nt!NtWriteRequestData
    8082a484 808d12f6 nt!NtWriteVirtualMemory
    8082a488 8082a6d0 nt!NtYieldExecution
    8082a48c 80935e00 nt!NtCreateKeyedEvent
    8082a490 80935eea nt!NtOpenKeyedEvent
    8082a494 80935f9c nt!NtReleaseKeyedEvent
    8082a498 80936228 nt!NtWaitForKeyedEvent
    8082a49c 808e907a nt!NtQueryPortInformationProcess

    lkd> !chkimg -f nt

    Warning: Any detected errors will be fixed to what we expect!
    Unable to write expected value at: 8082a0d4
    Unable to write expected value at: 8082a0d5
    Unable to write expected value at: 8082a0d6
    Unable to write expected value at: 8082a0d7
    Unable to write expected value at: 8082a14c
    Unable to write expected value at: 8082a14d
    Unable to write expected value at: 8082a14e
    Unable to write expected value at: 8082a14f
    Unable to write expected value at: 8082a154
    Unable to write expected value at: 8082a155
    Unable to write expected value at: 8082a156
    Unable to write expected value at: 8082a157
    Unable to write expected value at: 8082a20c
    Unable to write expected value at: 8082a20d
    Unable to write expected value at: 8082a20e
    Unable to write expected value at: 8082a20f
    Unable to write expected value at: 8082a2b0
    Unable to write expected value at: 8082a2b1
    Unable to write expected value at: 8082a2b2
    Unable to write expected value at: 8082a2b3
    Unable to write expected value at: 8082a2f4
    Unable to write expected value at: 8082a2f5
    Unable to write expected value at: 8082a2f6
    Unable to write expected value at: 8082a2f7
    Unable to write expected value at: 8082a40c
    Unable to write expected value at: 8082a40d
    Unable to write expected value at: 8082a40e
    Unable to write expected value at: 8082a40f
    28 errors (fixed): nt (8082a0d4-8082a40f)