调试某驱动
写个驱动,观察某驱动的运行,学学驱动而已。先注册映像加载通知例程。
PsSetLoadImageNotifyRoutine(LoadImageNotify);
代码:
VOID LoadImageNotify (
PUNICODE_STRING FullImageName,
HANDLE ProcessId,
PIMAGE_INFO ImageInfo
)
{
ANSI_STRING asImageName;
PCHAR Delimiter;
NTSTATUS Status;
ULONG Base;
ULONG Entry;
ULONG Patch;
ULONG i;
RtlUnicodeStringToAnsiString(&asImageName, FullImageName, TRUE);
if (!ImageInfo->SystemModeImage)
{
goto __End; //不是驱动
}
Delimiter = strrchr(asImageName.Buffer, '\\');
if (Delimiter == NULL)
goto __End;
Delimiter++;
if( _strnicmp(Delimiter,"xxx.sys",strlen("xxx.sys")) != 0)
goto __End;
Base = (ULONG)ImageInfo->ImageBase;
DbgPrint("%s Loaded, MappingAddress=%08X, Size=%08X\n",
asImageName.Buffer,
ImageInfo->ImageBase,
ImageInfo->ImageSize );
//这里地址直接硬编码了,可以分析PE文件及使用反汇编引擎(原代码的地址删了,表找我麻烦)
// 原驱动DriverEntry出口:
// leave
// retn 8
//
//
Entry = Base + 0x1111;
Patch = Base + 0x2222;
g_ReturnAddress = Base + 0x3333;
if (!(*(PULONG)Entry == 0x83EC8B55 && *(PUCHAR)(Entry+5) == 0x14)) //检查Entry
{
DbgPrint("Mismatched Entry!\n");
goto __End;
}
if (*(PULONG)Patch != 0x0008C2C9)
{
DbgPrint("Mismatched Patch Point!\n");
goto __End;
}
__asm
{
CLI
MOV EAX, CR0
AND EAX, NOT 10000H //disable WP bit
MOV CR0, EAX
}
*(PUCHAR)Entry = 0xE9;
*(PULONG)(Entry+1) = (ULONG)&SaveDriverObject - (Entry+5);
*(PUCHAR)Patch = 0xE9;
*(PULONG)(Patch+1) = (ULONG)&ReplaceDispatch - (Patch+5);
__asm
{
MOV EAX, CR0
OR EAX, 10000H //enable WP bit
MOV CR0, EAX
STI
}
__End:
RtlFreeAnsiString(&asImageName);
}
原驱动的DriverEntry入口,目的是获取参数DriverObject,因为编译器的优化,在DriverEntry
执行过程中这个参数被清0了, 所以先保存一份。
第2是DriverEntry的出口,在这里替换DriverObject内注册的派遣函数。
代码:
VOID __declspec (naked) SaveDriverObject()
{
// 55 push ebp
// 8B EC mov ebp, esp
// 83 EC 14 sub esp, 14h
__asm {
pushad
mov eax, [esp+20h+4]
mov g_DrvObj, eax
popad
push ebp ; 原代码
mov ebp, esp
sub esp, 14h
jmp [g_ReturnAddress]
}
}
VOID __declspec (naked) ReplaceDispatch()
{
__asm {
pushad
mov eax, g_DrvObj
mov ecx, [eax+18h] ; DriverExtension
mov ebx, [eax+34h] ; Unload
mov g_Unload, ebx
mov ebx, MyUnload
mov [eax+34h], ebx
mov ebx, [eax+38h]
mov g_Create, ebx
mov ebx, MyCreateCloseCleanup
mov [eax+38h], ebx ; Create
mov [eax+40h], ebx ; Close
mov [eax+80h], ebx ; CleanUp
mov ebx, [eax+70h]
mov g_DeviceControl, ebx
mov ebx, MyDeviceControl
mov [eax+70h], ebx
popad
//执行原出口代码
__emit 0xC9 //VC6的汇编不支持leave
retn 8
}
}
代码:
VOID MyUnload( PDRIVER_OBJECT DriverObject )
{
DbgPrint("MyUnload\n");
((PDRIVER_UNLOAD)g_Unload)(DriverObject);
return;
}
NTSTATUS MyCreateCloseCleanup( PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DbgPrint("MyCreateCloseCleanup\n");
return ((PDRIVER_DISPATCH)g_Create)(DeviceObject, Irp);
}
NTSTATUS MyDeviceControl( PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION irpSp;
PVOID inputBuff, outputBuff;
ULONG inputLen, outputLen, ctlCode;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
irpSp = IoGetCurrentIrpStackLocation(Irp);
// Buffered io
inputBuff = Irp->AssociatedIrp.SystemBuffer;
outputBuff = Irp->AssociatedIrp.SystemBuffer;
inputLen = irpSp->Parameters.DeviceIoControl.InputBufferLength;
outputLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
ctlCode = irpSp->Parameters.DeviceIoControl.IoControlCode;
switch (ctlCode)
{
case IOCTL_INIT:
//逆的代码...
break;
default:
DbgPrint("DeviceControl : Not Implemented IOCTL=%08X\n", ctlCode);
return ((PDRIVER_DISPATCH)g_DeviceControl)(DeviceObject, Irp);
break;
}
__End:
Irp->IoStatus.Information = outputLen;
Irp->IoStatus.Status = Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return Status;
}
实现一个完整的,当然只实现功能部分,保护的代码就不要了。加载自己的驱动站住坑,
想干啥干啥吧。