1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
(* Windows Registry reverse-engineering tool.
* Copyright (C) 2010 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
open Bitstring
open ExtString
open Printf
open Visualizer_utils
let () =
if Array.length Sys.argv <> 3 then (
eprintf "Error: missing argument.
Usage: %s hivefile endpages
" Sys.executable_name;
exit 1
)
let filename = Sys.argv.(1)
let new_end_pages = int_of_string Sys.argv.(2)
(* Load the file. *)
let bits = bitstring_of_file filename
(* Split into header + data at the 4KB boundary. *)
let header, data = takebits (4096 * 8) bits, dropbits (4096 * 8) bits
(* Truncate the file data. *)
let data = takebits (new_end_pages * 8) data
(* Read the header fields. *)
let seq, last_modified, major, minor, unknown1, unknown2,
root_key, end_pages, unknown3, fname =
bitmatch header with
| { "regf" : 4*8 : string;
seq1 : 4*8 : littleendian;
seq2 : 4*8 : littleendian;
last_modified : 64 : bitstring;
major : 4*8 : littleendian;
minor : 4*8 : littleendian;
unknown1 : 4*8 : littleendian;
unknown2 : 4*8 : littleendian;
root_key : 4*8 : littleendian;
end_pages : 4*8 : littleendian;
unknown3 : 4*8 : littleendian;
fname : 64*8 : string;
unknownguid1 : 16*8 : bitstring;
unknownguid2 : 16*8 : bitstring;
unknown4 : 4*8 : littleendian;
unknownguid3 : 16*8 : bitstring;
unknown5 : 4*8 : string;
unknown6 : 340*8 : bitstring;
csum : 4*8
: littleendian, save_offset_to (crc_offset),
check (assert (crc_offset = 0x1fc * 8); true);
unknown7 : (0x1000-0x200)*8 : bitstring } ->
seq1, last_modified, major, minor, unknown1, unknown2,
root_key, end_pages, unknown3, fname
| {_} -> assert false
(* Create a new header, with endpages updated. *)
let header =
let zeroguid = zeroes_bitstring (16*8) in
let before_csum =
BITSTRING {
"regf" : 4*8 : string;
seq : 4*8 : littleendian;
seq : 4*8 : littleendian;
last_modified : 64 : bitstring;
major : 4*8 : littleendian;
minor : 4*8 : littleendian;
unknown1 : 4*8 : littleendian;
unknown2 : 4*8 : littleendian;
root_key : 4*8 : littleendian;
Int32.of_int new_end_pages : 4*8 : littleendian;
unknown3 : 4*8 : littleendian;
fname : 64*8 : string;
zeroguid : 16*8 : bitstring;
zeroguid : 16*8 : bitstring;
0_l : 4*8 : littleendian;
zeroguid : 16*8 : bitstring;
0_l : 4*8 : littleendian;
zeroes_bitstring (340*8) : 340*8 : bitstring
} in
assert (bitstring_length before_csum = 0x1fc * 8);
let csum = bitstring_fold_left_int32_le Int32.logxor 0_l before_csum in
let csum_and_after =
BITSTRING {
csum : 4*8 : littleendian;
zeroes_bitstring ((0x1000-0x200)*8) : (0x1000-0x200)*8 : bitstring
} in
let new_header = concat [before_csum; csum_and_after] in
assert (bitstring_length header = bitstring_length new_header);
new_header
(* Write it. *)
let () =
let file = concat [header; data] in
bitstring_to_file file filename
|