(二十六)、seven

一、查壳

0
64位的驱动程序

二、IDA静态分析

字符串搜索看到了一串可疑的字符串
 
0
返回Driver
查看函数的时候发现可以驱动名
0
kdbclass 可疑的驱动名字,搜一下
0
驱动键盘过滤
继续进入read的分发函数
0
进入回调函数:
0

三、猜测是迷宫问题

结合字符串
0
与注释
__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;

}

 

posted @ 2022-04-28 23:19  TLSN  阅读(48)  评论(0)    收藏  举报