Add hivex_set_value API call, and ocaml and perl bindings, and tests.
[hivex.git] / lib / tools / clearheaderfields.ml
1 (* Windows Registry reverse-engineering tool.
2  * Copyright (C) 2010 Red Hat Inc.
3  *
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.
8  *
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.
13  *
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.
17  *)
18
19 open Bitstring
20 open ExtString
21 open Printf
22 open Visualizer_utils
23
24 let () =
25   if Array.length Sys.argv <> 2 then (
26     eprintf "Error: missing argument.
27 Usage: %s hivefile
28 " Sys.executable_name;
29     exit 1
30   )
31
32 let filename = Sys.argv.(1)
33
34 (* Load the file. *)
35 let bits = bitstring_of_file filename
36
37 (* Split into header + data at the 4KB boundary. *)
38 let header, data = takebits (4096 * 8) bits, dropbits (4096 * 8) bits
39
40 (* Read the header fields. *)
41 let seq, last_modified, major, minor, unknown1, unknown2,
42   root_key, end_pages,  unknown3, fname =
43   bitmatch header with
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;
62       csum : 4*8
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
68   | {_} -> assert false
69
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
73  * field.
74  *)
75 let header =
76   let zeroguid = zeroes_bitstring (16*8) in
77   let before_csum =
78     BITSTRING {
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
97     } in
98   assert (bitstring_length before_csum = 0x1fc * 8);
99   let csum = bitstring_fold_left_int32_le Int32.logxor 0_l before_csum in
100   let csum_and_after =
101     BITSTRING {
102       csum : 4*8 : littleendian;
103       zeroes_bitstring ((0x1000-0x200)*8) : (0x1000-0x200)*8 : bitstring
104     } in
105   let new_header = concat [before_csum; csum_and_after] in
106   assert (bitstring_length header = bitstring_length new_header);
107   new_header
108
109 (* Write it. *)
110 let () =
111   let file = concat [header; data] in
112   bitstring_to_file file filename