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 <> 3 then (
26 eprintf "Error: missing argument.
27 Usage: %s hivefile endpages
28 " Sys.executable_name;
32 let filename = Sys.argv.(1)
33 let new_end_pages = int_of_string Sys.argv.(2)
36 let bits = bitstring_of_file filename
38 (* Split into header + data at the 4KB boundary. *)
39 let header, data = takebits (4096 * 8) bits, dropbits (4096 * 8) bits
41 (* Truncate the file data. *)
42 let data = takebits (new_end_pages * 8) data
44 (* Read the header fields. *)
45 let seq, last_modified, major, minor, unknown1, unknown2,
46 root_key, end_pages, unknown3, fname =
48 | { "regf" : 4*8 : string;
49 seq1 : 4*8 : littleendian;
50 seq2 : 4*8 : littleendian;
51 last_modified : 64 : bitstring;
52 major : 4*8 : littleendian;
53 minor : 4*8 : littleendian;
54 unknown1 : 4*8 : littleendian;
55 unknown2 : 4*8 : littleendian;
56 root_key : 4*8 : littleendian;
57 end_pages : 4*8 : littleendian;
58 unknown3 : 4*8 : littleendian;
59 fname : 64*8 : string;
60 unknownguid1 : 16*8 : bitstring;
61 unknownguid2 : 16*8 : bitstring;
62 unknown4 : 4*8 : littleendian;
63 unknownguid3 : 16*8 : bitstring;
64 unknown5 : 4*8 : string;
65 unknown6 : 340*8 : bitstring;
67 : littleendian, save_offset_to (crc_offset),
68 check (assert (crc_offset = 0x1fc * 8); true);
69 unknown7 : (0x1000-0x200)*8 : bitstring } ->
70 seq1, last_modified, major, minor, unknown1, unknown2,
71 root_key, end_pages, unknown3, fname
74 (* Create a new header, with endpages updated. *)
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 Int32.of_int new_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