(二十六)、seven
一、查壳

64位的驱动程序
二、IDA静态分析
字符串搜索看到了一串可疑的字符串

返回Driver
查看函数的时候发现可以驱动名

kdbclass 可疑的驱动名字,搜一下

驱动键盘过滤
继续进入read的分发函数

进入回调函数:

三、猜测是迷宫问题
结合字符串

与注释
__int64 __fastcall sub_1400012F0(__int64 a1, IRP *a2_Irp) { struct _IRP *MasterIrp; // rsi unsigned __int64 keyNumber; // rdx int v5; // ecx USHORT *p_Size; // rdi __int64 v7; // rbp USHORT v8; // dx char v9; // dl const CHAR *v10; // rcx if ( a2_Irp->IoStatus.Status >= 0 ) { MasterIrp = a2_Irp->AssociatedIrp.MasterIrp; keyNumber = a2_Irp->IoStatus.Information / 0xC; if ( (_DWORD)keyNumber ) { v5 = dword_1400030E4; p_Size = &MasterIrp->Size; v7 = (unsigned int)keyNumber; while ( *(&MasterIrp->Size + 1) ) { LABEL_30: p_Size += 6; if ( !--v7 ) goto LABEL_31; } aO[v5] = 46; v8 = *p_Size; if ( *p_Size == 17 ) { // v5相当于下标 // 如果大于等于16 if ( (v5 & 0xFFFFFFF0) != 0 ) { // 16个字符为一行 // 这里正好向上移动 v5 -= 16; goto LABEL_13; } v5 += 208; dword_1400030E4 = v5; } if ( v8 != 31 ) goto LABEL_14; // s if ( (v5 & 0xFFFFFFF0) == 0xD0 ) // ..直接结束 v5 -= 208; else // 下 v5 += 16; LABEL_13: dword_1400030E4 = v5; LABEL_14: if ( v8 == 30 ) { if ( (v5 & 0xF) != 0 ) // 左移 --v5; else // 右移到最右边 v5 += 15; dword_1400030E4 = v5; } // 0x20相当于d按键 if ( v8 == 0x20 ) { if ( (v5 & 0xF) == 15 ) // 移动到最左端 v5 -= 15; else // 右移 ++v5; dword_1400030E4 = v5; } v9 = aO[v5]; if ( v9 == '*' ) { v10 = "-1s\n"; } else { if ( v9 != '7' ) { LABEL_29: aO[v5] = 111; goto LABEL_30; } v10 = "The input is the flag!\n"; } dword_1400030E4 = 16; DbgPrint(v10); v5 = dword_1400030E4; goto LABEL_29; } } LABEL_31: if ( a2_Irp->PendingReturned ) a2_Irp->Tail.Overlay.CurrentStackLocation->Control |= 1u; return (unsigned int)a2_Irp->IoStatus.Status; }
推出:
w是上s是向下,d是向右,a是向左,终点是7,*代表不可走
则flag 即为
hctf{ddddddddddddddssaasasasasasasasasas}
PS
自己手写(抄写)了一份驱动过滤代码,但没有运行成功,ObReferenceObjectByName函数返回0xc0000024...还未解决
#include <ntddk.h> #include <ntddkbd.h> #define KBD_DRIVER_NAME L"\\Driver\\kbdclass" VOID c2pDetach(IN PDEVICE_OBJECT pDeviceObject); ULONG KeyBpardCount = 0;//全局变量键计数加一// PDRIVER_OBJECT gDriverObject = NULL; NTSTATUS ObReferenceObjectByName( PUNICODE_STRING ObjectName, ULONG Attributes, PACCESS_STATE AccessState, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, PVOID ParseContext, PVOID* Object ); extern POBJECT_TYPE IoDriverObjectType; //typedef struct _KEYBOARD_INPUT_DATA { // USHORT UnitId; // USHORT MakeCode; // USHORT Flags; // USHORT Reserved; // ULONG ExtraInformation; //} KEYBOARD_INPUT_DATA, * PKEYBOARD_INPUT_DATA; typedef struct _C2P_DEV_EXT { // 这个结构的大小 ULONG NodeSize; // 过滤设备对象 PDEVICE_OBJECT pFilterDeviceObject; // 同一时候调用时的保护锁 KSPIN_LOCK IoRequestsSpinLock; // 进程间同步处理 KEVENT IoInProgressEvent; // 绑定的设备对象 PDEVICE_OBJECT TargetDeviceObject; // 绑定前底层设备对象 PDEVICE_OBJECT LowerDeviceObject; } C2P_DEV_EXT, * PC2P_DEV_EXT; #define DELAY_ONE_MICROSECOND (-10) #define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000) #define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000) VOID Unload(PDRIVER_OBJECT DriverObject,PIRP Irp) { PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT OldDeviceObject; PC2P_DEV_EXT devExt; LARGE_INTEGER lDelay; PRKTHREAD CurrentThread; //delay some time lDelay = RtlConvertLongToLargeInteger(100 * DELAY_ONE_MILLISECOND); CurrentThread = KeGetCurrentThread(); // 把当前线程设置为低实时模式。以便让它的执行尽量少影响其它程序。 KeSetPriorityThread(CurrentThread, LOW_REALTIME_PRIORITY); UNREFERENCED_PARAMETER(DriverObject); KdPrint(("DriverEntry unLoading...\n")); // 遍历全部设备并一律解除绑定 DeviceObject = DriverObject->DeviceObject; while (DeviceObject) { // 解除绑定并删除全部的设备 c2pDetach(DeviceObject); DeviceObject = DeviceObject->NextDevice; } ASSERT(NULL == DriverObject->DeviceObject); while (KeyBpardCount) { KeDelayExecutionThread(KernelMode, FALSE, &lDelay); } KdPrint(("DriverEntry unLoad OK!\n")); return; } NTSTATUS General_DisPatch_Fun(PDEVICE_OBJECT DeviceObject, PIRP Irp) { DbgPrint("General_DisPatch_Fun\n"); IoSkipCurrentIrpStackLocation(Irp); //IoSkipCurrentIrpStackLocation(Irp)函数功能: //{ // NT_ASSERT(Irp->CurrentLocation <= Irp->StackCount); // Irp->CurrentLocation++; // Irp->Tail.Overlay.CurrentStackLocation++; //} //增加IRP的当前堆栈位置// return IoCallDriver(((PC2P_DEV_EXT)DeviceObject->DeviceExtension)->LowerDeviceObject, Irp); //与指定设备对象关联的驱动程序发送 IRP。 } //Irp 的回调函数// NTSTATUS ReadComplete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { NTSTATUS status; PIO_STACK_LOCATION stack; ULONG keyNumber; PKEYBOARD_INPUT_DATA myData; stack = IoGetCurrentIrpStackLocation(Irp); if (NT_SUCCESS(Irp->IoStatus.Status)) { myData = Irp->AssociatedIrp.SystemBuffer; keyNumber = (ULONG)(Irp->IoStatus.Information / sizeof(PKEYBOARD_INPUT_DATA)); for (ULONG i = 0; i < keyNumber; i++) { DbgPrint("numkey : %u\n", keyNumber); DbgPrint("sancode : %x\n", myData->MakeCode); DbgPrint("%s\n", myData->Flags ? "Up" : "Down"); if (myData->MakeCode == 0x1f) //用"d"键去替换"s"// { myData->MakeCode = 0x20; } } } KeyBpardCount--; if (Irp->PendingReturned) //例程标记指定的IRP,指示驱动程序的调度例程随后返回 STATUS_PENDING,因为其他驱动程序例程需要进一步处理。 //除非驱动程序的调度例程完成 IRP(通过调用IoCompleteRequest)或将 IRP 传递给较低的驱动程序,否则它必须使用 IRP 调用IoMarkIrpPending。否则,一旦调度例程返回控制,I/O 管理器就会尝试完成 IRP { IoMarkIrpPending(Irp); } return Irp->IoStatus.Status; } NTSTATUS Read_DisPatch_Fun(PDEVICE_OBJECT DeviceObject,PIRP Irp) { PC2P_DEV_EXT devExt; DbgPrint("Read\n"); NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION CurrentIrpStack; KEVENT waitEvent; KeInitializeEvent(&waitEvent, NotificationEvent, FALSE); if (Irp->CurrentLocation == 1)//这个是判断是否到达了irp栈的最低端 { ULONG RetInformation = 0; DbgPrint("判断是否到达了栈低\n"); status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Status = status; Irp->IoStatus.Information = RetInformation; IoCompleteRequest(Irp, IO_NO_INCREMENT); //指示调用者已完成对给定 I/O 请求的所有处理,并将给定 IRP 返回给 I/O 管理器 return status; } KeyBpardCount++; devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension; //得到设备扩展,为了获取下一个设备的指针// CurrentIrpStack = IoGetCurrentIrpStackLocation(Irp); IoCopyCurrentIrpStackLocationToNext(Irp); //设置读IRP完成回调函数// IoSetCompletionRoutine(Irp, ReadComplete,DeviceObject, TRUE, TRUE, TRUE);//注册一个IoCompletion例程,当下一个较低级别的驱动程序完成给定 IRP 的请求操作时,将调用该例程。 return IoCallDriver(devExt->LowerDeviceObject, Irp); } //电源IRP分发函数// NTSTATUS Power_DisPatch_Fun(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PC2P_DEV_EXT devExt; devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension; PoStartNextPowerIrp(Irp); //例程向电源管理器发出信号,表明驱动程序已准备好处理下一个电源IRP// IoSkipCurrentIrpStackLocation(Irp); return PoCallDriver(devExt->LowerDeviceObject, Irp); } //即插即用IRP分发函数// NTSTATUS Pnp_Dispatch_Fun(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PC2P_DEV_EXT devExt; PIO_STACK_LOCATION IrpStack; NTSTATUS status = STATUS_SUCCESS; KIRQL oldIrql; KEVENT event; devExt = (PC2P_DEV_EXT)(DeviceObject->DeviceExtension); IrpStack = IoGetCurrentIrpStackLocation(Irp); switch (IrpStack->MinorFunction) { case IRP_MN_REMOVE_DEVICE: DbgPrint("IRP_MN_REMOVE\n"); //向下发送请求// IoSkipCurrentIrpStackLocation(Irp); IoCallDriver(devExt->LowerDeviceObject, Irp); // 解除绑定。 IoDetachDevice(devExt->LowerDeviceObject); // 删除我们自己生成的虚拟设备。 IoDeleteDevice(DeviceObject); status = STATUS_SUCCESS; break; defult: //下发//... IoSkipCurrentIrpStackLocation(Irp); status = IoCallDriver(devExt->LowerDeviceObject, Irp); } return status; } NTSTATUS c2pDevExtInit( IN PC2P_DEV_EXT devExt, IN PDEVICE_OBJECT pFilterDeviceObject, IN PDEVICE_OBJECT pTargetDeviceObject, IN PDEVICE_OBJECT pLowerDeviceObject) { memset(devExt, 0, sizeof(C2P_DEV_EXT)); devExt->NodeSize = sizeof(C2P_DEV_EXT); devExt->pFilterDeviceObject = pFilterDeviceObject; KeInitializeSpinLock(&(devExt->IoRequestsSpinLock)); KeInitializeEvent(&(devExt->IoInProgressEvent), NotificationEvent, FALSE); devExt->TargetDeviceObject = pTargetDeviceObject; devExt->LowerDeviceObject = pLowerDeviceObject; return(STATUS_SUCCESS); } NTSTATUS AttachDevices( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS status = 0; UNICODE_STRING uniNtNameString; PC2P_DEV_EXT devExt; //过滤设置的扩展设备// PDEVICE_OBJECT pFilterDeviceObject = NULL; //过滤设备// PDEVICE_OBJECT pTargetDeviceObject = NULL; //目标设备// PDEVICE_OBJECT pLowerDeviceObject = NULL; //底层设备// PDRIVER_OBJECT KbdDriverObject = NULL; //用于接收打开的物理键盘设备// KdPrint(("AttachDevices\n")); RtlInitUnicodeString(&uniNtNameString, KBD_DRIVER_NAME); status = ObReferenceObjectByName( //获取键盘驱动对象,保存在kbdDriver// &uniNtNameString, OBJ_CASE_INSENSITIVE, NULL, 0, IoDriverObjectType, KernelMode, NULL, &KbdDriverObject ); if (!NT_SUCCESS(status)) { DbgPrint("MyAttach: Couldn't get the MyTest Device Object,status is : %x\n",status); return(status); } else { //解饮用// ObDereferenceObject(DriverObject); } pTargetDeviceObject = KbdDriverObject->DeviceObject; // 如今开始遍历这个设备链 while (pTargetDeviceObject) { // 生成一个过滤设备。这是前面读者学习过的。这里的IN宏和OUT宏都是 // 空宏,仅仅有标志性意义。表明这个參数是一个输入或者输出參数。 status = IoCreateDevice( IN DriverObject, IN sizeof(C2P_DEV_EXT), IN NULL, IN pTargetDeviceObject->DeviceType, IN pTargetDeviceObject->Characteristics, IN FALSE, OUT &pFilterDeviceObject ); if (!NT_SUCCESS(status)) { KdPrint(("MyAttach: Couldn't create the MyFilter Filter Device Object\n")); return (status); } // 绑定。pLowerDeviceObject是绑定之后得到的下一个设备。也就是 // 前面经常说的所谓真实设备。 pLowerDeviceObject = IoAttachDeviceToDeviceStack(pFilterDeviceObject, pTargetDeviceObject); // 假设绑定失败了,放弃之前的操作,退出。 if (!pLowerDeviceObject) { KdPrint(("MyAttach: Couldn't attach to MyTest Device Object\n")); IoDeleteDevice(pFilterDeviceObject); pFilterDeviceObject = NULL; return(status); } // 设备扩展!以下要具体讲述设备扩展的应用。 devExt = (PC2P_DEV_EXT)(pFilterDeviceObject->DeviceExtension); c2pDevExtInit(devExt,pFilterDeviceObject,pTargetDeviceObject,pLowerDeviceObject); // 以下的操作和前面过滤串口的操作基本一致。这里不再解释了。 pFilterDeviceObject->DeviceType = pLowerDeviceObject->DeviceType; pFilterDeviceObject->Characteristics = pLowerDeviceObject->Characteristics; pFilterDeviceObject->StackSize = pLowerDeviceObject->StackSize + 1; pFilterDeviceObject->Flags |= pLowerDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE); //next device pTargetDeviceObject = pTargetDeviceObject->NextDevice; } return status; } VOID c2pDetach(IN PDEVICE_OBJECT pDeviceObject) { PC2P_DEV_EXT devExt; BOOLEAN NoRequestsOutstanding = FALSE; devExt = (PC2P_DEV_EXT)pDeviceObject->DeviceExtension; __try { __try { IoDetachDevice(devExt->TargetDeviceObject); devExt->TargetDeviceObject = NULL; IoDeleteDevice(pDeviceObject); devExt->pFilterDeviceObject = NULL; DbgPrint(("Detach Finished\n")); } __except (EXCEPTION_EXECUTE_HANDLER) {} } __finally {} return; } NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING Reg_Path) { NTSTATUS Ret; NTSTATUS status; DbgPrint("DriverEntry\n"); for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) { DriverObject->MajorFunction[i] = General_DisPatch_Fun; } DriverObject->MajorFunction[IRP_MJ_READ] = Read_DisPatch_Fun; DriverObject->MajorFunction[IRP_MJ_POWER] = Power_DisPatch_Fun; DriverObject->MajorFunction[IRP_MJ_PNP] = Pnp_Dispatch_Fun; gDriverObject = DriverObject; DriverObject->DriverUnload = Unload; status = AttachDevices(DriverObject, Reg_Path); return STATUS_SUCCESS; }

浙公网安备 33010602011771号