The CryptDisk driver is now mostly working and I have arrived at a
fork in the development path. There was a lot of experimentation,
trial-and-error, and copy/paste code involved in bringing the driver
to life and it shows. The driver project contains a lot of code that
has been commented out or is never called, and these code barnacles
can cause a lot of grief later. There is the mystery as to why the
current driver refuses to unload when earlier versions did.
I can either continue with the driver project in its current state
and whittle it down. Or I can start a new project and build it up,
pulling in only the pieces of the current project that I actually
need. Starting fresh invariably leads to a better product, but it
means a lull in the project as I spend a couple days rewriting the
same old thing -- lateral progress at best.
So today will be spent creating a new driver project, this time
paying more attention to usability concerns such as mount/unmount
and load/unload.
UPDATE [20170901]: Driver2 was definitely the right decision.
The first task is to make sure I am starting from the proper code
base. I have three active branches:
Unload (10a3547): I used this branch to disable a bunch
of stuff, trying to figure out why the driver would not unload. This
is a crippled version of the driver and can be discarded.
Work (e4c3288): Mount/unmount is working.
master (0efd40a): "Official" branch.
I switched to the Work branch, rebuilt the solution, and tested it
to make sure it was OK. This turned out to be the crippled version,
so I need to revert back a step. This version hung when I tried to
format the disk. This won't be as easy as I hoped, I need to figure
out which version actually works: e4c3288 (HEAD -> Work) Working on Unload.
0efd40a (origin/master, origin/Work, master) Mount/Unmount is now working.
aa3966c Trying to figure out control/disk transition.
6f3d7bb Removed dead code.
4bbc42f Cleaned up the control device creation.
70252b1 Added device enumeration. Cleaning up DeviceCtrl.
fe7f33a This version works.
3662a2a Split Device.cpp into DeviceCtrl.cpp and DeviceDisk.cpp
abbf334 (origin/LoadCreate) Disabled the initial breakpoint.
94a8212 This version mostly works.
dffc77c Trying to figure out why I can't access CryptDisk01.
0b36f1b Fixed a bunch of NtString bugs. Disk device is now being created. Media file is being created. Not creating volu
me link yet.
8a515bf DeviceCtrl now handles the initial mount command. Disk devices are now created on demand.
9f64dfb CryptDriver builds, but is not functional yet. Integrated NtString.
e4cc67b NtString now builds.
b60199f Added NtString class.
7024256 Fixed unload bug. Still no volumes appearing.
7d36d0b Fixed app unmount command.
af4ea4a Added mount/unmount code.
3d90dfe Wrote a lot of CryptDisk code. First complete build.
2d5caf7 Removed dead code.
ee99f13 Added functions to create the NT and DOS device names.
9777eca The driver now unloads properly.
4e438ac Created the control device.
2ae5d08 Added Driver infrastructure.
9d82bd8 Driver builds, loads, and unloads.
c58a2bb Initial CryptDisk commit. Forked from DbgOut13.
Results of testing each version: fe7f33a: I am able to format the disk. 70252b1: BugCheck in CtrlFile::Read() 4bbc42f: Worked. 6f3d7bb: Old loader. Format starts but never completes. 0efd40a: New loader. Format does not work.
The format hang happens when I try to reformat an existing
media file, which is a newly discovered bug that exists in all
versions. This invalidates my testing so I need to start testing from
the top, this time being sure to delete the media file before loading
the driver...
Results: 0efd40a: Format dialog never appears. aa3966c: New loader. Format dialog never appears. 6f3d7bb: Old loader. Format dialog appears but does not complete. 4bbc42f: Old loader. Format is successful.
I need to commit my code much more frequently! I also need
to write up a formal test plan to complete before merging into
master.
One of these versions recreated the zombie device, so now I need to
dump the VM and rebuild it before doing any work on load/unload.
This fun little exercise took about three hours, but now I have a
much better sense of what works and what doesn't. For the next
iteration of the driver I will be avoiding MountManager until much
later (if ever) and concentrate on making sure load/unload,
mount/unmount, and format operation is working at each step.
Driver2
August 30 2017, 1pm
I want to use the driver code from 4bbc42f as my reference for
Driver2, while retaining the latest version of the loader and
everything else. I checkout 4bbc42f and copy the entire CryptDisk
directory tree to CryptDisk.4bbc42f where I can use it as a reference
without constantly switching branches. I switch to the master branch,
merge Work to save it, then switch to the Work branch. I push
everything to my repo in the sky. I switch to Work, then create a new
branch named "Driver2".
Now I am finally ready to create my new Driver2 project. All the
settings and configuration will be exactly like the
existing Driver project. One of the first
changes I want to make is to extract some of the support files from
the Driver project to a separate WinKM library project: Error.c,
New.cpp, NtString.cpp, and System.c. I create the WinKM project
using the same settings.
It took about 40 minutes to create the two new projects and load
CryptDriver v2.0 for the first time. CryptDriver has arrived!
CryptDriver version 2.0.285 [VS12] VS12
DriverEntry=FFFFF80CE3F31000 pDriver=FFFFE38074C1CE60
It is just an empty DriverEntry() at this point. Now I can start pulling
code from the Driver (v1.0) project.
My first task was to track down the
"won't unload"
bug, which was polite enough to show up as soon as I wrote the IRP
handler for the control device. The Driver2 project was still tiny,
making it easier to track down what turned out to be a very obtuse
bug.
Control Worker Thread
DriverEntry() creates the control device. This time I want to
create a worker thread to handle the requests. This should allow me to
create the disk devices on demand without running into context
problems.
I created the IrpThread class to make it easier to add deferred IRP
processing:
I am now about seven hours into Driver2 and I am pleased with the
decision to start afresh. The new driver is already an improvement on
the original.
August 31 2017
I have spent about twelve hours on Driver2 and I now have my first
complete build. This puts me a bit ahead of schedule.
Strange crash: The target blew up without a bugcheck, very little
info. This turned out to be a bad pointer in DeviceDisk::DefRead().
The strange thing is that the IRP had null in both the SystemBuffer
and the MdlAddress. Then the call to
MmGetSystemAddressForMdlSafe() just blew up. This happened
because I forgot to set either DO_BUFFER_IO or DO_DIRECT_IO in the
DeviceDisk->Flags, so the system did neither.
I once again messed up that damn QUERY_DEVICE_NAME. I should just
return sizeof(*pInfo)+2*MAX_PATH and be done with it.
WinDbg's constant failed symbol lookups are still bogging me down.
Copy/Paste programming error: I forgot to change
return(STATUS_SUCCESS); to
return(IrpComplete(pIrp,STATUS_SUCCESS,InfoSz));
SUCCESS! Driver2 now loads, mounts, formats, writes, reads,
and unmounts. The app hangs after the unmount. I forgot to call
IrpComplete() again.
SUCCESS! Driver2 passed the test:
Load
Mount
Open file
Write to file
Unmount
Mount
Open file
Write to file
Unmount
Unload
Driver2 is fully functional in exactly 24 hours, start to finish.
Reformatting is working.
This version creates the disks on demand, not just at load time.
Now that I have a version that seems to be working and is stable, I
want to take some time to create an ioctl trace I can use as a
reference for later. I will log all the ioctls to a compact binary
array which can be downloaded by the app and expanded to text.
WebV7 (C)2018 nlited | Rendered by tikope in 52.453ms | 44.220.184.63