由于部分代码打上了extern,部分代码完全是通过汇编实现的,很难用C语言描述,所以我们希望能够得到函数的原型。
以下代码是从网上看到的,希望有帮助。当然有部分wrk已经有了,我是原帖转过来的
1.IoCallDriver
NTSTATUS
IoCallDriver(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
if (pIofCallDervier != NULL)
{
return pIofCallDervice(IoCallDriver);
}
//
// 现在:push the stack
// 包括:1) Irp->CurrentLocation 计数
// 2) Irp->Tail.Overlay.CurrentStackLocation 当前 stack 位置 push
//
if (--Irp->CurrentLocation <= 0)
{
KeBugCheckEx(35, Irp, 0, 0, 0);
}
PIO_STACK_LOCATION Stack = --Irp->Tail.Overlay.CurrentStackLocation;
Stack->DeviceObject = DeviceObject;
PDRVIER_OBJECT Driver = DeviceObject->DriverObject;
//
//调用 driver's dispatch routine
//
return (*Drivert->MajorFunction[Stack->MajorFunction])(DeviceObject, Irp);
}
2. IoGetDeviceObjectPointer()
NTSTATUS
IoGetDeviceObjectPointer(
IN PUNICODE_STRING ObjectName,
IN ACCESS_MASK DesiredAccess,
OUT PFILE_OBJECT *FileObject,
OUT PDEVICE_OBJECT *DeviceObject
)
{
PIO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE FileHandle;
PVOID Object;
//
// 初始化 OBJECT_ATTRIBUTE 结构
//
ObjectAttributes.Length = sizeof(ObjectAttributes);
ObjectAttributes.RootDirectory = NULL;
ObjectAttributes.Attributes = OBJ_KERNEL_HANDLE;
ObjectAttributes.SecurityDescriptor = NULL;
ObjectAttributes.SecurityQualityOfService = NULL;
ObjectAttributes.ObjectName = ObjectName;
NTSTATUS Status = ZwOpenFile(&FileHandle,
DesiredAccess,
&ObjectAttributes,
&IoStatusBlock,
0,
FILE_NON_DIRECTORY_FILE);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = ObReferenceObjectByHandle(FileHandle, 0, IoFileObjectType, KerneMode, &Object, NULL);
if (NT_SUCCESS(Status))
{
*FileObject = Object;
*DeviceObject = IoGetRelatedDeviceObject(Object);
}
ZwClose(FileHandle);
return Status;
}
3. IoGetAttachedDeviceReference()
PDEVICE_OBJECT
IoGetAttachedDeviceReference(
IN PDEVICE_OBJECT DeviceObject
)
{
PDEVICE_OBJECT devObj;
KIRQL OldIrql = KeRaiseIrlToDpcLevel();
devObj = IoGetAttachedDevice(DeviceObject);
ObfReferenceObject(devObj);
KfLowerIrql(OldIrql);
return devObj;
}
4. ObfReferenceObject()
LONG ObfReferenceObject(PVOID Object)
{
POBJECT_HEADER ObjectHeader = CONTAINING_RECORD(Object, OBJECT_HEADER, Body);
if (ObpTraceEnabled == TRUE)
{
ObpPushStackInfo(ObjectHeader, 1);
}
return InterlockedIncrement(ObjectHeader->PointerCount);
}
5. ObReferenceObjectByHandle()
NTSTATUS
ObReferenceObjectByHandle(
IN HANDLE Handle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_TYPE ObjectType,
IN KPROCESSOR_MODE AccessMode,
OUT PVOID *Object,
OUT POBJECT_HANDLE_INFORMATION HandleInformation
)
{
PKTHREAD Thread = GetCurrentThread(); // fs:[124h]
PHANDLE_TABLE HandleTable;
ACCESS_MASK GrantedAccess;
PKPROCESS Process;
PEPROCESS EProcess;
PETHREAD EThread;
PHANDLE_TABLE_ENTRY TableEntry;
PHANDLE_TABLE_ENTRY_INFO EntryInfo;
POBJECT_HEADER ObjectHeader;
ULONG ObAttributes;
PLIST_ENTRY ListEntry;
NTSTATUS Status;
*Object = NULL;
//
// BodyPointer 的值用来计算出 OBJECT_HEADER 结构地址:
// 1. 当 Handle = -1(KPROCESS handle)时,BodyPointer 为 Process值(由 Thread->ApcState.Process 得到)
// 2. 当 Handle = -2(KTHREAD handle)时,BodyPointer 为 Thread 值
//
PVOID BodyPointer;
if ((LONG)Handle < 0)
{
//
// 如果 Handle 是当前 KPROCESS handle 的话
// 当前 process 的 handle 为 -1
//
if (Handle == 0xFFFFFFFF)
{
if ((ObjectType != PsProcessType) && (ObjectType != NULL))
{
return STATUS_ACCESS_DENIED; // 值为 0C0000024h
}
//
// 从 KTHREAD 结构(ApcState.Process 域)里得到 KPROCESS 结构指针
// 这个 KPROCESS 指针指向一个 EPROCESS 结构的 Pcb 域(KPROCESS 变量)
// 根据这个得到 EPROCESS 结构地址!
//
Process = Thread->ApcState.Process; // KPROCESS 结构
EProcess = CONTAINING_RECORD(Process, EPROCESS, Pcb); // EPROCESS 结构
GrantedAccess = EProcess->GrantedAccess;
//
// 当前的 Process 指向 OBJECT_HEADER 结构的 Body 域
// 用 Process 值求出 OBJECT_HEADER 结构地址!
//
BodyPointer = Process;
}
else if (Handle == 0xFFFFFFFE)
{
//
// 如果 Handle 是当前 KTHREAD handle 的话
// 当前 thread 的 handle 为 -2 (0FFFFFFFEh)
//
if ((ObjectType != PsThreadType) && (ObectType != NULL))
{
return STATUS_ACCESS_DENIED;
}
//
// 此时:Thread 指向 ETHREAD 结构的 Tcb 成员!
// 根据 Tcb 得到宿主 ETHREAD 结构地址
//
EThread = CONTAINING_RECORD(Thread, ETHREAD, Tcb); // ETHREAD 结构
GrantedAccess = EThread->GrantedAccess;
//
// 当前的 Thread 指向 OBJECT_HEADER 结构的 Body 域
// 用 Thread 值求出 OBJECT_HEADER 结构地址!
//
BodyPointer = Thread;
}
else
{
//
// 测试 AccessMode 是否为 KernelMode(值为 0)
//
if (AccessMode == KernelMode)
{
Handle ^= 0x80000000; // 调整 Handle 值
HandleTable = ObpKernelHandleTable; // 使用全局变量 ObpKernelHandleTable 值
}
else
{
return STATUS_INVALID_HANDLE;
}
}
//
// 下面代码,在 handle 属于当前 process 或 thread 时,进行操作
//
if ((Handle == 0xFFFFFFFF || Handle == 0xFFFFFFFE)
{
if (((~GrantedAccess & DesiredAccess) != 0) && (AccessMode != KernelMode))
{
return STATUS_ACCESS_DENIED;
}
//
// 设置 Handlle information 返回结构
//
if (HandleInformation != NULL)
{
HandleInformation->GrantedAccess = GrantedAccess;
HandleInformation->HandleAttributes = 0;
}
//
// 根据 BodyPointer(指向 OBJECT_HEADER 结构的 Body 域)来得到 OBJECT_HEADER 结构地址
// 在 Handle = -1 时,BodyPointer = Process
// 在 Handle = -2 时,BodyPointer = Thread
//
ObjectHeader = CONTAINING_RECORD(BodyPointer, OBJECT_HEADER, Body);
if (ObpTraceEnabled == TRUE)
{
ObpPushStackInfo(ObjectHeader, 1);
}
//
// 增加 Object 计数
//
InterlockedIncrement(ObjectHeader->PointerCount);
//
// 成功:返回 Object 值
//
*Object = Thread;
return STATUS_SUCCESS;
}
}
else
{
//
// 当前 handle >= 0 时:得到当前 EPROCESS 结构地址和 HANDLE_TABLE 结构
//
Process = Thread->>ApcState.Process;
EProcess = CONTAINING_RECORD(Process, EPROCESS, Pcb);
HandleTable = &EProcess->ObjectTable;
}
//
// KeEnterCriticalRegionThread() 实现:对 KernelApcDisable -- 操作
//
Thread->KernelApcDisable--;
TableEntry = ExMapHandleToPointerEx(HandleTable, Handle, AccessMode);
if (TableEntry != NULL)
{
//
// 找到 宿主的 OBJECT_HEADER 结构地址
//
ObjectHeader = (POBJECT_HEADER )((ULONG)TableEntry->Object & 0xFFFFFFF8);
//
// 测试 object 类型,不区配时返回类型不符状态(STATUS_OBJECT_TYPE_MISMATCH)
//
if ((ObjectHeader->Type == ObjectType) || (ObjectType == NULL))
{
if (NtGlobalFlag & ***_KERNEL_STACK_TRACE_DB)
{
GrantedAccess = ObpTranslateGrantedAccessIndex(TableEntry->GrantedAccessIndex);
}
else
{
GrantedAccess = TableEntry->GrantedAccess & ~ObpAccessProtectCloseBit;
}
//
// 下面测试访问权限和模式,符合时成功处理
// 否则:返回 STATUS_ACCESS_DENIED 状态值
//
if (((DesiredAccess & ~GrantedAccess) == 0) || (AccessMode == KernelMode))
{
if (HandleTable->ExtraInfoPages != 0)
{
EntryInfo = ExpGetHandleInfo(HandleTable, Handle, TRUE);
}
else
{
EntryInfo = NULL;
}
//
// 设置 HandleInformation 返回信息
//
if (HandleInformation != NULL)
{
HandleInformation->GrantedAccesse = GrantedAccess ;
ObAttributes = TableEntry->ObAttributes;
ObAttributes = ObAttributes & 6;
if (TableEntry->GrantedAccess & ObpAccessProtectCloseBit)
{
ObAttributes = ObAttributes | 1;
}
HandleInformation->HandleAttributes = ObAttributes;
}
if ((TableEntry->ObAttributes & 4)
&& (EntryInfo != NULL)
&& (EntryInfo->AuditMask != 0)
&& (DesiredAccess != 0)
&& (AccessMode != 0))
{
ObpAuditObjectAccess(Handle, EntryInfo, &ObjectHeader->Type->Name, DesiredAccess);
}
if (ObpTraceEnabled == TRUE)
{
ObpPushStackInfo(ObjectHeader, 1);
}
InterlockedIncrement(ObjectHeader->PointerCount); // 增加 object 计数
ExUnlockHandleTableEntry(HandleTable, ObjectHandler);
*Object = &ObjectHeader->Body; // ObjectHeadler 的 Body 域作为 Object 参数值返回
Status = STATUS_SUCCESS;
}
else
{
//
// 返回权限不足
//
Status = STATUS_ACCESS_DENIED;
ExUnlockHandleTableEntry(HandleTable, TableEntry);
}
}
else
{
//
// 返回 object 类型不区配
//
Status = STATUS_OBJECT_TYPE_MISMATCH;
ExUnlockHandleTableEntry(HandleTable, TableEntry);
}
}
else
{
Status = STATUS_INVALID_HANDLE;
}
//
// KeLeaveCriticalRegionThread() 实现:对 KernelApcDisable ++ 操作后:
// 测试 KernelApcDisable 值是否为 0,并且 ListEntry 是否指向自己
//
Thread->KernelApcDisable++;
ListEntry = &Thread->ApcState.ApcListHead;
if ((Thread->KernelApcDisable == 0)
&& (Thread->ApcState.ApcListHead.Flink != ListEntry)
&& (Thread->SpecialApcDisable == 0)
{
KiCheckForKernelApcDelivery();
}
return Status;
}
6. ExpLookupHandleTableEntry()
PHANDLE_TABLE_ENTRY
ExpLookupHandleTableEntry (
IN PHANDLE_TABLE HandleTable,
IN EXHANDLE tHandle
)
{
PHANDLE_TABLE_ENTRY TableEntry;
ULONG MaxHandle = HandleTable->NextHandleNeedingPool;
tHandle.TagBits = 0;
if (tHandle.Value >= MaxHandle)
{
return NULL;
}
//
// HandleTable->TableCode 结构:
// (1) bit 0 到 bit 1 得出 TableEntry 的层数(类似分页机制的页表结构层数)
// (2) bit 2 到 bit 31 是 TableEntry 结构的基址(类似分页机制的 CR3 基址)
//
ULONG Level = HandleTable->TableCode & 3;
ULONG Base = HandleTable->TableCode & 0xFFFFFFFC;
ULONG Table; // Table 表基址
ULONG Scale; // Scale 值用于得出 TableEntry
switch (Level)
{
case 0:
//
// 当层数只有一层时:Base 就是最终的 Table 基址,tHandle.Value 就是 Scale 值
//
Table = Base;
Scale = tHandle.Value;
break;
case 1:
//
// 当层数有两层时:需要求出 Table 基址(放在 Base + TableOffset 地址的内存里)
// tHandle.Value 的 bit 2 到 bit 10 是 Scale 值
//
ULONG TableOffset = (tHandle.Value & 0xFFFFF800) >> 9; // 求出 Table Offset 值
Table = *((PULONG)(Base + TableOffset)); // 得到 Table 基址
Scale = tHandle.Value & 0x7FF;
break;
default:
//
// 否则(层数为三层):
// (1) 求出 Driectory 基址( 放在 Base + DriectoryOffset 地址的内存里)
// (2) 求出 Table 基址(放在 Directory + TableOffset 地址内存里)
// (3) tHandle.Value 的 bit 2 到 bit 10 是 Scale 值
//
ULONG TableOffset = ((tHandle.Value & 0xFFFFFF800) >> 9) & 0xFFF;
ULONG DirectoryOffset = ((tHandle.Value & 0xFFFFFF800) >> 9) & 0xFFFFF000) >> 10;
ULONG Directory = *((PULONG)(Base + DirectoryOffset)); // 得到 Diectory 基址
Table = *((PULONG)(Directory + TableOffset)); // 得到 Table 基址
Scale = tHandle.Value & 0x7FF;
break;
}
//
// 得到最后 TableEntry 结构地址
//
TableEntry = (PHANDLE_TABLE_ENTRY)(Table + Sacle * 2);
return TableEntry;
}
7. IoGetRelatedDeviceObject()
PDEVICE_OBJECT
IoGetRelatedDeviceObject(
IN PFILE_OBJECT FileObject
)
{
PDEVICE_OBJECT DeviceObject;
PVPB Vpb = FileObject->Vpb;
//
// 根据 FileObject 找到当前的 DeviceObject:
// 1. 如果 Vpb != NULL 并且 Vpb->DeviceObject != NULL,则:DeviceObject = Vpb->DeviceObject
// 2. 如果 FileObject->DeviceObject->Vpb->DeviceObject != NULL,则:DeviceObject = FileObject->DeviceObject->Vpb->DeviceObject
// 3. 否则 DeviceObject = FileObject->DeviceObject
//
if ((Vpb == NULL) || (Vpb->DeviceObject == NULL))
{
if (((FileObject->Flag & FO_DIRECT_DEVICE_OPEN) != 0)
|| (FileObject->DeviceObject->Vpb == NULL)
|| (FileObject->DeviceObject->Vpb->DeviceObject == NULL))
{
DeviceObject = FileObject->DeviceObject;
}
else
{
DeviceObject = FileObject->DeviceObject->Vpb->DeviceObject;
}
}
else
{
DeviceObject = Vpb->DeviceObject;
}
//
// 假如这个 DeviceObject 没有附加的 DeviceObject,就直接返回当前的 DeviceObject
// 在 DeviceObject->AttachedDevice 不为 NULL 时:
// 1. 当有 FileObject 有扩展结构时,并且扩展结构的TopDeviceObjectHint 不为 NULL
// 且 IopVerifyDeviceObjectOnStack() 返回值为 TURE 时,返回的 DeviceObject 为 FileObjectExtension->TopDeviceObjectHint;
// 2. 否则调用IoGetAttachedDevice() 函数找到最顶层的 附加的 DeviceObject
//
if (DeviceObject->AttachedDevice)
{
PIOP_FILE_OBJECT_EXTENSION FileObjectExtension =
(PIOP_FILE_OBJECT_EXTENSION)(FileObject + 1);
if ((FileObject->Flag & FO_FILE_OBJECT_HAS_EXTENSION == 0)
|| (FileObjectExtension->TopDeviceObjectHint == NULL)
|| (IopVerifyDeviceObjectOnStack(
DeviceObject,
fileObjectExtension->TopDeviceObjectHint,
0) == FALSE)
)
{
DeviceObject = IoGetAttachedDevice(DeviceObject);
}
else
{
DeviceObject = FileObjectExtension->TopDeviceObjectHint;
}
}
return DeviceObject;
}
8. IopfCompleteRequest()
VOID
IopfCompleteRequest(
IN PIRP Irp,
IN CCHAR PriorityBoost
)
{
CHAR StackCount = Irp->StackCount + 1;
CHAR CurrentLocation = Irp->CurrentLocation
PCHAR AuxiliaryBuffer = NULL;
NTSTATUS Status;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT OriginalFileObject;
PIO_STACK_LOCATION CurrentStackLocation;
//
// 假如 Stack location 超出 stack 数量(StackCount + 1)
// 或者 IRP 的类型不为 IO_TYPE_IRP(值为 6)时,进入蓝屏
//
if ((Irp->CurrentLocation > Irp->StackCount + 1)
|| (Irp->Type != IO_TYPE_IRP))
{
KeBugCheckEx(MULTIPLE_IRP_COMPLETE_REQUESTS, (ULONG_PTR)Irp, __LINE__, 0, 0);
}
//
// 得到最底层的 Stack location 结构
//
PIO_STACK_LOCATION Bottom = (PIO_STACK_LOCATION)((ULONG)Irp + sizeof(IRP));
//
// 假如发生错误返回,则:Parameters.Others.Argument4 是错误状态值
//
if (Bottom->Control & SL_ERROR_RETURNED)
{
Status = (NTSTATUS)(Bottom->Parameters.Others.Argument4);
}
else
{
Status = STATUS_SUCCESS;
}
//
// 得到当前 stack location,并从当前开始向后遍历
// 直到最后完成
//
CurrentStackLocation = Irp->Tail.Overlay.CurrentStackLocation;
Irp->CurrentLocation++;
Irp->Tail.Overlay.CurrentStackLocation = CurrentStackLocation + 1;
while (Irp->CurrentLocation <= Irp->StackCount + 1)
{
Irp->PendingReturned = CurrentStackLocation->Control & SL_PENDING_RETURNED;
//
// 当返回错误时:
//
if (!NT_SUCCESS(Irp->IoStatus.Status) && (Irp->IoStatus.Status != Status))
{
CurrentStackLocation->Control |= SL_ERROR_RETURNED;
Bottom->Control |= SL_ERROR_RETURNED;
Status = Irp->IoStatus.Staus;
Bottom->Parameters.Others.Argument4 = Status;
}
//
// 两个条件之一:
// 1. 在 NT_SUCCESS(Irp->IoStatus.Status) == TRUE 的情况下:
// (CurrentStackLocation->Control & SL_INVOKE_ON_SUCCESS) != 0 或者
// (Irp->Cacel == TURE) 并且 (CurrentStackLocation->Control & SL_INVOKE_ON_CANCEL) != 0
//
// 2. 在 NT_SUCESSS(Irp->IoStatus.Status) == FALSE 的情况下:
// (CurrentStackLocation->Control & SL_INVOKE_ON_ERROR) != 0 或者
// (Irp->Cancel == TURE) 并且 (CurrentStackLocation->Control & SL_INVOKE_ON_CANCEL) != 0
//
if ((NT_SUCCESS(Irp->IoStatus.Status) &&
((CurrentStackLocation->Control & SL_INVOKE_ON_SUCCESS)
|| (Irp->Cancel && (CurrentStackLocation->Control & SL_INVOKE_ON_CANCEL)))
|| (!NT_SUCCESS(Irp->IoStatus.Status) &&
((CurrentStackLocation->Control & SL_INVOKE_ON_ERROR)
|| (Irp->Cancel && (CurrentStackLocation->Control & SL_INVOKE_ON_CANCEL))))
{
CurrentStackLocation->Control &= SL_ERROR_RETURNED;
CurrentStackLocation->MinorFunction = 0;
CurrentStackLocation->Flags = 0;
CurrentStackLocation->Parameters.Others.Argument1 = NULL;
CurrentStackLocation->Parameters.Others.Argument2 = NULL;
CurrentStackLocation->Parameters.Others.Argument3 = NULL;
CurrentStackLocation->FileObject = NULL;
if ( Irp->CurrentLocation != Irp->StackCount + 1)
{
DeviceObject = Irp->Tail.Overlay.CurrentStackLocation->DeviceObject;
}
else
{
DeviceObject = NULL;
}
Status = (*(IO_COMPLETION_ROUTINE)CurrentStackLocation->CompletionRoutine)(
DeviceObject,
Irp,
CurrentStackLocation->Context);
if (Status == STATUS_MORE_PROCESSING_REQUIRED)
{
return;
}
}
else
{
if ((Irp->PendingReturned) && (Irp->CurrentLocation <= Irp->StackCount)
{
Irp->Tail.Overlay.CurrentStackLocation->Control |= SL_PENDING_RETURNED;
}
CurrentStackLocation->Control &= SL_ERROR_RETURNED;
CurrentStackLocation->MinorFunction = 0;
CurrentStackLocation->Flags = 0;
CurrentStackLocation->Parameters.Others.Argument1 = NULL;
CurrentStackLocation->Parameters.Others.Argument2 = NULL;
CurrentStackLocation->Parameters.Others.Argument3 = NULL;
CurrentStackLocation->FileObject = NULL;
}
//
// 指向下一个 stack location
//
Irp->Tail.Overlay.CurrentStackLocation++;
CurrentStackLocation++;
Irp->CurrentLocation++;
}
if (Irp->Flags & IRP_ASSOCIATED_IRP)
{
PIRP MasterIrp = Irp->AssociatedIrp.MasterIrp;
ULONG IrpCount = IopInterlocakedDecrementUlong(LockQueueIoDatabaseLock,
&MasterIrp->AssociatedIrp.IrpCount);
IopFreeIrpAndMdls(Irp);
if (IrpCount == 1)
{
IopfCompleteRequest(MasterIrp, PriorityBoost);
}
return;
}
if (Irp->IoStatus.Status == STATUS_REPARSE)
{
if (Irp->IoStatus.Information > IO_REPARSE_TAG_RESERVED_RANGE)
{
if (Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT)
{
AuxiliaryBuffer = Irp->Tail.Overlay.AuxiliaryBuffer;
Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
}
else
{
Irp->IoStatus.Status = STATUS_IO_REPARSE_TAG_NOT_HANDLED;
}
}
}
if (Irp->Tail.Overlay.AuxiliaryBuffer != NULL)
{
ExFreePoolWithTag(Irp->Tail.Overlay.AuxiliaryBuffer, 0);
Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
}
if ((Irp->Flags & (IRP_CLOSE_OPERATION | IRP_PAGING_IO))
{
if (Irp->Flags & (IRP_CLOSE_OPERATION | IRP_SYNCHRONOUS_PAGING_IO)))
{
Irp->UserIosb->Status = Irp->IoStatus.Status;
Irp->UserIosb->Information = Irp->IoStatus.Information;
KeSetEvent(Irp->UserEvent, PriorityBoost, 0);
if (Irp->Flags & (IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO))
{
if (IopReserveIrpAllocator == Irp)
{
IopFreeReserveIrp(PriorityBoost);
}
else
{
IoFreeIrp(Irp);
}
}
}
else
(
KeInitializeApc(&Irp->Tail.Apc,
&Irp->Tail.Overlay.Thread->Tcb,
Irp->ApcEnvironment,
IopCompletePageWrite,
0,
0,
0,
0);
KeInsertQueueApc(&Irp->Tail.Apc,
NULL,
NULL,
PriorityBoost);
}
return;
}
PMDL Mdl = = Irp->MdlAddress;
for (; Mdl; Mdl = Mdl->Next)
{
MmUnlockPages(Irp->MdlAddress);
}
if (Irp->Flags & IRP_DEFER_IO_COMPLETION)
&& (Irp->PendingReturned == FALSE))
{
if (Irp->IoStatus.Status == STATUS_REPARSE) &&
(Irp->Information == IO_REPARSE_TAG_MOUNT_POINT))
{
Irp->Tail.Overlay.AuxiliaryBuffer = AuxiliaryBuffer;
}
return;
}
OriginalFileObject = Irp->Tail.Overlay.OriginalFileObject;
if (Irp->Cancel == FALSE)
{
KeInitializeApc(&Irp->Tail.Apc,
&Irp->Tail.Overlay.Thread->Tcb,
Irp->ApcEnvironment,
IopCompleteRequest,
IopAbortRequest,
NULL,
KernelMode,
NULL);
KeInsertQueueApc(&Irp->Tail.Apc,
OriginalFileObject,
AuxiliaryBuffer,
PriorityBoost);
return;
}
KIRQL OldIrql = KeRaiseIrqlToDpcLevel();
if (Irp->Tail.Overlay.Thread != NULL)
{
KeInitializeApc(&Irp->Tail.Apc,
&Irp->Tail.Overlay.Thread->Tcb,
Irp->ApcEnvironment,
IopCompleteRequest,
IopAbortRequest,
NULL,
KernelMode,
NULL);
KeInsertQueueApc(&Irp->Tail.Apc,
OriginalFileObject,
AuxiliaryBuffer,
PriorityBoost);
KfLowerIrql(OldIrql);
}
else
{
KfLowerIrql(OldIrql);
IopDropIrp(Irp, OriginalFileObject);
}
return;
}
9. IopCompleteUnloadOrDelete()
VOID
IopCompleteUnloadOrDelete(
IN PDEVICE_OBJECT DeviceObject,
IN BOOLEAN OnCleanStack,
IN KIRQL Irql
)
{
PDRIVER_OBJECT DriverObject = DeviceObject->DriverObject;
BOOLEAN Unload = TRUE;
//
// 需要做 REMOVE 操作时:
//
if (DeviceObject->DeviceObjectExtension->ExtensionFlags & DOE_REMOVE_PENDING)
{
//
// 找到栈 bottom 的 device object
//
PDEVICE_OBJECT Bottom = IopGetDeviceAttachmentBase(DeviceObject);
PDEVICE_OBJECT Base = Bottom;
//
// 检测整个 stack 中的所有 device object 的 ReferenceCount 值是否为 0
// 不是则退出:
//
while (Bottom)
{
if (Bottom->ReferenceCount != 0)
{
KfLowerIrql(Irql);
return;
}
Bottom = Bottom->AttachedDevice;
}
//
// 如果所有的 device object 的 ReferenceCount = 0 时
// ExtensionFlags 标志值去掉 DOE_REMOVE_PENDING
// 指示:已处理移除
//
Bottom = Base;
while (Bottom)
{
Bottom->DeviceObjectExtension->ExtensionFlags &= ~DOE_REMOVE_PENDING;
Bottom->DeviceObjectExtension->ExtensionFlags |= DOE_REMOVE_PROCESSED;
Bottom = Bottom->AttachedDevice;
}
KfLowerIrql(Irql);
IopChainDereferenceComplete(Base, OnCleanStack);
return;
}
//
// 如果需要做 DELETE 操作时:
//
if (DeviceObject->DeviceObjectExtension->ExtensionFlags & DOE_DELETE_PENDING)
{
//
// 检测是否需要做 Unload 操作:
//
if (((DeviceObject->DeviceObjectExtension->ExtensionFlags & DOE_UNLOAD_PENDING) == 0)
|| (DriverObject->Flags & DRVO_UNLOAD_INVOKED))
{
Unload = FALSE;
}
if (DeviceObject->AttachedDevice != NULL)
{
PDRIVER_OBJECT AttachedDriverObject = DeviceObject->AttachedDevice->DriverObject;
DeviceObject->ReferenceCount++;
KfLowerIrql(Irql);
if ((AttachedDriverObject->FastIoDispatch)
&& (AttachedDriverObject->FastIoDispatch->SizeOfFastIoDispatch > 0x34)
&& (AttachedDriverObject->FastIoDispatch->FastIoDetachDevice))
{
AttachedDriverObject->FastIoDispatch->FastIoDetachDevice(
DeviceObject->AttachedDevice,
DeviceObject);
}
KIRQL OldIrql = KeRaiseIrqlToDpcLevel();
DeviceObject->ReferenceCount--;
if ((DeviceObject->AttachedDevice != NULL) || (DeviceObject->ReferenceCount != 0))
{
KfLowerIrql(OldIrql);
return;
}
}
KfLowerIrql(OldIrql);
if (DeviceObject->SecurityDescriptor != NULL)
{
ObDereferenceSecurityDescriptor(DeviceObject->SecurityDescriptor, 1);
}
IopInsertRemoveDevice(DeviceObject->DriverObject, DeviceObject, FALSE);
ObfDereferenceObject(DeviceObject);
if (Unload == FALSE)
{
return;
}
OldIrql = KeRaiseIrqlToDpcLevel();
if (DriverObject->Flags & DRVO_UNLOAD_INVOKED)
{
KfLowerIrql(OldIrql);
return;
}
}
PDEVICE_OBJECT devObj = DriverObject->DeviceObject;
while (devObj)
{
if ((devObj->ReferenceCount != 0)
|| (devObj->AttachedDevice != NULL)
|| ((devObj->DeviceObjectExtension->ExtensionFlags & 6))
{
Unload = FALSE;
break;
}
devObj = devObj->NextDevice;
}
if ((DriverObject->Flags & 0x80) && (DriverObject->DeviceObject != NULL))
{
Unload = FALSE;
}
if (Unload = FALSE)
{
KfLowerIrql(OldIrql);
return;
}
DriverObject->Flags |= 1;
KfLowerIrql(OldIrql);
LOAD_PACKET LoadPacket;
LoadPacket.Event.WaitListHead.Flink = &LoadPacket.Event.WaitListHead;
LoadPacket.Event.WaitListHead.Blink = &LoadPacket.Event.WaitListHead;
LoadPacket.Event.Type = 0;
LoadPacket.Event.Size = 4;
LoadPacket.Event.SignalState = 0;
LoadPacket.DriverObject = DriverObject;
if (OnCleanStack == FALSE)
{
LoadPacket.WorkQueueItem.Parameter = &LoadPacket;
LoadPacket.WorkQueueItem.List.Flink = NULL;
LoadPacket.WorkQueueItem.WorkerRoutine = IopLoadUnloadDrive;
ExQueueWorkItem(&LoadPacket.WorkQueueItem, DelayedWorkQueue);
KeWaitForSingleObject(&LoadPacket.Event,
Executive,
KernelMode,
FALSE,
NULL);
}
else
{
IopLoadUnloadDriver(&LoadPacket);
}
ObMakeTemporaryObject(DriverObject);
ObfDereferenceObject(DriverObject);
}
10. KiFastCallEntry()
注意:这个 KiFastCallEntry() 还不是完整的代码(逆了大部分代码):
//
// 说明:
// 下面的 KiFastCallEntry() 代码是根据 windows 2003 的反汇编出来
// 然后转化为 C 的伪代码形式。
// 主要分析了 sysenter 指令进入 0 级 kernel 内的系统服务例程分发的流程
// 只分析了部分流程(属于正常进入时,不包含不正确时的情形
//
//
// KiFastCallEntry() 看起来像下面:由 EAX 寄存器传递系统服务功能号
//
VOID
KiFastCallEntry(ULONG ServiceNumber)
{
//
// 设 fs 寄存器的 base 为 kernel 的 PCR 结构地址
//
fs = 0x30;
//
// 用户代码 data selector
//
ds = 0x23;
es = 0x23;
//
// 得到当前 TSS 块,并读取 0 级的 esp 值
// 注意:这个 Esp0 指向一个 KTRAP_FRAME 结构的 V86Es 成员!
// Esp0 值减去 0x7c 就等于 KTRAP_FRAME 结构地址,trap 用于 context 信息
// esp 被赋予 KTRAP_FRAME 结构地址:esp = KtrapFrame,它以 push 的方式保存 context 信息
//
PKTSS Tss = GetCurrentTss();
PKTRAP_FRAME KtrapFrame = (PKTRAP_FRAME)(Tss->Esp0 - 0x7c);
//
// 注意:下面保存 context 的操作是以 push 方式压入 TrapFrame 为 esp 的栈中
//
KtrapFrame->HardwareSegSs = 0x23; // 保存原 R3 的 SS 值
KtrapFrame->HardwareEsp = edx; // edx 是原 R3 的 ESP 值
KtrapFrame->EFlags = eflags; // 保存原 eflags 值
KtrapFrame->EFlags.IF = 1; // context 中的 eflags.IF 置位
eflags = 0; // 当前的 eflags 清为 0
//
// 当前 edx 保存着 sysenter 进入前的 esp 值
// 加上 8 后:edx 指向 native API 调用中的第 1 个参数
//
PVOID ArgumentPointer = edx + 8;
KtrapFrame->SegCs = 0x1b; // 保存原 R3 的 CS 值
KtrapFrame->Eip = UserSharedData->SystemCallReturn; // 保存返回函数
KtrapFrame->ErrCode = 0; // 错误码为 0
KtrapFrame->Ebp = ebp;
KtrapFrame->Ebx = ebx;
KtrapFrame->Esi = esi;
KtrapFrame->Edi = edi;
KtrapFrame->SegFs = 0x3b; // 原 R3 的 FS 值
PKPCR Kpcr = (PKPCR)0xffdff000; // 也就是 fs.base
KtrapFrame->ExceptionList = Kpcr->NtTib.ExceptionList; // 保存原 SEH 链底
Kpcr->->NtTib.ExceptionList = -1; // 设置为空 SEH 链
PKTHREAD Thread = Kpcr->PrcbData.CurrentThread; // 得到当前线程结构
PVOID InitialStack = Thread->InitialStack; // 得到初始的 stack 地址
KtrapFrame->PreviousPreviousMode = UserMode; // 1 值是原 MODE_MASK 值
KtrapFrame = (PKTRAP_FRAME)((ULONG)KtrapFrame - 0x48); // 计算出 Ktrap_frame 基地址
//
// 计算初始 stack 的 ktrap_frame 基址:
// 这个 0x29c 值等于:NPX_FRAME_LENGTH + KTRAP_FRAME_LENGTH
// NPX_FRAME_LEGNTH = 0x210
// KTRAP_FRAME_LENGTH = 0x8c
//
InitialStack = (PVOID)((ULONG)InitialStack - 0x29c);
Thread->PreviousMode = UserMode;
//
// 假如这两个 stack 基址值不同
//
if (KtrapFrame != InitialStack)
{
goto 3869;
}
//
// 此时 InitialStack 指向 KtrapFrame 基址,也就是:InitialStack == KtrapFrame
//
InitialStack->Dr7 = 0; // 清 Dr7 值
Thread->TrapFrame = InitialStack;
//
// 检测是否需要保存 debug context 信息(debug 寄存器)
//
if (Thread->Header.DebugActive != 0xff)
{
goto 372c;
}
ebx = KtrapFrame->Ebp; // 读取原 ebp 值
edi = KtrapFrame->Eip; // 读取 UserSharedData->SystemCallReturn
KtrapFrame->DbgArgPointer = ArgumentPointer; // native API 调用的第 1 个参数
KtrapFrame->DbgArgMark = 0xbadb0d00;
//
// 实际上:当前 KtrapFrame 值等价于当前 esp
// 因此,下面两行代码是构建一个标准的 call 返回流程
// 1. push UserSharedData->SystemCallReturn(返回地址)
// 2. push ebp(原 stack frame base )
//
// 当前:
// 1. ebp == esp
// 2. ebp 指向 KtrapFrame->DbgEbp 值(stack top)
//
KtrapFrame->DbgEbp = ebx;
KtrapFrame->DbgEip = edi;
//
// ServiceNumber 的 bit 12 是 index 值,由这个 index 值得到 SeviceTable entry 结构
// ServiceTable entry 为 16 bytes,其中 entry 的第 3 个值是 MaxServerNumber
//
// 在 windows 2003 中:
// ServiceTable[0].MaxServiceNumber = 0x128
// ServiceTable[1].MaxServiceNumber = 0x299
//
ULONG ServiceNumber = eax & 0xFFF;
ULONG Index = (eax >> 12) & 0x01
PSERVER_TABLE_ENTRY ServiceTableEntry = Thread->ServiceTable[Index];
//
// ServiceNumber 的低 12 位是真正的 ServiceNumber 值
//
//
if (ServiceNumber >= ServceTableEntry->MaxServiceNumber)
{
goto nt!KiBBTUnexpectedRange (80883662)
}
//
// 测试是否进入 GUI 服务例程
//
if (Index == 1)
{
//
// 从 fs:[18h] 得到 R3 的 TEB 块
//
PTEB Teb = GetCurrentUserTeb()
if (Teb->GdiBatchCount != 0)
{
//
// 调用 win32k 的 NtGdiFlushUserBatch() 函数
//
KeGdiFlushUserBatch(ServiceNumber, edx); // edx 是参数地址
}
}
Kpcr->PrcbData.KeSystemCalls++;
//
// 从 ServiceTable 里得到参数表地址
//
PVOID ArgumentTable = ServiceTableEntry->ArgumentTable;
//
// 得到 native API 调用时的参数 size
//
CCHAR ArgumentSize = ArgumentTable[ServiceNumber];
//
// 从 ServiceTable 里得到 service table address
//
PVOID ServiceTableBase = ServiceTableEntry->ServiceTableBase;
//
// 下面检测 API 参数地址是否属于 User-space
// MmUserProbeAddress 的值为 0x7FFF0000
//
if (ArgumentPointer >= MmUserProbeAddress)
{
goto 3b54;
}
//
// 在当前 stack 上开辟足够容参数的空间
// 将 API 调用时的参数复制到当前 stack 上
//
esp = esp - ArgumentSize;
RtlMoveMemory(esp, ArgumentPointer, ArgumentSize);
//
// 最后调用服务例程:这里真正调用系统服务例程!
//
*(PFUN)ServiceTableBase[ServiceNumber]();
//
// 假如调用者是 ring 3 并且需要检查 APC
//
if ((KiEnableApcCheck & 0x01) && (KtrapFrame->SegCs.RPL == 3))
{
KIRQL Irql = KeGetCurrentIrql();
//
// 如果当前 Irql 不是 PASSIVE_LEVEL 级别:抛出 BugCheck 错误!
//
if (Irql != PASSIVE_LEVEL)
{
Kpcr->Irql = PASSIVE_LEVEL;
KeBugCheck2(0x4A,
NtWriteFile,
Irql,
0,
0,
InitialStack);
}
Thread = Kpcr->CurrentThread;
//
// 检查 process 是否 attached ?
// 或者 APCs 是否被 disable ?
// 如果是的话:抛出 BugCheck 错误!
//
if ((Thread->ApcStateIndex & 0xff) || (Thread->CombinedApcDisable != 0))
{
KeBugCheck2(1,
NtWriteFile,
Thread->ApcStateIndex,
Thread->CombinedApcDisable,
0,
InitialStack);
}
}
//
// 恢复 stack frame
//
esp = ebp;
PKTRAP_FRAME OldTrapFrame = KtrapFrame->Edx; // 找到原 esp 值(进入 sysenter 之前)
Thread->TrapFrame = OldTrapFrame; // 保存在 Thread 的 TrapFrame 域里
cli();
if ((KtrapFrame->EFlags.VM == 1) || (KtrapFrame->SegCs.RPL == 3))
{
Thread->Alerted = 0;
while (Thread->ApcStateFill.AsUserApcPending != 0)
{
KtrapFrame->Eax = eax; // 保存返回值
KtrapFrame->SegFs = 0x3b;
KtrapFrame->SegDs = 0x23;
KtrapFrame->SegEs = 0x23;
KtrapFrame->SegGs = 0;
//
// 下面代码将 IRQL 提升到 APC_LEVEL 级别
// 然后提交 APC 排队处理(需要开中断)
// 完成后恢复原 IRQL 级别并关闭中断许可
//
OldIrql = KfRaiseIrql(APC_LEVEL);
sti();
KiDeliverApc(1, 0, KtrapFrame); // 提交 APC 处理
KfLowerIrql(OldIrql);
cli();
Thread->Alerted = 0;
}
}
Kpcr->NtTib.ExceptionList = KtrapFrame->ExceptionList;
Thread->PreviousMode = KtrapFrame->PreviousPreviousMode;
if (KtrapFrame->Dr7 & 0xffff23ff)
{
//
// 如果开启了 DR7 调试功能
//
if ((KtrapFrame->EFlags.VM == 1) || (KtrapFrame->SegCs.RPL == 3))
{
dr7 = 0; // 先关闭调试功能
dr0 = KtrapFrame->Dr0;
dr1 = KtrapFrame->Dr1;
dr2 = KtrapFrame->Dr2;
dr3 = KtrapFrame->Dr3;
dr6 = KtrapFrame->Dr6;
dr7 = KtrapFrame->Dr7;
}
}
//
// 下面进行一些检测处理
//
if (KtrapFrame->EFlags.VM == 1)
{
//
// 如果开启了 V8086 模式
//
edx = KtrapFrame->Edx;
ecx = KtrapFrame->Ecx;
eax = KtrapFrame->Eax;
}
else if (KtrapFrame->SegCs & 0xFFF9 == 0)
{
//
// 如果 CS selector 为 0 值(0级下的 NULL selector)
//
KtrapFrame->SegCs = KtrapFrame->TempSegCs;
//
// ErrCode 指向构造的 TempStack 结构
//
PVOID TempStack = KtrapFrame->TempEsp - 0x0c;
KtrapFrame->ErrCode = TempStack;
//
// 下面构造一个 stack 结构(TempStack)以便使用 iretd 指令返回:
//
// Eflags
// SegCs
// esp ------> Eip
//
TempStack->Eflags = KtrapFrame->EFlags;
TempStack->SegCs = KtrapFrame->SegCs;
TempStack->Eip = KtrapFrame->Eip;
edi = KtrapFrame->Edi;
esi = KtrapFrame->Esi;
ebx = KtrapFrame->Ebx;
ebp = KtrapFrame->Ebp;
//
// 基于构造的 TempStack 来中断返回
//
esp = &TempStack;
iretd;
}
else if (KtrapFrame->SegCs.RPL == 3)
{
//
// 恢复 ring 3 的寄存器值
//
eax = KtrapFrame->Eax;
edx = KtrapFrame->Edx;
ecx = KtrapFrame->Ecx;
gs = KtrapFrame->SegGs;
es = KtrapFrame->SegEs;
ds = KtrapFrame->SegDs;
fs = KtrapFrame->SegFs;
}
else if (KtrapFrame->SegCs != 8)
{
fs = KtrapFrame->SegFs;
}
//
// 现在:esp 指向 KtrapFrame->Edi 域
// 下一步工作是:pop 出相关的值
//
esp = &KtrapFrame->Edi;
//
// 下面恢复原部分寄存器 context 信息
// 也就是执行:
// pop edi ----> 此时 esp 指向 edi 保存的地址
// pop esi
// pop ebx
// pop ebp
//
edi = KtrapFrame->Edi;
esi = KtrapFrame->Esi;
ebx = KtrapFrame->Ebx;
ebp = KtrapFrame->Ebp;
//
// 此时 stack frame 内的值为:
//
// esp ----> KtrapFrame->ErrCode
// KtrapFrame->Eip
// KtrapFrame->SegCs
// KtrapFrame->EFlags
// ktrapFrame->HardwareEsp
// KtrapFrame->HardwareSegSs
//
// 这是一个标准的调用中断 handler 入栈的情形,esp 指向 ErrorCode
//
//
// 当 CS 值大于 0x80 时,代表是 16 位代码?(返回到 16 位代码 ?)
//
if (KtrapFrame->SegCs > 0x80)
{
//
// 此时 KtrapFrame->ErrCode 被构造为一个 32 位宽的 far pointer(16:16)
// 这个 far pointer 是 stack pointer 值,被用来加载到 SS:SP 寄存器
//
PFarPointer far = &KtrapFrame->ErrCode;
if ((far->SegSs == 0) || far->Sp != 0)
{
esp = esp + 4; // 跳过 ErrCode, 执行中断返回
iretd;
}
//
// 执行 shr dword ptr [esp], 10h 操作
//
far->Sp = far->SegSs;
far->SegSs = 0xf8; // SS selector 为 0xf8
//
// 下面将 far pointer 装入 SS:SP
//
Ss = far->SegSs;
Sp = far->Sp;
iretd; // 执行中断返回
}
//
// 下面进行判断两种情形:
// 1. 当调用者属于 Ring 0 时,直接使用 jmp 指令返回到目标返回地址
// 2. 当调用者属于 Ring 3 时,使用 sysexit 指令返回
//
esp = esp + 4; // 跳过 ErrCode
if (KtrapFrame->SegCs.RPL == 0)
{
//
// 属于 ring0 的调用,下面操作是:手动销栈,读出 Eip 值到 edx 寄存器
// 等价于下面的操作:
// pop edx
// pop ecx
// popfd
// jmp edx
//
edx = KtrapFrame->Eip; // 得到返回地址
ecx = KtrapFrame->SegCs; // SegCs 值
eflags = KtrapFrame->Eflags; // pop 出 eflags 寄存器
//
// 跳转到 edx 地址上,也就是跳到:ntdll!KiFastSystemCallRet() 例程
// 这个 ntdll!KiFastSystemCallRet() 例程只有一条 ret 指令
// 通过这种方式返回到 API 的调用者(而非执行 sysexit 指令)
//
jmp edx
}
else
{
//
// 当调用者是用户代码时,返回的地址属于 3 级的用户层代码
//
if (KtrapFrame->EFlags.TF == 1)
{
//
// 如果开启单步调试,则使用 iretd 指令返回
//
iretd;
}
else
{
//
// 下面的处理,目的是:
// 1. 销掉部分 stack
// 2. 找到返回地址到 EDX 寄存器
// 3. 找到返回的 esp 值到 ECX 寄存器
// 4. 使用 sysexit 指令返回
//
edx = KtrapFrame->Eip; // pop 出 EIP 值
KtrapFrame->EFlags.IF = 0; // 清掉 stack 的中 IF 标志位
eflags = KtrapFrame->EFlags; // pop 出 eflags 值
ecx = ktrapFrame->HardwareEsp; // pop 出 Esp 值到
sti(); // 返回前打开中断
sysexit; // 执行 sysexit 指令返回
}
}
... ...
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课