Wednesday, April 24, 2013

Cyber Defense Exercise 2013: Extracting cached passphrases in Truecrypt

This was an incredibly difficult challenge. We unfortunately did not solve it before CDX ended, however, I'm grateful to Carnegie Mellon University (CMU) for keeping the forensic examination environment open even after ENDEX. Note though: any code examples are from my local Truecrypt experiment, not CMU's challenge due to the difficult nature of copy paste between USAFAnyet and CMU CERT.

During the exercise, we tried using volshell from Volatility, a python script, and strings.

Looking at processes active is pretty standard for a memory dump so we did that:
root# vol.py -f memdump.dd --profile=WinXPSP3x86 volshell
Volatile Systems Volatility Framework 2.2
Current context: process System, pid=4, ppid=0 DTB=0x6bc0000
Welcome to volshell! Current memory image is:
memdump.dd
To get help, type 'hh()'
>>> ps()
Name            PID     PPID   Offset
[...]
TrueCrypt.exe   1544    1752   0x86687da0
[...]
>>>
The TrueCrypt.exe process seemed promising, so we scoured the strings of the process dump. Little did we know that this was pointless, because the only stuff in the TrueCrypt userland process is GUI stuff.

We started reading Ram is Key at this point.

The most helpful piece of knowledge to have whilst diving into RAM is Key is to realize the difference between a key and a passphrase. A key is the cryptographic sequence that AES uses to encrypt and decrypt data. The average user has no idea about the key. The passphrase is the user supplied cryptographic material. Hopefully the user knows about the passphrase.

This picture shows the keys used by TrueCrypt, which obviously are machine generated:

RAM is Key talked a lot about drivers and kernel space. MSDN was an extremely useful reference. These in particular: DEVICE_OBJECT, DRIVER_OBJECT, Device Extensions.

Thus, doing some driver-oriented volatility plugins seemed great:
root# vol.py -f memdump.dd --profile=WinXPSP3x86 devicetree
[...]
DRV 0x01e4d030 \Driver\truecrypt
---| DEV 0x81fc0200 TrueCryptVolumeE FILE_DEVICE_DISK
---| DEV 0x81cf75d0 TrueCrypt FILE_DEVICE_UNKNOWN
[...]
root#
A deep understanding of what devicetree does is very helpful.

Device Extensions turned out to be a rabbit trail when pursuing passphrases, but they seem to be useful for extracting keys, though one would need to look at the Truecrypt driver source code to make any sense of Truecrypt's particular Device Extension structure. Without doing any further research, here's what I found in the device extension which I guess was mildly useful:
>>> dt("_DEVICE_OBJECT", 0x81fc0200)
[_DEVICE_OBJECT _DEVICE_OBJECT] @ 0x81FC0200
0x0   : Type                           3
0x2   : Size                           1416
0x4   : ReferenceCount                 3
0x8   : DriverObject                   2179256368
0xc   : NextDevice                     2177856976
0x10  : AttachedDevice                 0
0x14  : CurrentIrp                     0
0x18  : Timer                          0
0x1c  : Flags                          80
0x20  : Characteristics                256
0x24  : Vpb                            2183885000
0x28  : DeviceExtension                2180776632
0x2c  : DeviceType                     7
0x30  : StackSize                      7
0x34  : Queue                          2180776500
0x5c  : AlignmentRequirement           0
0x60  : DeviceQueue                    2180776544
0x74  : Dpc                            2180776564
0x94  : ActiveThreadCount              0
0x98  : SecurityDescriptor             3778765672
0x9c  : DeviceLock                     2180776604
0xac  : SectorSize                     512
0xae  : Spare1                         0
0xb0  : DeviceObjectExtension          2180777864
0xb4  : Reserved                       0
"Type" being 3 is important because that means we were right about overlaying the _DEVICE_OBJECT over the chosen address.
>>> db(2180776632, 800)
0x81fc02b8  00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00   ................
0x81fc02c8  01 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00   ................
0x81fc02d8  38 6a 1c 82 01 00 04 00 00 00 00 00 e4 02 fc 81   8j..............
0x81fc02e8  e4 02 fc 81 00 00 00 00 f0 02 fc 81 f0 02 fc 81   ................
0x81fc02f8  05 00 05 00 00 00 00 00 a8 6a 1c 82 a8 6a 1c 82   .........j...j..
0x81fc0308  ff ff ff 7f 0c 01 00 80 a8 21 18 82 20 30 e4 81   .........!...0..
0x81fc0318  00 d0 cd 81 00 00 00 00 00 00 40 06 00 00 00 00   ..........@.....
0x81fc0328  00 00 3c 06 00 00 00 00 00 1e 03 00 00 00 00 00   ..<.............
0x81fc0338  01 00 00 00 01 00 00 00 00 02 00 00 00 00 00 00   ................
0x81fc0348  00 02 00 00 00 00 04 00 00 00 00 00 54 03 fc 81   ............T...
0x81fc0358  54 03 fc 81 00 00 00 00 00 02 fc 81 02 00 08 00   T...............
0x81fc0368  01 00 00 00 6c 03 fc 81 6c 03 fc 81 50 37 17 82   ....l...l...P7..
0x81fc0378  50 37 17 82 00 00 00 00 00 01 00 00 c8 11 35 82   P7............5.
0x81fc0388  00 d0 cd 81 0c 01 00 80 00 00 3c 06 00 00 00 00   ..........<.....
0x81fc0398  4c 07 fc 81 00 00 00 00 00 00 00 00 00 00 00 00   L...............
0x81fc03a8  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x81fc03b8  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x81fc03c8  00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00   ................
0x81fc03d8  01 00 04 00 00 00 00 00 e0 03 fc 81 e0 03 fc 81   ................
0x81fc03e8  f8 fb e9 81 ec 03 fc 81 ec 03 fc 81 00 00 00 00   ................
0x81fc03f8  01 00 04 00 00 00 00 00 68 fc e9 81 68 fc e9 81   ........h...h...
0x81fc0408  70 38 11 82 0c 04 fc 81 0c 04 fc 81 00 00 00 00   p8..............
0x81fc0418  01 00 04 00 00 00 00 00 e0 38 11 82 e0 38 11 82   .........8...8..
0x81fc0428  40 37 17 82 2c 04 fc 81 2c 04 fc 81 00 00 00 00   @7..,...,.......
0x81fc0438  01 00 04 00 00 00 00 00 b0 37 17 82 b0 37 17 82   .........7...7..
0x81fc0448  00 d0 c9 81 00 d0 c5 81 01 00 04 00 01 00 00 00   ................
0x81fc0458  58 04 fc 81 58 04 fc 81 01 00 04 00 01 00 00 00   X...X...........
0x81fc0468  68 04 fc 81 68 04 fc 81 01 00 00 00 00 00 00 00   h...h...........
0x81fc0478  00 c4 0e 00 00 00 00 00 00 02 00 00 00 00 00 00   ................
0x81fc0488  00 c6 0e 00 00 00 00 00 00 02 00 00 00 d0 c1 81   ................
0x81fc0498  00 00 40 06 00 00 00 00 00 00 00 00 01 00 04 00   ..@.............
0x81fc04a8  00 00 00 00 ac 04 fc 81 ac 04 fc 81 00 00 00 00   ................
0x81fc04b8  01 00 04 00 01 00 00 00 c0 04 fc 81 c0 04 fc 81   ................
0x81fc04c8  00 56 06 00 00 00 00 00 00 00 00 00 00 00 00 00   .V..............
0x81fc04d8  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x81fc04e8  00 00 00 00 01 00 04 00 00 00 00 00 f4 04 fc 81   ................
0x81fc04f8  f4 04 fc 81 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x81fc0508  00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00   ................
0x81fc0518  5c 00 3f 00 3f 00 5c 00 43 00 3a 00 5c 00 44 00   \.?.?.\.C.:.\.D.
0x81fc0528  6f 00 63 00 75 00 6d 00 65 00 6e 00 74 00 73 00   o.c.u.m.e.n.t.s.
0x81fc0538  20 00 61 00 6e 00 64 00 20 00 53 00 65 00 74 00   ..a.n.d...S.e.t.
0x81fc0548  74 00 69 00 6e 00 67 00 73 00 5c 00 6c 00 75 00   t.i.n.g.s.\.u.s.
0x81fc0558  6b 00 65 00 5c 00 44 00 65 00 73 00 6b 00 74 00   e.r.\.D.e.s.k.t.
0x81fc0568  6f 00 70 00 5c 00 74 00 63 00 63 00 6f 00 6e 00   o.p.\.t.c.c.o.n.
0x81fc0578  74 00 61 00 69 00 6e 00 65 00 72 00 00 00 00 00   t.a.i.n.e.r.....
0x81fc0588  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x81fc0598  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x81fc05a8  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x81fc05b8  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x81fc05c8  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
So, the TrueCrypt (TC) volume open in this memory dump is "C:\Documents and Settings\user\Desktop\tccontainer". If the name of the TC volume wasn't so generic, it may be useful to spin off an indexing of the strings in the memory image, and then a grep. The "strings" module of volatility would have to be used in order to map the file offset to an actual memory offset.

At this point, I determined, mostly from reading RAM is Key, that the best way to find the passphrase would be to dump the executable space of the truecrypt driver, and search it with the format [1 byte size][3 null bytes][passphrase][1 null byte], however, after dumping the driver, I found the passphrase. The easiest way to find where the truecrypt driver lives is to use "driverscan" volatility module. We'll do it the more interesting way, however. Same device object as before:
>>> dt("_DEVICE_OBJECT", 0x81fc0200)
[_DEVICE_OBJECT _DEVICE_OBJECT] @ 0x81FC0200
0x0   : Type                           3
0x2   : Size                           1416
0x4   : ReferenceCount                 3
0x8   : DriverObject                   2179256368
0xc   : NextDevice                     2177856976
0x10  : AttachedDevice                 0
0x14  : CurrentIrp                     0
0x18  : Timer                          0
0x1c  : Flags                          80
0x20  : Characteristics                256
0x24  : Vpb                            2183885000
0x28  : DeviceExtension                2180776632
0x2c  : DeviceType                     7
0x30  : StackSize                      7
0x34  : Queue                          2180776500
0x5c  : AlignmentRequirement           0
0x60  : DeviceQueue                    2180776544
0x74  : Dpc                            2180776564
0x94  : ActiveThreadCount              0
0x98  : SecurityDescriptor             3778765672
0x9c  : DeviceLock                     2180776604
0xac  : SectorSize                     512
0xae  : Spare1                         0
0xb0  : DeviceObjectExtension          2180777864
0xb4  : Reserved                       0
>>> dt("_DRIVER_OBJECT", 2179256368)
[_DRIVER_OBJECT _DRIVER_OBJECT] @ 0x81E4D030
0x0   : Type                           4
0x2   : Size                           168
0x4   : DeviceObject                   2180776448
0x8   : Flags                          18
0xc   : DriverStart                    2986721280
0x10  : DriverSize                     224128
0x14  : DriverSection                  2182800832
0x18  : DriverExtension                2179256536
0x1c  : DriverName                     \Driver\truecrypt
0x24  : HardwareDatabase               2154363536
0x28  : FastIoDispatch                 0
0x2c  : DriverInit                     2986935637
0x30  : DriverStartIo                  0
0x34  : DriverUnload                   2986747628
0x38  : MajorFunction                  -
>>> db(2986721280, 224128)
Memory unreadable at b205c000
Now, that doesn't really mean that memory is unreadable at b205c000h, just that 224128 bytes after b205c000h is not readable. I do not know why this is true, but I just adjusted the bounds down until it worked:
>>> db(0xb205c000, 0x35000)
[...]
[watch pretty ascii flow by]
[...]
0xb2090e10  6c 45 71 75 61 6c 53 69 64 00 d9 04 53 65 51 75   lEqualSid...SeQu
0xb2090e20  65 72 79 49 6e 66 6f 72 6d 61 74 69 6f 6e 54 6f   eryInformationTo
0xb2090e30  6b 65 6e 00 e5 04 53 65 54 6f 6b 65 6e 49 73 41   ken...SeTokenIsA
0xb2090e40  64 6d 69 6e 00 00 c4 04 53 65 43 61 70 74 75 72   dmin....SeCaptur
0xb2090e50  65 53 75 62 6a 65 63 74 43 6f 6e 74 65 78 74 00   eSubjectContext.
0xb2090e60  1d 02 4b 65 49 6e 69 74 69 61 6c 69 7a 65 53 65   ..KeInitializeSe
0xb2090e70  6d 61 70 68 6f 72 65 00 30 02 4b 65 51 75 65 72   maphore.0.KeQuer
0xb2090e80  79 49 6e 74 65 72 72 75 70 74 54 69 6d 65 00 00   yInterruptTime..
0xb2090e90  c7 04 53 65 43 72 65 61 74 65 43 6c 69 65 6e 74   ..SeCreateClient
0xb2090ea0  53 65 63 75 72 69 74 79 00 00 c5 03 52 74 6c 43   Security....RtlC
0xb2090eb0  6f 70 79 53 69 64 00 00 4c 04 52 74 6c 4c 65 6e   opySid..L.RtlLen
0xb2090ec0  67 74 68 53 69 64 00 00 59 01 49 6f 45 6e 75 6d   gthSid..Y.IoEnum
0xb2090ed0  65 72 61 74 65 44 65 76 69 63 65 4f 62 6a 65 63   erateDeviceObjec
0xb2090ee0  74 4c 69 73 74 00 75 03 50 73 47 65 74 56 65 72   tList.u.PsGetVer
0xb2090ef0  73 69 6f 6e 00 00 60 05 5a 77 53 65 74 49 6e 66   sion..`.ZwSetInf
0xb2090f00  6f 72 6d 61 74 69 6f 6e 46 69 6c 65 00 00 45 05   ormationFile..E.
0xb2090f10  5a 77 51 75 65 72 79 49 6e 66 6f 72 6d 61 74 69   ZwQueryInformati
0xb2090f20  6f 6e 46 69 6c 65 00 00 c9 05 77 63 73 6e 63 70   onFile....wcsncp
0xb2090f30  79 00 cc 05 77 63 73 73 74 72 00 00 8c 05 5f 73   y...wcsstr...._s
0xb2090f40  6e 77 70 72 69 6e 74 66 00 00 5c 01 49 6f 46 69   nwprintf..\.IoFi
0xb2090f50  6c 65 4f 62 6a 65 63 74 54 79 70 65 00 00 66 02   leObjectType..f.
0xb2090f60  4b 65 54 69 63 6b 43 6f 75 6e 74 00 6e 74 6f 73   KeTickCount.ntos
0xb2090f70  6b 72 6e 6c 2e 65 78 65 00 00 4d 00 4b 66 4c 6f   krnl.exe..M.KfLo
0xb2090f80  77 65 72 49 72 71 6c 00 44 00 4b 65 52 61 69 73   werIrql.D.KeRais
0xb2090f90  65 49 72 71 6c 54 6f 44 70 63 4c 65 76 65 6c 00   eIrqlToDpcLevel.
0xb2090fa0  4f 00 4b 66 52 65 6c 65 61 73 65 53 70 69 6e 4c   O.KfReleaseSpinL
0xb2090fb0  6f 63 6b 00 4c 00 4b 66 41 63 71 75 69 72 65 53   ock.L.KfAcquireS
0xb2090fc0  70 69 6e 4c 6f 63 6b 00 40 00 4b 65 47 65 74 43   pinLock.@.KeGetC
0xb2090fd0  75 72 72 65 6e 74 49 72 71 6c 00 00 48 41 4c 2e   urrentIrql..HAL.
0xb2090fe0  64 6c 6c 00 4d 02 4b 65 52 65 73 74 6f 72 65 46   dll.M.KeRestoreF
0xb2090ff0  6c 6f 61 74 69 6e 67 50 6f 69 6e 74 53 74 61 74   loatingPointStat
>>>
This looks like the import address table (IAT), though definitely not all of it; the last entry on-screen seems to be cut off. Be exploratory, and scroll up past the beginning of the IAT. And then a little farther:
0xb208ffd0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb208ffe0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb208fff0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090000  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090020  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090030  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090040  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090050  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090060  17 00 00 00 74 72 75 65 63 72 79 70 74 70 61 73   ....truecryptpas
0xb2090070  73 77 6f 72 64 73 65 63 75 72 65 00 00 00 00 00   swordsecure.....
0xb2090080  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090090  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb20900a0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb20900b0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb20900c0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb20900d0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb20900e0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb20900f0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090100  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090110  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090120  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090130  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090140  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090150  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090160  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090170  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090180  00 00 00 00 46 ea 30 4f 00 00 00 00 f8 41 03 00   ....F.0O.....A..
0xb2090190  01 00 00 00 08 00 00 00 08 00 00 00 a8 41 03 00   .............A..
0xb20901a0  c8 41 03 00 e8 41 03 00 e0 0c 01 00 e0 00 01 00   .A...A..........
0xb20901b0  2d 60 01 00 e9 60 01 00 10 60 01 00 59 65 01 00   -`...`...`..Ye..
0xb20901c0  15 66 01 00 1b 60 01 00 06 42 03 00 16 42 03 00   .f...`...B...B..
0xb20901d0  26 42 03 00 3c 42 03 00 5c 42 03 00 75 42 03 00   &B...B...B..uB..
0xb20901e0  8b 42 03 00 ab 42 03 00 00 00 01 00 02 00 03 00   .B...B..........
0xb20901f0  04 00 05 00 06 00 07 00 74 72 75 65 63 72 79 70   ........truecryp
0xb2090200  74 2e 73 79 73 00 5f 61 65 73 5f 64 65 63 72 79   t.sys._aes_decry
0xb2090210  70 74 40 31 32 00 5f 61 65 73 5f 65 6e 63 72 79   pt@12._aes_encry
0xb2090220  70 74 40 31 32 00 5f 61 65 73 5f 68 77 5f 63 70   pt@12._aes_hw_cp
0xb2090230  75 5f 64 65 63 72 79 70 74 40 38 00 5f 61 65 73   u_decrypt@8._aes
0xb2090240  5f 68 77 5f 63 70 75 5f 64 65 63 72 79 70 74 5f   _hw_cpu_decrypt_
0xb2090250  33 32 5f 62 6c 6f 63 6b 73 40 38 00 5f 61 65 73   32_blocks@8._aes
0xb2090260  5f 68 77 5f 63 70 75 5f 65 6e 61 62 6c 65 5f 73   _hw_cpu_enable_s
0xb2090270  73 65 40 30 00 5f 61 65 73 5f 68 77 5f 63 70 75   se@0._aes_hw_cpu
0xb2090280  5f 65 6e 63 72 79 70 74 40 38 00 5f 61 65 73 5f   _encrypt@8._aes_
0xb2090290  68 77 5f 63 70 75 5f 65 6e 63 72 79 70 74 5f 33   hw_cpu_encrypt_3
0xb20902a0  32 5f 62 6c 6f 63 6b 73 40 38 00 5f 69 73 5f 61   2_blocks@8._is_a
0xb20902b0  65 73 5f 68 77 5f 63 70 75 5f 73 75 70 70 6f 72   es_hw_cpu_suppor
0xb20902c0  74 65 64 40 30 00 00 00 00 00 00 00 00 00 00 00   ted@0...........
0xb20902d0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb20902e0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb20902f0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0xb2090300  00 00 00 00 00 00 8b ff 55 8b ec 81 ec 98 00 00   ........U.......
0xb2090310  00 a1 80 8c 08 b2 33 c5 89 45 fc 56 57 8b 7d 08   ......3..E.VW.}.
0xb2090320  33 c0 0f b7 88 8a 05 09 b2 66 89 4c 05 bc 40 40   3........f.L..@@
0xb2090330  66 85 c9 75 ed 33 c0 0f b7 88 66 05 09 b2 66 89   f..u.3....f...f.
0xb2090340  8c 05 7c ff ff ff 40 40 66 85 c9 75 ea 8b 35 44   ..|...@@f..u..5D
0xb2090350  a9 07 b2 8d 85 7c ff ff ff 50 8d 85 70 ff ff ff   .....|...P..p...
0xb2090360  50 ff d6 8d 45 bc 50 8d 85 68 ff ff ff 50 ff d6   P...E.P..h...P..
0xb2090370  8d 85 78 ff ff ff 50 6a 00 68 00 01 00 00 6a 22   ..x...Pj.h....j"
0xb2090380  8d 85 70 ff ff ff 50 6a 04 57 ff 15 a8 a8 07 b2   ..p...Pj.W......
0xb2090390  85 c0 7c 6b 8b 85 78 ff ff ff 83 48 1c 10 8b 8d   ..|k..x....H....
0xb20903a0  78 ff ff ff 33 c0 40 89 41 5c 8b 8d 78 ff ff ff   x...3.@.A\..x...
0xb20903b0  8b 49 28 6a 00 68 70 b2 08 b2 89 01 ff 15 fc a9   .I(j.hp.........
Now, if the passphrase had not been chilling in plain sight, you'd have to dump the driver to a file, and comb it over with a python script kind of like:
import struct,string

def isasciistr(s):
    return all(c in string.printable for c in s)

def findPassphrases(memdump):
    img = open(memdump, 'rb', buffering=10240)

    while True:
        region = img.read(10240)
        if len(region) == 0:
            break
        startoffset = 0
        while startoffset < len(region):
            offset = region.find('\x00\x00\x00', startoffset)
            if offset > -1:
                startoffset = offset+3
                lengthField = region[offset-1]
                #we found a set of three null bytes
                length = struct.unpack('<B', region[offset-1])[0]
                if length > 0:
                    passphrase = region[offset+3:offset+3+length]
                    lengthReal = len(passphrase)
                    #make sure we aren't hurtling off the region boundary
                    if offset+3+length+1 < 10240:
                        #make sure byte right after string is a null byte (sure, more should be null, but whatever)
                        if ord(region[offset+3+length+1]) != 0:
                            break
                    #make sure that the string is as long as the field said it would be
                    if isasciistr(passphrase) and ord(lengthField) == lengthReal:
                        #print the possibility
                        print "POSITIVE: "+passphrase + " EXPECT("+hex(ord(lengthField))+")"+" GOT("+hex(lengthReal)+")"
            else:
                break

findPassphrases()
Kudos to pants for the vast majority of the above script.

- syreal