i have made a small modification of one of User_Russian's great driver examples (http://www.purebasic.fr/english/viewtop ... evelopment)
to show how to get dynamically the index number from the Service Descriptor Table of known functions. You can use this to generally detect SDT hooks or make it easily to hook SDT functions, or just as kind of getprocaddress.
btw. sry for my bad english and messy code ;X
http://s14.directupload.net/images/130707/ilkicvt3.png
Code: Select all
Declare DriverEntry(*DriverObject, *RegistryPath)
XIncludeFile #PB_Compiler_Home+"DDK\ntddk.pbi"
XIncludeFile #PB_Compiler_Home+"DDK\ntstatus.pbi"
CompilerSelect #PB_Compiler_Processor
CompilerCase #PB_Processor_x86
Import "ntoskrnl.lib"
CompilerCase #PB_Processor_x64
ImportC "ntoskrnl.lib"
CompilerEndSelect
IoCompleteRequest(*IRP, PriorityBoost)
RtlInitUnicodeString(*UString, *String)
IoCreateDevice(*DriverObject, DeviceExtensionSize, *UDeviceName, DeviceType, DeviceCharacteristics, Exclusive, *DeviceObject)
IoDeleteDevice(*DeviceObject)
IoCreateSymbolicLink(*SymbolicLinkName, *DeviceName)
IoDeleteSymbolicLink(*SymbolicLinkName)
ZwQuerySystemInformation(SysInfoClass, *SysInfo, SysInfoLength.l, *ReturnLength)
ExAllocatePool(PoolType, NumBytes)
ExFreePool(*Point)
*KeServiceDescriptorTable.SERVICE_DESCRIPTOR_TABLE As "__imp__KeServiceDescriptorTable"
EndImport
ImportC "ntoskrnl.lib"
DbgPrint(*String)
strstr(*Stringx, *SearchFor)
_stricmp(*str1,*str2)
_snprintf(STRx,count.l,*format,arg)
strcat ( *destination,*source)
strcpy ( *destination, *source );
EndImport
#IOCTL_READ_PORT_UCHAR = $200
#IOCTL_WRITE_PORT_UCHAR = $400
*A=@DriverEntry()
!jmp [p_A]
Structure SYSTEM_MODULE
Reserved1.l;
Reserved2.l;
*ImageBaseAddress;
ImageSize.l;
Flags.l;
Id.w;
Rank.w;
w018.w;
NameOffset.w;
Name.s{#MAXIMUM_FILENAME_LENGTH};
EndStructure
Structure SYSTEM_MODULE_INFO
ModulesCount.l;
Modules.SYSTEM_MODULE[0];
EndStructure
Structure StrippedExport
*AddressOfName
*AddressOfFunc
*LoopOrdinal
*Ordinal
EndStructure
Macro NTCALL(_function)
*KeServiceDescriptorTable\ntoskrnl\ServiceTable\ar[_function]
EndMacro
Enumeration
#SM_SDT_Name_By_Ordinal
#SM_SDT_Ordinal_By_Name
EndEnumeration
;get the kernel base address
Procedure.l GetKernelBaseAddress()
Protected SystemInfoBufferSize.l,*pSystemInfoBuffer
Protected *ModulesInfo.SYSTEM_MODULE_INFO
ZwQuerySystemInformation(#SystemModuleInformation, @SystemInfoBufferSize, 0, @SystemInfoBufferSize)
If @SystemInfoBufferSize <> 0 ;
*pSystemInfoBuffer = ExAllocatePool(#PagedPool, SystemInfoBufferSize*2)
If *pSystemInfoBuffer <> #Null
If ZwQuerySystemInformation(#SystemModuleInformation, *pSystemInfoBuffer, SystemInfoBufferSize*2, @SystemInfoBufferSize)= #STATUS_SUCCESS
*ModulesInfo = *pSystemInfoBuffer
For i = 0 To *ModulesInfo\ModulesCount -1
;ntoskrnl.exe single-processor without PAE
;ntkrnlmp.exe multi-processor without PAE
;ntkrnlpa.exe single-processor With PAE (version 5.0 And higher)
;ntkrpamp.exe multi-processor With PAE (version 5.0 And higher)
If strstr(@*ModulesInfo\Modules[i]\Name,@"ntoskrnl.exe") Or strstr(@*ModulesInfo\Modules[i]\Name,@"ntkrnlmp.exe") Or strstr(@*ModulesInfo\Modules[i]\Name,@"ntkrnlpa.exe") Or strstr(@*ModulesInfo\Modules[i]\Name,@"ntkrpamp.exe")
DbgPrint(@*ModulesInfo\Modules[i]\Name)
ProcedureReturn *ModulesInfo\Modules[i]\ImageBaseAddress
EndIf
Next
EndIf
ExFreePool(*pSystemInfoBuffer)
EndIf
EndIf
ProcedureReturn 0
EndProcedure
;get address of exportname or get name of exportaddress
Procedure.l GetExport(*KernelBase,*ExportName,*ExportAddress,*outExport.StrippedExport)
Protected *DOS_STUB.IMAGE_DOS_HEADER
Protected *NT_HEADER.IMAGE_NT_HEADERS
Protected *DATA_HEADER.IMAGE_DATA_DIRECTORY
Protected *EXPORT.IMAGE_EXPORT_DIRECTORY
Protected i.l,*addrName,*addrFunc,*addrOrd,*AddressOfName,*AddressOfFunc,*AddressOfOrd
Protected DebugString.s{100}
Protected OrdinalString.s{8}
*DOS_STUB = *KernelBase
*NT_HEADER = *KernelBase + *DOS_STUB\e_lfanew
*EXPORT = *KernelBase + *NT_HEADER\OptionalHeader\DataDirectory[0]\VirtualAddress
*addrName = *KernelBase + *EXPORT\AddressOfNames ;start names array
*addrFunc = *KernelBase + *EXPORT\AddressOfFunctions ;start address array
*addrOrd = *KernelBase + *EXPORT\AddressOfNameOrdinals ;start ordinals array
For i = 0 To *EXPORT\NumberOfNames -1
*AddressOfName = *KernelBase + PeekL(*addrName+(i*4))
AddressOfOrd = PeekW(*addrOrd+(i*2))
*AddressOfFunc = *KernelBase + PeekL(*addrFunc+(AddressOfOrd*4))
;*AddressOfFunc = *KernelBase + PeekL(*addrFunc+(i*4))
If *ExportAddress <> 0 And *ExportName = 0
If *AddressOfFunc = *ExportAddress
*outExport\AddressOfFunc=*AddressOfFunc
*outExport\AddressOfName=*AddressOfName
*outExport\LoopOrdinal =i
*outExport\Ordinal =AddressOfOrd
ProcedureReturn 1
EndIf
ElseIf *ExportName <> 0 And *ExportAddress = 0
If _stricmp(*ExportName,*AddressOfName) = 0
*outExport\AddressOfFunc=*AddressOfFunc
*outExport\AddressOfName=*AddressOfName
*outExport\LoopOrdinal =i
*outExport\Ordinal =AddressOfOrd
ProcedureReturn 1
EndIf
EndIf
Next
ProcedureReturn 0
EndProcedure
;searches for the name of an SDT index or searches for an SDT index by entering the function name
Procedure.l GetSdtOrinalFromExportTableEx(*KernelBase,SDTOrdinal.l,*Name,SearchMode)
Protected *NtCallAddr,i.l
Protected retExport.StrippedExport
Select SearchMode
Case #SM_SDT_Name_By_Ordinal
*NtCallAddr = NTCALL(SDTOrdinal)
If GetExport(*KernelBase,0,*NtCallAddr,@retExport) = 1
If *NtCallAddr = retExport\AddressOfFunc
ProcedureReturn retExport\AddressOfName
Else
ProcedureReturn 0
EndIf
EndIf
Case #SM_SDT_Ordinal_By_Name
If GetExport(*KernelBase,*Name,0,@retExport) = 1
For i = 0 To *KeServiceDescriptorTable\ntoskrnl\ServiceLimit-1
*NtCallAddr = NTCALL(i)
If *NtCallAddr = retExport\AddressOfFunc
ProcedureReturn i
EndIf
Next
EndIf
EndSelect
ProcedureReturn 0
EndProcedure
;searches for the name of an SDT index or searches for an SDT index by entering the function name
Procedure DeviceIoControl(*DeviceObject.DEVICE_OBJECT, *pIrp.IRP)
Protected ntStatus, *Point, *Stack.IO_STACK_LOCATION
*Stack = *pIrp\Tail\Overlay\CurrentStackLocation
inBuffersize = *Stack\Parameters\DeviceIoControl\InputBufferLength
outBuffersize = *Stack\Parameters\DeviceIoControl\OutputBufferLength
CtrlBuff = PeekI(*pIrp\SystemBuffer)
address = CtrlBuff & $FFFF
Byte.a = (CtrlBuff>>16)&255
Code = *Stack\Parameters\DeviceIoControl\IoControlCode
ntStatus = #STATUS_SUCCESS
Select Code
Case #IOCTL_READ_PORT_UCHAR
*pIrp\IoStatus\Information = 1
Case #IOCTL_WRITE_PORT_UCHAR
*pIrp\IoStatus\Information = 0
Default
ntStatus = #STATUS_UNSUCCESSFUL
*pIrp\IoStatus\Information = 0
EndSelect
*pIrp\IoStatus\Status = ntStatus
IoCompleteRequest(*pIrp, #IO_NO_INCREMENT)
ProcedureReturn ntStatus
EndProcedure
Procedure CreateDispatch(*DeviceObject.DEVICE_OBJECT, *pIrp.IRP)
*pIrp\IoStatus\Information = 0
*pIrp\IoStatus\Status = #STATUS_SUCCESS
IoCompleteRequest(*pIrp, #IO_NO_INCREMENT)
ProcedureReturn #STATUS_SUCCESS
EndProcedure
Procedure UnloadDriver(*DriverObject.DRIVER_OBJECT)
Protected uniDOSString.UNICODE_STRING
RtlInitUnicodeString(@uniDOSString, ?DosDevices)
IoDeleteSymbolicLink (@uniDOSString)
IoDeleteDevice(*DriverObject\DeviceObject)
EndProcedure
Procedure DriverEntry(*DriverObject.DRIVER_OBJECT, *RegistryPath.UNICODE_STRING)
Protected deviceObject.DEVICE_OBJECT
Protected uniNameString.UNICODE_STRING
Protected uniDOSString.UNICODE_STRING
Protected *KernelBase,*CallName
Protected i.l
Protected DebugString.s{100}
Protected OrdinalString.s{8}
RtlInitUnicodeString(@uniNameString, ?Device)
RtlInitUnicodeString(@uniDOSString, ?DosDevices)
DbgPrint(@"DriverEntry")
strcpy(@DebugString,@"Number of functions overall: ")
_snprintf(@OrdinalString,8,@"%x", *KeServiceDescriptorTable\ntoskrnl\ServiceLimit)
strCat(@DebugString,@OrdinalString)
DbgPrint(@DebugString)
*KernelBase = GetKernelBaseAddress()
If *KernelBase <> 0
DbgPrint(@"Found KernelBase")
;list all exported functions in SDT
For i = 0 To *KeServiceDescriptorTable\ntoskrnl\ServiceLimit -1
*CallName = GetSdtOrinalFromExportTableEx(*KernelBase,i,0,#SM_SDT_Name_By_Ordinal)
If *CallName <> 0
strcpy(@DebugString,@"Found Call: ")
strCat(@DebugString,*CallName)
strCat(@DebugString,@" Ordinal: ")
_snprintf(@OrdinalString,9,@"0x%x",i)
strCat(@DebugString,@OrdinalString)
DbgPrint(@DebugString)
Else
;DbgPrint(@"No Export present for this call")
EndIf
Next
strcpy(@DebugString,@"NtQuerySystemInformation")
;search for NtQuerySystemInformation
*CallName = GetSdtOrinalFromExportTableEx(*KernelBase,0,@DebugString,#SM_SDT_Ordinal_By_Name)
strcpy(@DebugString,@"Found Index No of NtQuerySystemInformation: ")
_snprintf(@OrdinalString,9,@"0x%x",*CallName)
strCat(@DebugString,@OrdinalString)
DbgPrint(@DebugString)
EndIf
status = IoCreateDevice(*DriverObject, 0, @uniNameString, #FILE_DEVICE_UNKNOWN, 0, #False, @deviceObject)
If status <> #STATUS_SUCCESS
ProcedureReturn status
EndIf
status = IoCreateSymbolicLink(@uniDOSString, @uniNameString)
If status <> #STATUS_SUCCESS
IoDeleteDevice(@deviceObject) ; Ìû äîëæíû ñàìè óáèðàòü "õâîñòû" â ðåæèìå ÿäðà!
ProcedureReturn status
EndIf
*DriverObject\DriverUnload = @UnloadDriver()
*DriverObject\MajorFunction[#IRP_MJ_CLOSE] = @CreateDispatch()
*DriverObject\MajorFunction[#IRP_MJ_CREATE] = @CreateDispatch()
*DriverObject\MajorFunction[#IRP_MJ_DEVICE_CONTROL] = @DeviceIoControl()
ProcedureReturn #STATUS_SUCCESS
EndProcedure
;
DataSection
CompilerSelect #PB_Compiler_Processor
CompilerCase #PB_Processor_x86
Device:
!du '\Device\driver', 0, 0
DosDevices:
!du '\DosDevices\driver', 0, 0
CompilerCase #PB_Processor_x64
Device:
!du '\Device\driver_x64', 0, 0
DosDevices:
!du '\DosDevices\driver_x64', 0, 0
CompilerEndSelect
EndDataSection