X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;ds=sidebyside;f=hivex%2Ftools%2Fvisualizer.ml;h=5b7ac79d2287a1ea872c5a93c256fb1156d2264c;hb=4615036b31c37b78187e3368da4c673817542d9b;hp=bc447b7a79ec724b2e1b963220c2d7989ffbbffe;hpb=1390ec8cc052fa8af58ddb40825f4fadc9879c0d;p=hivex.git diff --git a/hivex/tools/visualizer.ml b/hivex/tools/visualizer.ml index bc447b7..5b7ac79 100644 --- a/hivex/tools/visualizer.ml +++ b/hivex/tools/visualizer.ml @@ -408,19 +408,27 @@ let bitmatch nk_fields = classname : 4*8 : littleendian, bind (get_offset classname); (* sentinelchicken.com says this is a single 32 bit field * containing maximum number of bytes in a subkey name, however - * that does not seem to be correct. We think it is two 16 bit + * that does not seem to be correct. We think it is several * fields, the first being the maximum number of bytes in the * UTF16-LE encoded version of the subkey names, (since subkey * names are usually ASCII, that would be max length of names * 2). * This is a historical maximum, so it can be greater than the * current maximum name field. * - * The second field is often non-zero, but the purpose is unknown. - * In the hives we examined it had values 0, 1, 0x20, 0x21, 0xa0, - * 0xa1, 0xe1, suggesting some sort of flags. + * The remaining fields are often non-zero, but the purpose is + * unknown. + * + * In the hives we examined the other fields had values as + * follows: + * userflags: 0, 2, 0xa, 0xe + * virtcontrolflags: 0, 1 + * debug: always 0 *) max_subkey_name_len : 2*8 : littleendian; - unknown2 : 2*8 : littleendian; + unknown2_userflags : 4; + unknown2_virtcontrolflags : 4; + unknown2_debug : 8; + (* sentinelchicken.com says: maximum subkey CLASSNAME length, * however that does not seem to be correct. In hives I looked * at, it has value 0, 0xc, 0x10, 0x18, 0x1a, 0x28. @@ -453,7 +461,7 @@ let fprintf_nk chan nk = bitmatch bits with | { :nk_fields } -> fprintf chan - "NK %s %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s %s %08lx %s %d %ld %s %08lx %d %s %s %s %d %04x %08lx %d %d %08lx %d %d %s\n" + "NK %s %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s %s %08lx %s %d %ld %s %08lx %d %s %s %s %d %x %x %x %08lx %d %d %08lx %d %d %s\n" (print_offset nk) (if unknownflag8000 then "8" else ".") (if unknownflag4000 then "4" else ".") @@ -476,26 +484,27 @@ let fprintf_nk chan nk = (print_offset subkeys) subkeys_vol nr_values (print_offset vallist) (print_offset sk) (print_offset classname) - max_subkey_name_len unknown2 unknown3 - max_vk_name_len max_vk_data_len unknown6 + max_subkey_name_len + unknown2_userflags unknown2_virtcontrolflags unknown2_debug + unknown3 max_vk_name_len max_vk_data_len unknown6 name_len classname_len name type data_t = Inline of bitstring | Offset of int let bitmatch vk_fields = { "vk" : 2*8 : string; name_len : 2*8 : littleendian; - (* No one documents the important fact that data_len can have the - * top bit set (randomly or is it meaningful?). The length can - * also be 0 (or 0x80000000) if the data type is NONE. + (* Top bit set means that the data is stored inline. In that case + * the data length must be <= 4. The length can also be 0 (or + * 0x80000000) if the data type is NONE. *) data_len : 4*8 : littleendian, bind ( - let data_len = Int32.logand data_len 0x7fff_ffff_l in - Int32.to_int data_len + let is_inline = Int32.logand data_len 0x8000_0000_l = 0x8000_0000_l in + let data_len = Int32.to_int (Int32.logand data_len 0x7fff_ffff_l) in + if is_inline then assert (data_len <= 4) else assert (data_len > 4); + is_inline, data_len ); - (* Inline data if len <= 4, offset otherwise. - * - * The data itself depends on the type field. + (* The data itself depends on the type field. * * For REG_SZ type, the data always seems to be NUL-terminated, which * means because these strings are often UTF-16LE, that the string will @@ -506,7 +515,8 @@ let bitmatch vk_fields = *) data : 4*8 : bitstring, bind ( - if data_len <= 4 then + let is_inline, data_len = data_len in + if is_inline then Inline (takebits (data_len*8) data) else ( let offset = @@ -537,9 +547,10 @@ let fprintf_vk chan vk = | Offset offset -> let (_, _, bits) = lookup "fprintf_vk (data)" offset in bits in - fprintf chan "VK %s %s %d %s%s %s %08x %s %08x %08x\n" + let is_inline, data_len = data_len in + fprintf chan "VK %s %s %s %d %s%s %s %08x %s %08x %08x\n" (print_offset vk) - name data_len + name (if is_inline then "inline" else "-") data_len (match data with | Inline _ -> "" | Offset offset -> "["^print_offset offset^"]") @@ -601,8 +612,15 @@ let rec visit_nk ?(nk_is_root = false) nk = eprintf "NK %s unknownflag0400 is set\n" (print_offset nk); if unknown1 <> 0_l then eprintf "NK %s unknown1 <> 0 (%08lx)\n" (print_offset nk) unknown1; - if unknown2 <> 0 then - eprintf "NK %s unknown2 <> 0 (%04x)\n" (print_offset nk) unknown2; + if unknown2_userflags <> 0 then + eprintf "NK %s unknown2_userflags <> 0 (%x)\n" + (print_offset nk) unknown2_userflags; + if unknown2_virtcontrolflags <> 0 then + eprintf "NK %s unknown2_virtcontrolflags <> 0 (%x)\n" + (print_offset nk) unknown2_virtcontrolflags; + if unknown2_debug <> 0 then + eprintf "NK %s unknown2_debug <> 0 (%x)\n" + (print_offset nk) unknown2_debug; if unknown3 <> 0_l then eprintf "NK %s unknown3 <> 0 (%08lx)\n" (print_offset nk) unknown3; if unknown6 <> 0_l then @@ -691,6 +709,8 @@ and visit_vk vk = | { :vk_fields } -> fprintf_vk stdout vk; + let is_inline, data_len = data_len in + if unknown1 <> 0 then eprintf "VK %s unknown1 flags set (%02x)\n" (print_offset vk) unknown1;