1 (* Windows Registry reverse-engineering tool.
2 * Copyright (C) 2010 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 if Array.length Sys.argv <> 2 then (
26 eprintf "Error: missing argument.
28 " Sys.executable_name;
32 let filename = Sys.argv.(1)
35 let bits = bitstring_of_file filename
37 (* Split into header + data at the 4KB boundary. *)
38 let header, data = takebits (4096 * 8) bits, dropbits (4096 * 8) bits
40 (* Read the header fields. *)
41 let seq, last_modified, major, minor, unknown1, unknown2,
42 root_key, end_pages, unknown3, fname =
44 | { "regf" : 4*8 : string;
45 seq1 : 4*8 : littleendian;
46 seq2 : 4*8 : littleendian;
47 last_modified : 64 : bitstring;
48 major : 4*8 : littleendian;
49 minor : 4*8 : littleendian;
50 unknown1 : 4*8 : littleendian;
51 unknown2 : 4*8 : littleendian;
52 root_key : 4*8 : littleendian;
53 end_pages : 4*8 : littleendian;
54 unknown3 : 4*8 : littleendian;
55 fname : 64*8 : string;
56 unknownguid1 : 16*8 : bitstring;
57 unknownguid2 : 16*8 : bitstring;
58 unknown4 : 4*8 : littleendian;
59 unknownguid3 : 16*8 : bitstring;
60 unknown5 : 4*8 : string;
61 unknown6 : 340*8 : bitstring;
63 : littleendian, save_offset_to (crc_offset),
64 check (assert (crc_offset = 0x1fc * 8); true);
65 unknown7 : (0x1000-0x200)*8 : bitstring } ->
66 seq1, last_modified, major, minor, unknown1, unknown2,
67 root_key, end_pages, unknown3, fname
70 (* Create a new header, but with unknown fields cleared. Do it in
71 * two parts, first creating everything up to the checksum, then
72 * calculating the checksum and appending checksum and the final
76 let zeroguid = zeroes_bitstring (16*8) in
79 "regf" : 4*8 : string;
80 seq : 4*8 : littleendian;
81 seq : 4*8 : littleendian;
82 last_modified : 64 : bitstring;
83 major : 4*8 : littleendian;
84 minor : 4*8 : littleendian;
85 unknown1 : 4*8 : littleendian;
86 unknown2 : 4*8 : littleendian;
87 root_key : 4*8 : littleendian;
88 end_pages : 4*8 : littleendian;
89 unknown3 : 4*8 : littleendian;
90 fname : 64*8 : string;
91 zeroguid : 16*8 : bitstring;
92 zeroguid : 16*8 : bitstring;
93 0_l : 4*8 : littleendian;
94 zeroguid : 16*8 : bitstring;
95 0_l : 4*8 : littleendian;
96 zeroes_bitstring (340*8) : 340*8 : bitstring
98 assert (bitstring_length before_csum = 0x1fc * 8);
99 let csum = bitstring_fold_left_int32_le Int32.logxor 0_l before_csum in
102 csum : 4*8 : littleendian;
103 zeroes_bitstring ((0x1000-0x200)*8) : (0x1000-0x200)*8 : bitstring
105 let new_header = concat [before_csum; csum_and_after] in
106 assert (bitstring_length header = bitstring_length new_header);
111 let file = concat [header; data] in
112 bitstring_to_file file filename