(* 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 <> 2 then ( eprintf "Error: missing argument. Usage: %s hivefile " Sys.executable_name; exit 1 ) let filename = Sys.argv.(1) (* 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 (* 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, but with unknown fields cleared. Do it in * two parts, first creating everything up to the checksum, then * calculating the checksum and appending checksum and the final * field. *) 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; 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