初学驱动逆向,在《windows驱动开发技术详解》中随便找个例子逆逆看 [ \chapter09\SpecialStartIOTest ]。
水平很菜,各路牛人笑过。
逆向该例子的DriverEntry和CreateDevice函数,这两个函数在《windows驱动开发技术详解》的例子中十分常见。
并逆向的本范例驱动的核心部分 HelloDDKRead 函数,没什么技术含量。
经验:需要熟悉各数据结构内部的参数地址,便能方便地理解反汇编中的参数定位,相关结构可以通过WinDBG查看[DRIVER_OBJECT / DEVICE_OBJECT / Irp]。
DriverEntry
NTSTATUS __stdcall DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
public _DriverEntry@8
_DriverEntry@8 proc near
status= dword ptr -4
pDriverObject= dword ptr 8
pRegistryPath= dword ptr 0Ch
push ebp // 保护现场
mov ebp, esp
push ecx
push offset aEnterDriverent ; "Enter DriverEntry\n"
call _DbgPrint // KdPrint(("Enter DriverEntry\n"));
add esp, 4 // 申请空间
// 填充 Unload 与 IRP
// pDriverObject->DriverUnload = HelloDDKUnload;
mov eax, [ebp+pDriverObject]
mov dword ptr [eax+34h], offset ?HelloDDKUnload@@YGXPAU_DRIVER_OBJECT@@@Z ; HelloDDKUnload(_DRIVER_OBJECT *)
// pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutin;
mov ecx, [ebp+pDriverObject]
mov dword ptr [ecx+38h], offset ?HelloDDKDispatchRoutin@@YGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z ; HelloDDKDispatchRoutin(_DEVICE_OBJECT *,_IRP *)
// pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutin;
mov edx, [ebp+pDriverObject]
mov dword ptr [edx+40h], offset ?HelloDDKDispatchRoutin@@YGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z ; HelloDDKDispatchRoutin(_DEVICE_OBJECT *,_IRP *)
// pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutin;
mov eax, [ebp+pDriverObject]
mov dword ptr [eax+48h], offset ?HelloDDKDispatchRoutin@@YGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z ; HelloDDKDispatchRoutin(_DEVICE_OBJECT *,_IRP *)
// pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKRead;
mov ecx, [ebp+pDriverObject]
mov dword ptr [ecx+44h], offset ?HelloDDKRead@@YGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z ; HelloDDKRead(_DEVICE_OBJECT *,_IRP *)
// pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = HelloDDKDispatchRoutin;
mov edx, [ebp+pDriverObject]
mov dword ptr [edx+80h], offset ?HelloDDKDispatchRoutin@@YGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z ; HelloDDKDispatchRoutin(_DEVICE_OBJECT *,_IRP *)
// pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HelloDDKDispatchRoutin;
mov eax, [ebp+pDriverObject]
mov dword ptr [eax+70h], offset ?HelloDDKDispatchRoutin@@YGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z ; HelloDDKDispatchRoutin(_DEVICE_OBJECT *,_IRP *)
// pDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = HelloDDKDispatchRoutin;
mov ecx, [ebp+pDriverObject]
mov dword ptr [ecx+50h], offset ?HelloDDKDispatchRoutin@@YGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z ; HelloDDKDispatchRoutin(_DEVICE_OBJECT *,_IRP *)
// pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = HelloDDKDispatchRoutin;
mov edx, [ebp+pDriverObject]
mov dword ptr [edx+78h], offset ?HelloDDKDispatchRoutin@@YGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z ; HelloDDKDispatchRoutin(_DEVICE_OBJECT *,_IRP *)
// pDriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HelloDDKDispatchRoutin;
mov eax, [ebp+pDriverObject]
mov dword ptr [eax+94h], offset ?HelloDDKDispatchRoutin@@YGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z ; HelloDDKDispatchRoutin(_DEVICE_OBJECT *,_IRP *)
// status = CreateDevice(pDriverObject);
mov ecx, [ebp+pDriverObject]
push ecx ; pDriverObject
call ?CreateDevice@@YGJPAU_DRIVER_OBJECT@@@Z ; CreateDevice(_DRIVER_OBJECT *)
mov [ebp+status], eax
// KdPrint((“Leave DriverEntry\n”));
push offset aLeaveDriverent ; "Leave DriverEntry\n"
call _DbgPrint
// return status;
add esp, 4
mov eax, [ebp+status]
mov esp, ebp // 恢复现场
pop ebp // 恢复现场
retn 8
_DriverEntry@8 endp
源码参考:
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
NTSTATUS status;
KdPrint(("Enter DriverEntry\n"));
//设置卸载函数
pDriverObject->DriverUnload = HelloDDKUnload;
//设置派遣函数
pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKRead;
pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = HelloDDKDispatchRoutin;
pDriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = HelloDDKDispatchRoutin;
//创建驱动设备对象
status = CreateDevice(pDriverObject);
KdPrint(("Leave DriverEntry\n"));
return status;
}
CreateDevice
int __stdcall CreateDevice(_DRIVER_OBJECT *pDriverObject)
?CreateDevice@@YGJPAU_DRIVER_OBJECT@@@Z proc near
DeviceName= _UNICODE_STRING ptr -24h
pDevExt= dword ptr -1Ch
devName= _UNICODE_STRING ptr -18h
status= dword ptr -10h
pDevObj= dword ptr -0Ch
symLinkName= _UNICODE_STRING ptr -8
pDriverObject= dword ptr 8
push ebp
mov ebp, esp // 保护现场
// RtlInitUnicodeString(&devName, "\\Device\\MyDDKDevice");
sub esp, 24h // 申请空间
push offset SourceString // "\\Device\\MyDDKDevice"
lea eax, [ebp+devName]
push eax ; DestinationString
call ds:__imp__RtlInitUnicodeString@8 ; RtlInitUnicodeString(x,x)
// DeviceName.Length = devName.Length
mov ecx, dword ptr [ebp+devName.Length]
mov dword ptr [ebp+DeviceName.Length], ecx
// DeviceName.Buffer = devName.Buffer
mov edx, [ebp+devName.Buffer]
mov [ebp+DeviceName.Buffer], edx
// IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), &(UNICODE_STRING)DeviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
lea eax, [ebp+pDevObj]
push eax ; DeviceObject
push 1 ; Exclusive
push 0 ; DeviceCharacteristics
push 22h ; DeviceType
lea ecx, [ebp+DeviceName]
push ecx ; DeviceName
push 28h ; DeviceExtensionSize
mov edx, [ebp+pDriverObject]
push edx ; DriverObject
call ds:__imp__IoCreateDevice@28 ; IoCreateDevice(x,x,x,x,x,x,x)
// if (!NT_SUCCESS(status))
mov [ebp+status], eax
cmp [ebp+status], 0
jge short loc_150E9
// FALSE
mov eax, [ebp+pDevObj] // pDevObj
mov ecx, [eax+1Ch] // pDevObj->Flags
or ecx, 4 // Flags |= DO_BUFFERED_IO;
mov edx, [ebp+pDevObj] // pDevObj
mov [edx+1Ch], ecx // pDevObj->Flags |= DO_BUFFERED_IO;
mov eax, [ebp+pDevObj] // pDevObj
mov ecx, [eax+28h] // pDevObj->DeviceExtension
mov [ebp+pDevExt], ecx // pDevExt = pDevObj->DeviceExtension [格式需要转换]
mov edx, [ebp+pDevExt]
mov eax, [ebp+pDevObj]
mov [edx], eax // pDevExt->pDevice = pDevObj; [设备拓展的第一个参数,遂无偏移]
mov ecx, [ebp+pDevExt]
mov edx, dword ptr [ebp+devName.Length]
mov [ecx+4], edx // 设备拓展第二个参数
mov eax, [ebp+devName.Buffer]
mov [ecx+8], eax // pDevExt->ustrDeviceName = devName;
push 14h ; size_t
push 0 ; int
mov ecx, [ebp+pDevExt]
add ecx, 14h // 设备拓展第四个参数
push ecx ; void *
call _memset // _memset(&pDevExt->device_queue, 0, sizeof(pDevExt->device_queue));
add esp, 0Ch // 申请空间
mov edx, [ebp+pDevExt]
add edx, 14h // 设备拓展第四个参数
push edx ; DeviceQueue
call ds:__imp__KeInitializeDeviceQueue@4 ; KeInitializeDeviceQueue(x) // KeInitializeDeviceQueue(&pDevExt->device_queue);
push offset a??Helloddk ; "\\??\\HelloDDK"
lea eax, [ebp+symLinkName]
push eax ; DestinationString
call ds:__imp__RtlInitUnicodeString@8 ; RtlInitUnicodeString(x,x) // RtlInitUnicodeString(&symLinkName, "\\??\\HelloDDK");
mov ecx, [ebp+pDevExt]
mov edx, dword ptr [ebp+symLinkName.Length]
mov [ecx+0Ch], edx
mov eax, [ebp+symLinkName.Buffer]
mov [ecx+10h], eax
lea ecx, [ebp+devName]
push ecx ; DeviceName
lea edx, [ebp+symLinkName]
push edx ; SymbolicLinkName
call ds:__imp__IoCreateSymbolicLink@8 ; IoCreateSymbolicLink(x,x) // IoCreateSymbolicLink(&SymbolicLinkName, DevName);
// if(!NT_SUCCESS(status))
mov [ebp+status], eax
cmp [ebp+status], 0
jge short loc_1517C
// TRUE
mov eax, [ebp+pDevObj]
push eax ; DeviceObject
call ds:__imp__IoDeleteDevice@4 ; IoDeleteDevice(x) // IoDeleteDevice(pDevObj);
mov eax, [ebp+status]
jmp short loc_1517E
源码参考:
NTSTATUS CreateDevice (
IN PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
//创建设备名称
UNICODE_STRING devName;
RtlInitUnicodeString(&devName,L"\\Device\\MyDDKDevice");
//创建设备
status = IoCreateDevice( pDriverObject,
sizeof(DEVICE_EXTENSION),
&(UNICODE_STRING)devName,
FILE_DEVICE_UNKNOWN,
0, TRUE,
&pDevObj );
if (!NT_SUCCESS(status))
return status;
pDevObj->Flags |= DO_BUFFERED_IO;
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
pDevExt->pDevice = pDevObj;
pDevExt->ustrDeviceName = devName;
RtlZeroBytes(&pDevExt->device_queue,sizeof(pDevExt->device_queue));
KeInitializeDeviceQueue(&pDevExt->device_queue);
//创建符号链接
UNICODE_STRING symLinkName;
RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");
pDevExt->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink( &symLinkName,&devName );
if (!NT_SUCCESS(status))
{
IoDeleteDevice( pDevObj );
return status;
}
return STATUS_SUCCESS;
}
IRP_MJ_READ
// 第一段:整个函数所有变量的定义。
pDevExt= dword ptr -8 // 堆栈:PDEVICE_EXTENSION pDevExt [dword ptr -8]
oldirql= byte ptr -4 // 堆栈:KIRQL oldirql [byte ptr -4]
pDevObj= dword ptr 8 // 参数:PDEVICE_OBJECT pDevObj
pIrp= dword ptr 0Ch // 参数:PIRP pIrp
// 第二段:KdPrint(("Enter HelloDDKRead\n"));
push ebp
mov ebp, esp // 保护现场
sub esp, 8 // 开拓8个字节的空间
push offset aEnterHelloddkr // "Enter HelloDDKRead\n"
call _DbgPrint
// 第三段:PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
add esp, 4 // 开拓4字节空间
mov eax, [ebp+pDevObj] // 定位到 pDevObj
mov ecx, [eax+28h] // 定位到 pDevObj+28h,即为 pDevObj->DeviceExtension
mov [ebp+pDevExt], ecx // 需要加上参数的转换,语句:pDevExt = pDevObj->DeviceExtension;
// 第四段:IoMarkIrpPending(pIrp);
// #define IoMarkIrpPending( Irp ) ( IoGetCurrentIrpStackLocation( (Irp) )->Control |= SL_PENDING_RETURNED )
// #define IoGetCurrentIrpStackLocation( Irp ) ( (Irp)->Tail.Overlay.CurrentStackLocation )
mov edx, [ebp+pIrp] // 定位到 pIrp
mov eax, [edx+60h] // 定位到 pIrp+60h,即为 Irp->Tail.Overlay.CurrentStackLocation
mov cl, [eax+3] // 定位到 ->Control
or cl, 1 // 或运算,SL_PENDING_RETURNED 0x01
mov edx, [ebp+pIrp]
mov eax, [edx+60h]
mov [eax+3], cl // 或运算结果赋值给 Irp->Tail.Overlay.CurrentStackLocation
// 第五段:IoSetCancelRoutine(pIrp,OnCancelIRP)
// #define IoSetCancelRoutine( Irp, NewCancelRoutine ) ( \
// (PDRIVER_CANCEL) InterlockedExchangePointer( (PVOID *) &(Irp)->CancelRoutine, (PVOID) (NewCancelRoutine) ) )
mov edx, offset ?OnCancelIRP@@YGXPAU_DEVICE_OBJECT@@PAU_IRP@@@Z // OnCancelIRP(_DEVICE_OBJECT *,_IRP *)
mov ecx, [ebp+pIrp]
add ecx, 38h // Irp -> CancelRoutine
call ds:__imp_@InterlockedExchange@8 // InterlockedExchange(x,x)
// 第六段:KeRaiseIrql(DISPATCH_LEVEL, &oldirql)
// #define DISPATCH_LEVEL 2 // Dispatcher level
// #define KeRaiseIrql(a,b) *(b) = KfRaiseIrql(a)
mov cl, 2
call ds:__imp_@KfRaiseIrql@4 // KfRaiseIrql(x)
mov [ebp+oldirql], al // 将函数调用结果存入oldirql
// 第七段:KdPrint(("HelloDDKRead irp :%x\n", pIrp));
mov ecx, [ebp+pIrp]
push ecx
push offset aHelloddkreadIr ; "HelloDDKRead irp :%x\n"
call _DbgPrint
// 第八段:KdPrint(("DeviceQueueEntry:%x\n", pIrp->Tail.Overlay.DeviceQueueEntry));
add esp, 8
mov edx, [ebp+pIrp]
add edx, 40h // pIrp->40h,即 pIrp->Tail.Overlay.DeviceQueueEntry
push edx
push offset aDevicequeueent ; "DeviceQueueEntry:%x\n"
call _DbgPrint
// 第九段:if (!KeInsertDeviceQueue(&pDevExt->device_queue, &pIrp->Tail.Overlay.DeviceQueueEntry));
add esp, 8
mov eax, [ebp+pIrp]
add eax, 40h // pIrp->40h,即 pIrp->Tail.Overlay.DeviceQueueEntry
push eax // DeviceQueueEntry
mov ecx, [ebp+pDevExt] // 定位到 pDevExt
add ecx, 14h // pDevExt->14h,即是 &pDevExt->device_queue
push ecx // DeviceQueue
call ds:__imp__KeInsertDeviceQueue@8 // KeInsertDeviceQueue(x,x)
and eax, 0FFh // 取反
test eax, eax // 判断
jnz short loc_141ED // 跳转
// 第十段:[判断为真] MyStartIo(pDevObj,pIrp);
mov edx, [ebp+pIrp]
push edx // 参数:pFistIrp
mov eax, [ebp+pDevObj]
push eax // 参数:DeviceObject
call ?MyStartIo@@YGXPAU_DEVICE_OBJECT@@PAU_IRP@@@Z // MyStartIo(_DEVICE_OBJECT *,_IRP *)
// 第十一段:[判断为假] KeLowerIrql(oldirql);
mov cl, [ebp+oldirql] // 定位参数 oldirql
call ds:__imp_@KfLowerIrql@4 // KfLowerIrql(x)
// 第十二段:KdPrint(("Leave HelloDDKRead\n"));
push offset aLeaveHelloddkr // "Leave HelloDDKRead\n"
call _DbgPrint
// 返回STATUS_PENDING状态:return STATUS_PENDING;
add esp, 4
mov eax, 103h // #define STATUS_PENDING ((NTSTATUS)0x00000103L) // winnt
mov esp, ebp // 恢复现场
pop ebp // 恢复现场
retn 8
?HelloDDKRead@@YGJPAU_DEVICE_OBJECT@@PAU_IRP@@@Z endp
源码对照:
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
{
KdPrint(("Enter HelloDDKRead\n"));
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
//将IRP设置为挂起
IoMarkIrpPending(pIrp);
IoSetCancelRoutine(pIrp,OnCancelIRP);
KIRQL oldirql;
//提升IRP至DISPATCH_LEVEL
KeRaiseIrql(DISPATCH_LEVEL, &oldirql);
KdPrint(("HelloDDKRead irp :%x\n",pIrp));
KdPrint(("DeviceQueueEntry:%x\n",&pIrp->Tail.Overlay.DeviceQueueEntry));
if (!KeInsertDeviceQueue(&pDevExt->device_queue, &pIrp->Tail.Overlay.DeviceQueueEntry))
MyStartIo(pDevObj,pIrp);
//将IRP降至原来IRQL
KeLowerIrql(oldirql);
KdPrint(("Leave HelloDDKRead\n"));
//返回pending状态
return STATUS_PENDING;
}