Log in

View Full Version : How does this cdrom driver hold the read data before return?


kcynice
October 14th, 2008, 03:31
There is a cdrom driver which simply implements IRP_MJ_READ routine by calling IofCallDriver. But the driver can decrypt the data in special disc. If so, when and how the driver gets the chance to hold the data read by lower level driver and decrypt it?

Regards

disavowed
October 14th, 2008, 14:51
Disassemble the driver and find out?

kcynice
October 14th, 2008, 20:37
yes. I had just disassembled the driver and found its IRP_MJ_READ and other most routines were the same. I am not good at driver programming but just know the basic acknowledge about it. any idea?

Kayaker
October 15th, 2008, 00:46
I'm afraid the answer is still the same, you're going to have to learn to interpret the disassembly.

"IRP_MJ_READ and other most routines were the same"

If you're saying what I think you're saying, all the IRP_MJ_ MajorFunction routines may point to a single dispatch routine which uses a switch statement to direct the code, like:

Code:

// Dispatch on MajorFunction
switch (IrpStack->MajorFunction)
{
// Default these two IRPs
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
break;

case IRP_MJ_READ:
...

case IRP_MJ_DEVICE_CONTROL:


Interpret this and you should find IRP_MJ_READ. Secondary option - use Softice DRIVER command to find address of IRP_MJ_READ.


At a minimum, you should learn about the IRP structure and incorporate the named field definitions into your IDA disassembly. Definition of fields such as Irp->MdlAddress or Irp->AssociatedIrp.SystemBuffer for example are very useful pointers to data transfer.

Do yourself a favor and read the first google hits of both Msdn and Osronline for 'IRP_MJ_READ'. Then give yourself some time to learn a bit about driver programming. Get the DDK and look up the API's the driver uses.


For your specific case, if your driver is communicating with usermode, you might be looking for a shared user MDL mapping. Just a big chunk of bytes that undergoes what looks like a decryption routine. A little digging you might be able to find it.

Kayaker

kcynice
October 15th, 2008, 08:58
Yes, like you said, the driver mapped most of its IRP_MJ_ MajorFunction routines may point to a single dispatch routine, which just simply call IofCallDriver. I wrote a small test program using ReadFile to test. It's strange that when ReadFile was called, the system procedure didn't reach the IRP_MJ_READ routine.

deroko
October 15th, 2008, 11:46
Maybe because it was using FastIoRead

kcynice
October 16th, 2008, 03:00
Quote:
[Originally Posted by deroko;77382]Maybe because it was using FastIoRead


Maybe. and i have researched for many documents about it, but i couldn't understand FastIoRead well. So, would you like to give me more details? for example where should i insert some breakpoints, etc?

deroko
October 16th, 2008, 07:06
ok here is example how to find FastIoRead:

Code:

0: kd> !object \Filesystem\ntfs
Object: 8a6822a0 Type: (8a714ca0) Driver
ObjectHeader: 8a682288 (old version)
HandleCount: 0 PointerCount: 6
Directory Object: e1741e08 Name: Ntfs
0: kd> dt nt!_DRIVER_OBJECT 8a6822a0
+0x000 Type : 4
+0x002 Size : 168
+0x004 DeviceObject : 0x8a31a770 _DEVICE_OBJECT
+0x008 Flags : 0x92
+0x00c DriverStart : 0xb9d3b000
+0x010 DriverSize : 0x8c600
+0x014 DriverSection : 0x8a7165b0
+0x018 DriverExtension : 0x8a682348 _DRIVER_EXTENSION
+0x01c DriverName : _UNICODE_STRING "\FileSystem\Ntfs"
+0x024 HardwareDatabase : 0x809a6260 _UNICODE_STRING "\REGISTRY\MACHINE\HARDW
ARE\DESCRIPTION\SYSTEM"
+0x028 FastIoDispatch : 0xb9d5a9a0 _FAST_IO_DISPATCH
+0x02c DriverInit : 0xb9dc0384 long Ntfs!GsDriverEntry+0
+0x030 DriverStartIo : (null)
+0x034 DriverUnload : (null)
+0x038 MajorFunction : [28] 0xb9d60e01 long Ntfs!NtfsFsdCreate+0
0: kd> dt nt!_FAST_IO_DISPATCH b9d5a9a0
+0x000 SizeOfFastIoDispatch : 0x70
+0x004 FastIoCheckIfPossible : 0xb9d750e3 unsigned char Ntfs!NtfsFastIoC
heckIfPossible+0
+0x008 FastIoRead : 0xb9d5bd57 unsigned char Ntfs!NtfsCopyReadA+0
+0x00c FastIoWrite : 0xb9d7a665 unsigned char Ntfs!NtfsCopyWriteA+0

+0x010 FastIoQueryBasicInfo : 0xb9d6168e unsigned char Ntfs!NtfsFastQuer
yBasicInfo+0
+0x014 FastIoQueryStandardInfo : 0xb9d6017e unsigned char Ntfs!NtfsFastQ
ueryStdInfo+0
+0x018 FastIoLock : 0xb9d7b30f unsigned char Ntfs!NtfsFastLock+0
+0x01c FastIoUnlockSingle : 0xb9d7b415 unsigned char Ntfs!NtfsFastUnlock
Single+0
+0x020 FastIoUnlockAll : 0xb9db48f4 unsigned char Ntfs!NtfsFastUnlockAl
l+0
+0x024 FastIoUnlockAllByKey : 0xb9db4a39 unsigned char Ntfs!NtfsFastUnlo
ckAllByKey+0
+0x028 FastIoDeviceControl : (null)
+0x02c AcquireFileForNtCreateSection : 0xb9d5ba3a void Ntfs!NtfsAcquireF
orCreateSection+0
+0x030 ReleaseFileForNtCreateSection : 0xb9d5ba81 void Ntfs!NtfsReleaseF
orCreateSection+0
+0x034 FastIoDetachDevice : (null)
+0x038 FastIoQueryNetworkOpenInfo : 0xb9da3052 unsigned char Ntfs!NtfsFa
stQueryNetworkOpenInfo+0
+0x03c AcquireForModWrite : 0xb9d67c12 long Ntfs!NtfsAcquireFileForModWr
ite+0
+0x040 MdlRead : 0xb9da3166 unsigned char Ntfs!NtfsMdlReadA+0
+0x044 MdlReadComplete : 0x80811afa unsigned char nt!FsRtlMdlReadComple
teDev+0
+0x048 PrepareMdlWrite : 0xb9da34e0 unsigned char Ntfs!NtfsPrepareMdlWr
iteA+0
+0x04c MdlWriteComplete : 0x80894bec unsigned char nt!FsRtlMdlWriteCompl
eteDev+0
+0x050 FastIoReadCompressed : (null)
+0x054 FastIoWriteCompressed : (null)
+0x058 MdlReadCompleteCompressed : (null)
+0x05c MdlWriteCompleteCompressed : (null)
+0x060 FastIoQueryOpen : 0xb9d5ffb8 unsigned char Ntfs!NtfsNetworkOpenC
reate+0
+0x064 ReleaseForModWrite : (null)
+0x068 AcquireForCcFlush : 0xb9d5b8e2 long Ntfs!NtfsAcquireFileForCcFlus
h+0
+0x06c ReleaseForCcFlush : 0xb9d5b908 long Ntfs!NtfsReleaseFileForCcFlus
h+0
0: kd>


in softice it could be easier by simply looking at FastIO displayed by driver command. (offset +8)

kcynice
October 16th, 2008, 19:21
Quote:
[Originally Posted by deroko;77391]ok here is example how to find FastIoRead:

in softice it could be easier by simply looking at FastIO displayed by driver command. (offset +8)


The example you gave me seemed generated by windbg, right? does it support not inner structures or drivers of windows itself? Unfortunately, my xp crashed yesterday, so i haven't try your advice. You said offset+8 is the fastio, what's the base address?

And, if the driver use fast io, its IRP_MJ_READ routine would not called by the system when an user app use ReadFile to read data?

And i will reinstall my xp system as soon as possible to try you advice, thanks.
---------added--------------
i have tried that driver by driver command, softICE showed 'FastIoDispatch*:00000000'. Does this mean that this driver doesn't use FastIoDispatch?

Regards

Kayaker
October 16th, 2008, 22:24
Quote:
[Originally Posted by kcynice;77396]softICE showed 'FastIoDispatch*:00000000'. Does this mean that this driver doesn't use FastIoDispatch?


Yes that's right. Though it was a good suggestion.

This may not be a clue to your problem, but there is also the DriverStartIo routine which should be ruled out as well. It's apparently used for managing pending I/O Request Packets, for example by SCSI Port drivers.

By chance I recently generated a list of drivers from my own system which use FastIoDispatch and DriverStartIo routines.

Since the system Cdrom driver uses DriverStartIo, maybe yours does as well and is somehow involved.


Code:

Cdrom : DriverStartIo F9EEC51D
i8042prt : DriverStartIo F9F5B974
Beep : DriverStartIo FA3C151A
atapi : DriverStartIo F9D6C7C6
vmscsi : DriverStartIo F9D5040E
TermDD : DriverStartIo FA031926
Fdc : DriverStartIo FA195F34

IpNat : FastIoDispatch F8561C80
LGTO_Sync : FastIoDispatch FA260FB8
HTTP : FastIoDispatch F7CB95E8
WMIxWDM : FastIoDispatch 80561480
Null : FastIoDispatch FA581380
ACPI : FastIoDispatch F9E7A520
AFD : FastIoDispatch F860C030

kcynice
October 17th, 2008, 04:04
But, the problem is, the DriverStartIo routine still wouldn't be called.
and my cdrom shows a list of its drivers:

****.sys (the driver i wanna reverse)
cdrom.sys
imapi.sys
redbook.sys
storprop.sys

so, i set a bp at cdrom.sys' IRP_MJ_READ routine too, but it doesn't stop at the bp although my test program calls ReadFile. Why?

deroko
October 17th, 2008, 06:28
Quote:
[Originally Posted by kcynice;77396]itself? Unfortunately, my xp crashed yesterday, so i haven't try your advice. You said offset+8 is the fastio, what's the base address?


offset + 8 in FastIoDispatch is FastIoRead, but if driver doesn't have FastIo then this won't be used. Generally speaking FastIo is specific for Filesystem drivers, and filesystem filters. it's used to query fs filterdriver fast. For example: once you read file it will be cached, so no need to send irp_mj_read again, as filter driver can read from this cache and it will perfrom memcy(user_buffer, cache, size) in try/except block. the other solution to block fastios is to write driver which will hook all fastios in base filesystem driver and return false, this will ensure that all requests go trough dispath routines

the problem with your code is that you are bpx-in IRP_MJ_READ of cdrom and if I'm not wrong this is storage device, and in such is different from cdfs.sys which is filesystem, so when you issue ReadFile for a file on your cdrom, you will not be getting to cdrom.sys, you will be getting to cdfs.sys or udfs.sys where you will see eventually CcCopyRead(above mentioned memcpy) which actually reads from cache. To learn more about relation between cdrom.sys and cdfs.sys you coulde check sources which come with WDK, although this won't be an easy task, as cdfs.sys and cdrom both have around 1.5mb of source code

aionescu
October 20th, 2008, 10:50
If you want to PM me that driver I can take a look for you.

Are you *sure* IRP_MJ_READ isn't actually doing anything?

Are you *sure* it's not using Fast I/O?

Sorry but I don't trust SI, WinDBG is a much better tool.

Also, are you sure this driver does the decryption? Maybe the .sys extracts another .sys and loads it dynamically? Is the binary obfuscated at all?

If your ReadFile isn't generating a fast I/O read or an IRP_MJ_READ to get to the driver, then it's not on the driver stack, not loaded, or you weren't sending the Read to the right device object...

kcynice
October 21st, 2008, 21:42
I am sure i was sending the Read to the right device object, because i just translate the file's absolute path in the disc to call CreateFile. When i use ReadFile to read data from the file handle, IRP_MJ_READ routine would not be called. As i said before, its FastIoDispatch pointer is 0x00000000, so i think it didn't use FastIo. But i tried to set bp at somewhere of the driver(try here and where) and found that it would be broken if the file was first read.
Any idea?
Thanks for your reply