TrueCrypt のソースをちょっと見てみたのだが、大きくてよく分からない。もっと基本的なものでソースコードがあるものがないか探してみたところ結構見つかった。
このあたりをビルドできるか見てみて、方針を決めようと思う。
ついでなので、ファイルシステム(Installable File System Driver :IFS)もいくつか発見。
基本的なことを知りたければ、EXT2IFS を見てみるのが良さそう。使うのなら、Ext2Fsd -- なのか? ちなみに、EXT2IFS 以外は、ext3 にも対応しているし、インストーラもある。
filedisk を MinGW でコンパイルしてみた。
crosscrypt を見ると、filedisk.h filedisk.c を使っていてベースにしているみたいなので、filedisk をコンパイルすることにした。
実際やってみると、vfd のときとほとんど同じところが引っかかる。具体的には、PSECURITY_CLIENT_CONTEXT と PsRevertToSelf 。あと、NtAdjustPrivilegesToken 関係。
同じような感じなら、ファイルを 仮想ディスクに見せるという基本機能の filedisk をベースにした方が良さそう。
というわけで、同じように ビルドだけはできるものを作ってみた。(ドライバのみ)
→
http://nmj.sumomo.ne.jp/arc/filedisk-wk001.tgzあと、オリジナルをミラー
→
http://nmj.sumomo.ne.jp/arc/filedisk-14.zipとりあえず、オリジナルの filedisk.sys と nm で比較 (__imp_ シンボルのみ )
mingw 版 (wk001) にだけあるもの
__imp__ExAllocatePool@8
__imp__ExInterlockedInsertTailList@12
__imp__ExInterlockedRemoveHeadList@8
__imp__MmMapLockedPagesSpecifyCache@24
__imp__memcpy
__imp__memset
オリジナルだけにあるもの
__imp_@ExfInterlockedInsertTailList@12
__imp_@ExfInterlockedRemoveHeadList@8
__imp__DbgPrint
__imp__ExAllocatePoolWithTag@12
__imp__KeGetCurrentIrql@0
__imp__MmMapLockedPages@8
__imp__PsRevertToSelf@0
__imp__RtlAssert@16
__imp__SeCreateClientSecurity@16
__imp__SeImpersonateClient@8
__imp__SeTokenType@4
両方にあるもの
__imp_@IofCompleteRequest@8
__imp_@ObfDereferenceObject@4
__imp__ExFreePool@4
__imp__IoCreateDevice@28
__imp__IoDeleteDevice@4
__imp__KeGetCurrentThread@0
__imp__KeInitializeEvent@12
__imp__KeInitializeSpinLock@4
__imp__KeSetEvent@12
__imp__KeSetPriorityThread@8
__imp__KeWaitForSingleObject@20
__imp__NtAdjustPrivilegesToken@24
__imp__ObReferenceObjectByHandle@24
__imp__PsCreateSystemThread@28
__imp__PsTerminateSystemThread@4
__imp__RtlAnsiStringToUnicodeString@12
__imp__RtlAppendUnicodeToString@8
__imp__RtlCopyUnicodeString@8
__imp__RtlFreeUnicodeString@4
__imp__RtlInitUnicodeString@8
__imp__RtlQueryRegistryValues@20
__imp__ZwClose@4
__imp__ZwCreateDirectoryObject@12
__imp__ZwCreateFile@44
__imp__ZwMakeTemporaryObject@4
__imp__ZwOpenProcessToken@12
__imp__ZwQueryInformationFile@20
__imp__ZwReadFile@36
__imp__ZwSetInformationFile@20
__imp__ZwWriteFile@36
__imp__swprintf
ついでに、ext2ifs-0.3-src.zip を MinGW でコンパイル。
ヘッダファイルの変更とか大分手馴れてきたのだが...
try except() finally
__try __execpt()
がない。自分で作るほどの知識もないし... 困った。
とりあえず、適当に define してコンパイルだけ通したところ
CcInitializeCacheMap@20
CcPinRead@24
CcUnpinData@4
FsRtlIsNtstatusExpected@4
IoCreateStreamFileObject@8
IoGetTopLevelIrp@0
IoIsOperationSynchronous@4
IoRegisterFileSystem@4
IoSetTopLevelIrp@4
の 9 個の undefined が出た。
とりあえず、ファイルシステム を 作ったり改造したりは考えていないので、メモだけして終わる。
とりあえずここまでのもの
→
http://nmj.sumomo.ne.jp/arc/ext2ifs-0.3-wk001.tgzオリジナル バイナリとソースのミラー
→
http://nmj.sumomo.ne.jp/arc/ext2ifs-0.3.zip→
http://nmj.sumomo.ne.jp/arc/ext2ifs-0.3-src.zip追記:
LibSEH - a Windows SEH compatibility library というのを発見。なにか参考になるかも。
追記: filedisk を使ってみた。
インストールは、割と簡単だった。
1. filedisk.sys を C:\WINDOWS\system32\drivers にコピー
2. filedisk.exe を C:\WINDOWS\system32 にコピー
3. filedisk.reg を実行してレジストリを設定
4. リブート
あとは、example.txt を参考に mount すれば、ローカルディスクとして、マイコンピュータで見えるので、フォーマットすればよい。
filedisk /mount 0 d:\test1.img 100M m:
- デフォルトでは、4 つの仮想 DISKをサポートしていて、0
は 1つ目を指定
- 新規仮想 DISK を作るときは、サイズを指定(今回は 100M)
2 回目からは、100M をはずす。
- 最後に ドライブレターを指定
filedisk /umount m:
- DISK をはずすときは、/umount + ドライブレターを指定
※) format は、ドライブのプロパティで普通にできる。
※)上記は、MSYS コンソールではダメで、コマンドプロプトを使用する必要がある
※)システム起動とかで自動的にマウントする機能はない。使用時に、filedisk /mount ... を実行する必要がある。
ちなみに、crosscrypt を見てみたら、filedisk.sys , filedisk.exe , filedisk.reg が同じようにある。インストールの方法も同じ。filedisk.reg の内容も同じで、filedisk.sys / filedisk.exe を置き換えるようだ。コマンドも上位互換。
- 実用として使うなら、crosscrypt を使えばよさそう。
さて、ここからが本題。最初のステップとして自分でビルドした filedisk.sys を試してみたいのだが、どうすればよいのだろう?
少なくとも、filedisk.reg を編集して、Start のところを 3 にして、マニュアル スタートにしないとやばいのは分かる。
それはやるとして .. マニュアル スタートはいったいどうやってやるのだろう?
どうも
ServiWinを使えばよいらしい。
いよいよ ... 自分でビルドした filedisk.sys を実行する環境はできた。
だが、その前に 動くと期待できるものを試してみたい。
具体的には、MicroSoft の DDK から ntoskrnl.lib を取り出して、MinGW では、undefined になっていたシンボルを解決したバイナリを作りたい。
DDKの無料ダウンロードが開始されていた! の記事にある Windows Server 2003 SP1 DDK をダウンロードして、インストールして、lib/wxp/i386/ntoskrnl.lib を取り出して、-lntoskrnl の代わりに ファイル名を指定する。
これでできた filedisk.sys を WINDOWS/system32/drivers にコピーし、ServiWin でスタートすると ... 速攻青画面。
ちなみに、最初に作ったものも 青画面。
なにか足りないものがあるようだ。
ググっていくと、kqemu の Makefile が見つかった。動作しているものの Makefile だから信頼できるだろう。
これみると、コンパイルは普通で、リンクの仕方がこんな風になっている。
1) gcc -Wl,--base-file,base.tmp -Wl,--entry,_DriverEntry@8 \
-nostartfiles -nostdlib -o junk.tmp $(OBJECTS) \
-lntoskrnl -lhal
rm junk.tmp
2)dlltool --as=as --dllname $(TARGET) --base-file base.tmp \
--output-exp temp.exp
rm base.tmp
3)gcc -Wl,--subsystem,native -Wl,--image-base,0x10000 \
-Wl,--file-alignment,0x1000 \
-Wl,--section-alignment,0x1000 \
-Wl,--entry,_DriverEntry@8 -Wl,--stack,0x40000 \
-Wl,temp.exp \
-mdll -nostartfiles -nostdlib -o $(TARGET) \
$(OBJECTS) -lntoskrnl -lhal
rm temp.exp
2 つの 中間ファイルを作る全部で 3 ステップの手順。果たして必須なのだろうか? temp.exp がなんらかのチューニングのために必要だと想像。alignment も同じと考えると 足りないのは、
-Wl,--subsystem,native
-mdll
の 2つ。とりあえず -shared をはずして、これで試してみる。
ブルースクリーンは出なくなった! のだが、全然ダメ。ServiWin で開始すると、ServiWin が砂時計のままになる。
で、放置していた warning を見てみたら、外から呼び出される関数は全部 DDKAPI をつけなければならなかった。
あと、ヘッダーで _NTDDK_ が define されていることを期待しているところがあったので CFLAGS を修正。
で、これを 開始 しようとしたのだが、今度は 停止のまま状態が変わらなくなった。
進んでいる気がするが、まだまだみたい。なんとかしてデバックしていかないとこれ以上は進まない感じがする。
でググってたら、
Windows Device Driver Programming Part 1、
Part 2という解説ページを発見!
デバッグについても解説がある。ありがたや。
Windows Device Driver Programming Part 2にある。ex1.zip を試してみた。
- DebugView を立ち上げ、Capture → Capture Kernel をマークする。
- 付属の InstallDriver を立ち上げ kernel/ex1.sys をインストール → DebugView に以下が表示される。
00000007 129.96109009 DriverEntry Called
- user/ex1_user を実行 → DebugView に以下が表示される。
00000008 143.64530945 Example_Create Called
00000009 143.64535522 Example_IoControl Called
00000010 143.64537048 UserModeMessage = 'Hello from user mode!'
00000011 143.64537048 KernelModeMessage = 'Hello from kernel mode!'
00000012 143.64541626 Example_UnSupportedFunction Called
00000013 143.64541626 Example_Close Called
さて、どのように動くのか理解したところで、ビルドしてみる。
この修正で、コンパイルだけは Warning もなしにできるようになる。
つぎにリンク。
gcc -Wl,--subsystem,native -Wl,--image-base,0x10000 \
-Wl,--entry,_DriverEntry@8 \
-mdll -nostartfiles -nostdlib -o ex1.sys ex1.o \
-lntoskrnl
これで、Warning なしに ex1.sys ができてしまう。
さて、これを .. Install Driver でインストールしようとすると ..
00000000 0.00000000 SYSLDR: LdrRelocateImageWithBias() failed 0xc0000018
00000001 0.00000391 SYSLDR: OldBase : 00010000
00000002 0.00000670 SYSLDR: NewBase : A98D7000
00000003 0.00000922 SYSLDR: Diff : 0x0
00000004 0.00001201 SYSLDR: NextOffset : 00000000
00000005 0.00001425 SYSLDR: *NextOffset : 0x0
00000006 0.00001704 SYSLDR: SizeOfBlock : 0xa98d7000
なんていうメッセージが出て失敗する。
ちょっと、Linux の file で調べてみたら
ex1.sys.org: MS-DOS executable (EXE), OS/2 or MS Windows
ex1.sys: MS Windows PE 32-bit Intel 80386 native DLL not relocatable
ex1.o: 80386 COFF executable not stripped - version 30821
こんな違いが ...
リンクのオプションを
gcc -Wl,--subsystem,native -Wl,--image-base,0x10000 \
-Wl,--entry,_DriverEntry@8 \
-shared -nostartfiles -nostdlib -o ex1.sys ex1.o \
-lntoskrnl
と変更してみたところ ..
ex1.sys: MS Windows PE 32-bit Intel 80386 native DLL
となった。これを インストールしてみたら .. OK 。user/ex1_user でもメッセージが正しく出た!。
というわけで、filesys に戻る。
同じように、-mdll → -shared に変更したら、なんと動いた!
実は他にもいろいろ変更しているが、とりあえず動いた最初のもwのを
filedisk-wk002.zipとして置いておく。