Author:softworm
Worte driver , Watch the driver to work, only learn driver. First register image loader message routine.
Code:
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 );
//The address immediate hard code, May analysis PE file and use disassemb engine
// Original driver's DriverEntry export:
// leave
// retn 8
//
//
Entry = Base + 0x1111;
Patch = Base + 0x2222;
g_ReturnAddress = Base + 0x3333;
if (!(*(PULONG)Entry == 0x83EC8B55 && *(PUCHAR)(Entry+5) == 0x14)) //Check 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);
}
The function patch two part of original driver
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 );
//The address immediate hard code, May analysis PE file and use disassemb engine
// Original driver's DriverEntry export:
// leave
// retn 8
//
//
Entry = Base + 0x1111;
Patch = Base + 0x2222;
g_ReturnAddress = Base + 0x3333;
if (!(*(PULONG)Entry == 0x83EC8B55 && *(PUCHAR)(Entry+5) == 0x14)) //Check 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);
}
The function patch two part of original driver
DriverEntry entry of original driver, Be designed to get paramter of DriverObject, Because optimize compiler, The paramter is cleared to 0, So first save a share.
Second export of DriverEntry, Here replace dispatch function of DriverObject registered.
Second export of DriverEntry, Here replace dispatch function of DriverObject registered.
Code:
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 ; Original code
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
//Execute original export code 执行原出口代码
__emit 0xC9 //VC6的汇编不支持leave
retn 8
}
}
{
// 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 ; Original code
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
//Execute original export code 执行原出口代码
__emit 0xC9 //VC6的汇编不支持leave
retn 8
}
}
Then may mount oneself code , Start only PassThru :
Code:
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;
}
Then it doesn't matter, Reverse IOCTL code and one by one replace.
{
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;
}
Then it doesn't matter, Reverse IOCTL code and one by one replace.
No comments:
Post a Comment