调试某驱动
写个驱动,观察某驱动的运行,学学驱动而已。先注册映像加载通知例程。
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; }
实现一个完整的,当然只实现功能部分,保护的代码就不要了。加载自己的驱动站住坑,
想干啥干啥吧。