Created
July 5, 2011 09:41
-
-
Save ksose/1064568 to your computer and use it in GitHub Desktop.
Detect SSDT hooks from user-mode in python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# k`sOSe - detect SSDT hooks | |
import ctypes | |
import struct | |
from ctypes.wintypes import * | |
from ctypes import windll | |
SYSCALLS = [ | |
"NtAcceptConnectPort", | |
"NtAccessCheck", | |
"NtAccessCheckAndAuditAlarm", | |
"NtAccessCheckByType", | |
"NtAccessCheckByTypeAndAuditAlarm", | |
"NtAccessCheckByTypeResultList", | |
"NtAccessCheckByTypeResultListAndAuditAlarm", | |
"NtAccessCheckByTypeResultListAndAuditAlarmByHandle", | |
"NtAddAtom", | |
"NtQueryBootOptions", | |
"NtAdjustGroupsToken", | |
"NtAdjustPrivilegesToken", | |
"NtAlertResumeThread", | |
"NtAlertThread", | |
"NtAllocateLocallyUniqueId", | |
"NtAllocateUserPhysicalPages", | |
"NtAllocateUuids", | |
"NtAllocateVirtualMemory", | |
"NtAreMappedFilesTheSame", | |
"NtAssignProcessToJobObject", | |
"NtCallbackReturn", | |
"NtModifyBootEntry", | |
"NtCancelIoFile", | |
"NtCancelTimer", | |
"NtClearEvent", | |
"NtClose", | |
"NtCloseObjectAuditAlarm", | |
"NtCompactKeys", | |
"NtCompareTokens", | |
"NtCompleteConnectPort", | |
"NtCompressKey", | |
"NtConnectPort", | |
"NtContinue", | |
"NtCreateDebugObject", | |
"NtCreateDirectoryObject", | |
"NtCreateEvent", | |
"NtCreateEventPair", | |
"NtCreateFile", | |
"NtCreateIoCompletion", | |
"NtCreateJobObject", | |
"NtCreateJobSet", | |
"NtCreateKey", | |
"NtCreateMailslotFile", | |
"NtCreateMutant", | |
"NtCreateNamedPipeFile", | |
"NtCreatePagingFile", | |
"NtCreatePort", | |
"NtCreateProcess", | |
"NtCreateProcessEx", | |
"NtCreateProfile", | |
"NtCreateSection", | |
"NtCreateSemaphore", | |
"NtCreateSymbolicLinkObject", | |
"NtCreateThread", | |
"NtCreateTimer", | |
"NtCreateToken", | |
"NtCreateWaitablePort", | |
"NtDebugActiveProcess", | |
"NtDebugContinue", | |
"NtDelayExecution", | |
"NtDeleteAtom", | |
"NtModifyBootEntry", | |
"NtDeleteFile", | |
"NtDeleteKey", | |
"NtDeleteObjectAuditAlarm", | |
"NtDeleteValueKey", | |
"NtDeviceIoControlFile", | |
"NtDisplayString", | |
"NtDuplicateObject", | |
"NtDuplicateToken", | |
"NtQueryBootOptions", | |
"NtEnumerateKey", | |
"NtEnumerateSystemEnvironmentValuesEx", | |
"NtEnumerateValueKey", | |
"NtExtendSection", | |
"NtFilterToken", | |
"NtFindAtom", | |
"NtFlushBuffersFile", | |
"NtFlushInstructionCache", | |
"NtFlushKey", | |
"NtFlushVirtualMemory", | |
"NtFlushWriteBuffer", | |
"NtFreeUserPhysicalPages", | |
"NtFreeVirtualMemory", | |
"NtFsControlFile", | |
"NtGetContextThread", | |
"NtGetDevicePowerState", | |
"NtGetPlugPlayEvent", | |
"NtGetWriteWatch", | |
"NtImpersonateAnonymousToken", | |
"NtImpersonateClientOfPort", | |
"NtImpersonateThread", | |
"NtInitializeRegistry", | |
"NtInitiatePowerAction", | |
"NtIsProcessInJob", | |
"NtIsSystemResumeAutomatic", | |
"NtListenPort", | |
"NtLoadDriver", | |
"NtLoadKey", | |
"NtLoadKey2", | |
"NtLockFile", | |
"NtLockProductActivationKeys", | |
"NtLockRegistryKey", | |
"NtLockVirtualMemory", | |
"NtMakePermanentObject", | |
"NtMakeTemporaryObject", | |
"NtMapUserPhysicalPages", | |
"NtMapUserPhysicalPagesScatter", | |
"NtMapViewOfSection", | |
"NtModifyBootEntry", | |
"NtNotifyChangeDirectoryFile", | |
"NtNotifyChangeKey", | |
"NtNotifyChangeMultipleKeys", | |
"NtOpenDirectoryObject", | |
"NtOpenEvent", | |
"NtOpenEventPair", | |
"NtOpenFile", | |
"NtOpenIoCompletion", | |
"NtOpenJobObject", | |
"NtOpenKey", | |
"NtOpenMutant", | |
"NtOpenObjectAuditAlarm", | |
"NtOpenProcess", | |
"NtOpenProcessToken", | |
"NtOpenProcessTokenEx", | |
"NtOpenSection", | |
"NtOpenSemaphore", | |
"NtOpenSymbolicLinkObject", | |
"NtOpenThread", | |
"NtOpenThreadToken", | |
"NtOpenThreadTokenEx", | |
"NtOpenTimer", | |
"NtPlugPlayControl", | |
"NtPowerInformation", | |
"NtPrivilegeCheck", | |
"NtPrivilegeObjectAuditAlarm", | |
"NtPrivilegedServiceAuditAlarm", | |
"NtProtectVirtualMemory", | |
"NtPulseEvent", | |
"NtQueryAttributesFile", | |
"NtQueryBootOptions", | |
"NtQueryBootOptions", | |
"NtQueryDebugFilterState", | |
"NtQueryDefaultLocale", | |
"NtQueryDefaultUILanguage", | |
"NtQueryDirectoryFile", | |
"NtQueryDirectoryObject", | |
"NtQueryEaFile", | |
"NtQueryEvent", | |
"NtQueryFullAttributesFile", | |
"NtQueryInformationAtom", | |
"NtQueryInformationFile", | |
"NtQueryInformationJobObject", | |
"NtQueryInformationPort", | |
"NtQueryInformationProcess", | |
"NtQueryInformationThread", | |
"NtQueryInformationToken", | |
"NtQueryInstallUILanguage", | |
"NtQueryIntervalProfile", | |
"NtQueryIoCompletion", | |
"NtQueryKey", | |
"NtQueryMultipleValueKey", | |
"NtQueryMutant", | |
"NtQueryObject", | |
"NtQueryOpenSubKeys", | |
"NtQueryPerformanceCounter", | |
"NtQueryQuotaInformationFile", | |
"NtQuerySection", | |
"NtQuerySecurityObject", | |
"NtQuerySemaphore", | |
"NtQuerySymbolicLinkObject", | |
"NtQuerySystemEnvironmentValue", | |
"NtQuerySystemEnvironmentValueEx", | |
"NtQuerySystemInformation", | |
"NtQuerySystemTime", | |
"NtQueryTimer", | |
"NtQueryTimerResolution", | |
"NtQueryValueKey", | |
"NtQueryVirtualMemory", | |
"NtQueryVolumeInformationFile", | |
"NtQueueApcThread", | |
"NtRaiseException", | |
"NtRaiseHardError", | |
"NtReadFile", | |
"NtReadFileScatter", | |
"NtReadRequestData", | |
"NtReadVirtualMemory", | |
"NtRegisterThreadTerminatePort", | |
"NtReleaseMutant", | |
"NtReleaseSemaphore", | |
"NtRemoveIoCompletion", | |
"NtRemoveProcessDebug", | |
"NtRenameKey", | |
"NtReplaceKey", | |
"NtReplyPort", | |
"NtReplyWaitReceivePort", | |
"NtReplyWaitReceivePortEx", | |
"NtReplyWaitReplyPort", | |
"NtRequestDeviceWakeup", | |
"NtRequestPort", | |
"NtRequestWaitReplyPort", | |
"NtRequestWakeupLatency", | |
"NtResetEvent", | |
"NtResetWriteWatch", | |
"NtRestoreKey", | |
"NtResumeProcess", | |
"NtResumeThread", | |
"NtSaveKey", | |
"NtSaveKeyEx", | |
"NtSaveMergedKeys", | |
"NtSecureConnectPort", | |
"NtQueryBootOptions", | |
"NtQueryBootOptions", | |
"NtSetContextThread", | |
"NtSetDebugFilterState", | |
"NtSetDefaultHardErrorPort", | |
"NtSetDefaultLocale", | |
"NtSetDefaultUILanguage", | |
"NtSetEaFile", | |
"NtSetEvent", | |
"NtSetEventBoostPriority", | |
"NtSetHighEventPair", | |
"NtSetHighWaitLowEventPair", | |
"NtSetInformationDebugObject", | |
"NtSetInformationFile", | |
"NtSetInformationJobObject", | |
"NtSetInformationKey", | |
"NtSetInformationObject", | |
"NtSetInformationProcess", | |
"NtSetInformationThread", | |
"NtSetInformationToken", | |
"NtSetIntervalProfile", | |
"NtSetIoCompletion", | |
"NtSetLdtEntries", | |
"NtSetLowEventPair", | |
"NtSetLowWaitHighEventPair", | |
"NtSetQuotaInformationFile", | |
"NtSetSecurityObject", | |
"NtSetSystemEnvironmentValue", | |
"NtQuerySystemEnvironmentValueEx", | |
"NtSetSystemInformation", | |
"NtSetSystemPowerState", | |
"NtSetSystemTime", | |
"NtSetThreadExecutionState", | |
"NtSetTimer", | |
"NtSetTimerResolution", | |
"NtSetUuidSeed", | |
"NtSetValueKey", | |
"NtSetVolumeInformationFile", | |
"NtShutdownSystem", | |
"NtSignalAndWaitForSingleObject", | |
"NtStartProfile", | |
"NtStopProfile", | |
"NtSuspendProcess", | |
"NtSuspendThread", | |
"NtSystemDebugControl", | |
"NtTerminateJobObject", | |
"NtTerminateProcess", | |
"NtTerminateThread", | |
"NtTestAlert", | |
"NtTraceEvent", | |
"NtTranslateFilePath", | |
"NtUnloadDriver", | |
"NtUnloadKey", | |
"NtUnloadKeyEx", | |
"NtUnlockFile", | |
"NtUnlockVirtualMemory", | |
"NtUnmapViewOfSection", | |
"NtVdmControl", | |
"NtWaitForDebugEvent", | |
"NtWaitForMultipleObjects", | |
"NtWaitForSingleObject", | |
"NtWaitHighEventPair", | |
"NtWaitLowEventPair", | |
"NtWriteFile", | |
"NtWriteFileGather", | |
"NtWriteRequestData", | |
"NtWriteVirtualMemory", | |
"NtYieldExecution", | |
"NtCreateKeyedEvent", | |
"NtOpenKeyedEvent", | |
"NtReleaseKeyedEvent", | |
"NtWaitForKeyedEvent", | |
"NtQueryPortInformationProcess" | |
] | |
class SYSDBG_PACKET(ctypes.Structure): | |
_fields_ = ( | |
("Address", ctypes.c_void_p), | |
("Buffer", ctypes.c_void_p), | |
("BufferLen", ULONG) | |
) | |
class SYSTEM_MODULE_INFORMATION(ctypes.Structure): | |
_fields_ = ( | |
("ModuleCount", ULONG), | |
("WhoCares", ctypes.c_void_p * 2), | |
("BaseAddress", ctypes.c_void_p), | |
("Size", ULONG), | |
("MoarStuff", ULONG), | |
("MoarMoar", USHORT), | |
("HeyThere", USHORT), | |
("Pwned", USHORT), | |
("W00t", USHORT), | |
("ImageName", ctypes.c_char_p * 256) | |
) | |
class TOKEN_PRIVS(ctypes.Structure): | |
_fields_ = ( | |
("PrivilegeCount", ULONG), | |
("Privileges", ULONG * 3) | |
) | |
def get_debug_privs(): | |
token = HANDLE() | |
windll.advapi32.OpenProcessToken(windll.kernel32.GetCurrentProcess(), 0x00000020, ctypes.byref(token)) | |
privs = TOKEN_PRIVS() | |
privs.PrivilegeCount = 1 | |
privs.Privileges = (0x14, 0, 2) | |
windll.advapi32.AdjustTokenPrivileges(token, 0, ctypes.byref(privs), 0, 0, 0) | |
windll.kernel32.CloseHandle(token) | |
def get_sdt_rva(): | |
ntos_handle = windll.kernel32.LoadLibraryA("ntoskrnl.exe") | |
return windll.kernel32.GetProcAddress(ntos_handle, "KeServiceDescriptorTable") - ntos_handle | |
def get_kernel_addr(): | |
buffer_size = ULONG(0) | |
windll.ntdll.ZwQuerySystemInformation(11, 0, 0, ctypes.byref(buffer_size)); | |
sysmod_info = ctypes.create_string_buffer(buffer_size.value) | |
windll.ntdll.ZwQuerySystemInformation(11, ctypes.byref(sysmod_info), buffer_size.value, ctypes.byref(buffer_size)); | |
mod_list = ctypes.cast(sysmod_info, ctypes.POINTER(SYSTEM_MODULE_INFORMATION)) | |
return (mod_list[0].BaseAddress, mod_list[0].BaseAddress + mod_list[0].Size) | |
def kernel_read(addr, size): | |
sysdbg_packet = SYSDBG_PACKET() | |
sysdbg_packet.Address = addr | |
if size == 4: | |
buff = ULONG() | |
else: | |
buff = ctypes.create_string_buffer(size) | |
sysdbg_packet.Buffer = ctypes.cast(ctypes.byref(buff), ctypes.c_void_p) | |
sysdbg_packet.BufferLen = size | |
windll.ntdll.ZwSystemDebugControl(8, ctypes.byref(sysdbg_packet), ctypes.sizeof(SYSDBG_PACKET), 0, 0, 0) | |
return buff | |
def get_ssdt(): | |
ssdt_ptr = kernel_read(kernel_start + get_sdt_rva(), 4) | |
ssdt_size = kernel_read(kernel_start + get_sdt_rva() + 8, 4) | |
return (ssdt_ptr.value, ssdt_size.value) | |
get_debug_privs() | |
(kernel_start, kernel_end) = get_kernel_addr() | |
print "[+] Got kernel @ 0x%08x => 0x%08x" % (kernel_start, kernel_end) | |
(ssdt_ptr, ssdt_size) = get_ssdt() | |
print "[+] Got SSDT @ 0x%08x, entries: 0x%04x" % (ssdt_ptr, ssdt_size) | |
ssdt = kernel_read(ssdt_ptr, ssdt_size*4) | |
offset = 0 | |
while offset < ssdt_size*4: | |
address = struct.unpack('<L', ssdt[offset:offset+4])[0] | |
if address > kernel_end or address < kernel_start: | |
try: | |
syscall = SYSCALLS[offset/4] | |
except: | |
syscall = "syscall_id_%02x" % (offset/4) | |
print "[*] Hooked %s => 0x%08x" % (syscall, address) | |
offset += 4 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment