Hi all,
I am developing a filter driver for xp. It encrypts/decrypts the whole
disk except the MBR.
My filter driver is an upper filter over the DiskDrive and FloppyDisk
devices, with SERVICE_BOOT_START StartType.
First, I have tested the driver with the floppy device and it works
perfectly
Then, I installed the driver attaching it, additionally, to the
harddisk device and rebooted the machine.
At boot, the MBR loads two sectors (not encrypted) containing some code
that hooks the int 13h. This code processes CHS and LBA reads decrypting
the resulting buffers. The writings are not allowed.
Additionally, in the first boot, this code (the-two-sectors-code)
encrypts the whole disk except the MBR. Then, it loads the boot sector
and jumps to this code (boot sector code). Now, the boot sector will
continue loading the needed sectors and the int 13h will decrypt them
transparently.
Windows XP boots and shows the login screen. I enter in the session and
the “new hardware wizard” appears saying someting about new hardware
found ¿?. Then, it says that the new hardware is configured and that it
is necessary to reboot the system.
In the next boot (and the next, …), there are possibilities around
80% that scandisk appears due coherency problems in the filesystem.
Why? I suppose that this two weird things (new hardware and coherency
problem) arise because some data corruption in the readings/writings in
the disk. I am lost. I’ve reviewed the code but this is my first driver
and all seems ok, at least for me
I am including the code relative to IRP_MJ_READ and IRP_MJ_WRITE
process and the encryption procedure (a simple dword xor) but if someone
needs more info, please, ask me:
<------------------------------------------------------------------------------->
//
// FCifradorReadWrite
//
NTSTATUS
FCifradorReadWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION IrpS = IoGetCurrentIrpStackLocation (Irp);
PIO_STACK_LOCATION NextIrpS = IoGetNextIrpStackLocation (Irp);
PDEVICE_EXTENSION deviceExtension;
BOOLEAN enter = TRUE;
PUCHAR address;
PMDL ptr;
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
// IRP_MJ_WRITE -> Cipher
if ((IrpS->MajorFunction == IRP_MJ_WRITE) && IrpS->Parameters.Write.Length)
{
for (ptr = Irp->MdlAddress; ptr != NULL; ptr = ptr->Next)
{
address = MmGetSystemAddressForMdlSafe (ptr, HighPagePriority);
// The pages couldn’t be mapped
if (address == NULL)
{
DbgPrint(“filtro_cifrador: FCifradorReadWrite - No pudo mapearse
MdlAddress.\n”);
return STATUS_INSUFFICIENT_RESOURCES;
}
// The sector 0 (MBR) must not be ciphered
if (enter && ((IrpS->Parameters.Write.ByteOffset.QuadPart / 512) == 0))
{
enter = FALSE;
FCifradorCipher (address + 512, MmGetMdlByteCount (ptr) - 512);
}
else
{
FCifradorCipher (address, MmGetMdlByteCount (ptr));
}
}
}
//
// Copy current stack to next stack.
//
*NextIrpS = *IrpS;
// Add the completion routine
IoSetCompletionRoutine (Irp, FCifradorCompletion, DeviceObject, TRUE,
TRUE, TRUE);
//
// Return the results of the call to the disk driver.
//
return IoCallDriver(deviceExtension->TargetDeviceObject, Irp);
}
//
// FCifradorCompletion
//
NTSTATUS
FCifradorCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PIO_STACK_LOCATION IrpS = IoGetCurrentIrpStackLocation (Irp);
BOOLEAN enter = TRUE;
PUCHAR address;
PMDL ptr;
UNREFERENCED_PARAMETER (Context);
// Tratar el IRP
if (IrpS->MajorFunction == IRP_MJ_READ)
{
if (IrpS->Parameters.Read.Length)
{
for (ptr = Irp->MdlAddress; ptr != NULL; ptr = ptr->Next)
{
address = MmGetSystemAddressForMdlSafe (ptr, HighPagePriority);
// The pages couldn’t be mapped
if (address == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
// The sector 0 (MBR) must not be deciphered
if (enter && ((IrpS->Parameters.Read.ByteOffset.QuadPart / 512) == 0))
{
enter = FALSE;
FCifradorCipher (address + 512, MmGetMdlByteCount (ptr) - 512);
}
else
{
FCifradorCipher (address, MmGetMdlByteCount (ptr));
}
}
}
}
else // IRP_MJ_WRITE //
{
if (IrpS->Parameters.Write.Length)
{
for (ptr = Irp->MdlAddress; ptr != NULL; ptr = ptr->Next)
{
address = MmGetSystemAddressForMdlSafe (ptr, HighPagePriority);
// The pages couldn’t be mapped
if (address == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
// The sector 0 (MBR) must not be deciphered
if (enter && ((IrpS->Parameters.Write.ByteOffset.QuadPart / 512) == 0))
{
enter = FALSE;
FCifradorCipher (address + 512, MmGetMdlByteCount (ptr) - 512);
}
else
{
FCifradorCipher (address, MmGetMdlByteCount (ptr));
}
}
}
}
// Check IrPending flag
if (Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
return STATUS_SUCCESS;
}
//
// FCifradorCipher
//
VOID
FCifradorCipher (
IN PUCHAR address,
IN ULONG bytes
)
{
ULONG i;
DWORD t;
if (bytes == 0)
return;
// XOR one dword with 0x01020304
for (i = 0; i < bytes; i += 4)
{
t = 0x00000000;
t = address[i + 3];
t = (t << 8) | address[i + 2];
t = (t << 8) | address[i + 1];
t = (t << 8) | address[i];
t ^= 0x01020304;
address[i] = (BYTE) t;
address[i + 1] = (BYTE) (t >> 8);
address[i + 2] = (BYTE) (t >> 16);
address[i + 3] = (BYTE) (t >> 24);
}
return;
}
<------------------------------------------------------------------------------->
Thanks in advance,
Rafa.