source: trunk/include/regfi.h @ 152

Last change on this file since 152 was 152, checked in by tim, 15 years ago

preliminary support for big data records

switched to using key flags rather than incorrect key types

  • Property svn:keywords set to Id
File size: 19.0 KB
Line 
1/*
2 * Branched from Samba project Subversion repository, version #6903:
3 *   http://viewcvs.samba.org/cgi-bin/viewcvs.cgi/trunk/source/include/regfio.h?rev=6903&view=auto
4 *
5 * Windows NT (and later) registry parsing library
6 *
7 * Copyright (C) 2005-2009 Timothy D. Morgan
8 * Copyright (C) 2005 Gerald (Jerry) Carter
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 3 of the License.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 * $Id: regfi.h 152 2009-06-02 20:00:38Z tim $
24 */
25
26/************************************************************
27 * Most of this information was obtained from
28 * http://www.wednesday.demon.co.uk/dosreg.html
29 * Thanks Nigel!
30 ***********************************************************/
31
32#ifndef _REGFI_H
33#define _REGFI_H
34
35#include <stdlib.h>
36#include <stdio.h>
37#include <stdbool.h>
38#include <stdarg.h>
39#include <string.h>
40#include <errno.h>
41#include <time.h>
42#include <fcntl.h>
43#include <sys/stat.h>
44#include <sys/types.h>
45#include <unistd.h>
46#include <assert.h>
47
48#include "talloc.h"
49#include "smb_deps.h"
50#include "winsec.h"
51#include "void_stack.h"
52#include "range_list.h"
53#include "lru_cache.h"
54
55/******************************************************************************/
56
57/* regfi library error message types */
58#define REGFI_MSG_INFO  0x0001
59#define REGFI_MSG_WARN  0x0004
60#define REGFI_MSG_ERROR 0x0010
61
62/* Windows is lame */
63#ifdef O_BINARY
64#define REGFI_OPEN_FLAGS O_RDONLY|O_BINARY
65#else
66#define REGFI_OPEN_FLAGS O_RDONLY
67#endif
68
69/* Registry data types */
70#define REG_NONE                       0
71#define REG_SZ                         1
72#define REG_EXPAND_SZ                  2
73#define REG_BINARY                     3
74#define REG_DWORD                      4
75#define REG_DWORD_LE                   4  /* DWORD, little endian */
76#define REG_DWORD_BE                   5  /* DWORD, big endian */
77#define REG_LINK                       6
78#define REG_MULTI_SZ                   7
79#define REG_RESOURCE_LIST              8
80#define REG_FULL_RESOURCE_DESCRIPTOR   9
81#define REG_RESOURCE_REQUIREMENTS_LIST 10
82#define REG_QWORD                      11 /* 64-bit little endian */
83/* XXX: Has MS defined a REG_QWORD_BE? */
84/* Not a real type in the registry */
85#define REG_KEY                    0x7FFFFFFF
86
87#define REGFI_MAX_DEPTH            512
88#define REGFI_OFFSET_NONE          0xffffffff
89
90/* XXX: This is totally arbitrary right now. */
91#define REGFI_MAX_SUBKEY_DEPTH     255
92
93/* Header sizes and magic number lengths for various records */
94#define REGFI_HBIN_ALLOC           0x1000 /* Minimum allocation unit for HBINs */
95#define REGFI_REGF_SIZE            0x1000 /* "regf" header block size */
96#define REGFI_REGF_MAGIC_SIZE      4
97#define REGFI_REGF_NAME_SIZE       64
98#define REGFI_REGF_RESERVED1_SIZE  340
99#define REGFI_REGF_RESERVED2_SIZE  3528
100#define REGFI_HBIN_MAGIC_SIZE      4
101#define REGFI_CELL_MAGIC_SIZE      2
102#define REGFI_HBIN_HEADER_SIZE     0x20
103#define REGFI_NK_MIN_LENGTH        0x4C
104#define REGFI_VK_MIN_LENGTH        0x14
105#define REGFI_SK_MIN_LENGTH        0x14
106#define REGFI_SUBKEY_LIST_MIN_LEN  0x4
107
108
109/* Constants used for validation */
110/* XXX: Can we add clock resolution validation as well as range?  It has
111 *      been reported that Windows timestamps are never more than a
112 *      certain granularity (250ms?), which could be used to help
113 *      eliminate false positives.  Would need to verify this and
114 *      perhaps conservatively implement a check.
115 */
116 /* Minimum time is Jan 1, 1990 00:00:00 */
117#define REGFI_MTIME_MIN_HIGH       0x01B41E6D
118#define REGFI_MTIME_MIN_LOW        0x26F98000
119 /* Maximum time is Jan 1, 2290 00:00:00
120  * (We hope no one is using Windows by then...)
121  */
122#define REGFI_MTIME_MAX_HIGH       0x03047543
123#define REGFI_MTIME_MAX_LOW        0xC80A4000
124
125
126/* Flags for the vk records */
127/* XXX: This next flag may be incorrect.  According to Jeffrey Muir,
128*       this may actually indicate that the value name is stored in
129*       UTF-16LE.
130*/
131#define REGFI_VK_FLAG_NAME_PRESENT 0x0001
132#define REGFI_VK_DATA_IN_OFFSET    0x80000000
133#define REGFI_VK_MAX_DATA_LENGTH   1024*1024  /* XXX: This is arbitrary */
134
135
136/* Known key flags */
137/*******************/
138/* These next two show up on normal-seeming keys in Vista and W2K3 registries */
139#define REGFI_NK_FLAG_UNKNOWN1     0x4000
140#define REGFI_NK_FLAG_UNKNOWN2     0x1000
141
142/* This next one shows up on root keys in some Vista "software" registries */
143#define REGFI_NK_FLAG_UNKNOWN3     0x0080
144
145/* Predefined handle.  Rumor has it that the valuelist count for this key is
146 * where the handle is stored.
147 * http://msdn.microsoft.com/en-us/library/ms724836(VS.85).aspx
148 */
149#define REGFI_NK_FLAG_PREDEF_KEY   0x0040
150
151/* The name will be in ASCII if this next bit is set, otherwise UTF-16LE */
152#define REGFI_NK_FLAG_ASCIINAME    0x0020
153
154/* Symlink key. 
155 * See: http://www.codeproject.com/KB/system/regsymlink.aspx
156 */
157#define REGFI_NK_FLAG_LINK         0x0010
158
159/* This key cannot be deleted */
160#define REGFI_NK_FLAG_NO_RM        0x0008
161
162/* Root of a hive */
163#define REGFI_NK_FLAG_ROOT         0x0004
164
165/* Mount point of another hive.  NULL/(default) value indicates which hive
166 * and where in the hive it points to.
167 */
168#define REGFI_NK_FLAG_HIVE_LINK    0x0002
169
170/* These keys shouldn't be stored on disk, according to:
171 * http://geekswithblogs.net/sdorman/archive/2007/12/24/volatile-registry-keys.aspx
172 */
173#define REGFI_NK_FLAG_VOLATILE     0x0001
174
175/* Useful for identifying unknown flag types */
176#define REGFI_NK_KNOWN_FLAGS       (REGFI_NK_FLAG_PREDEF_KEY\
177                                    | REGFI_NK_FLAG_ASCIINAME\
178                                    | REGFI_NK_FLAG_LINK\
179                                    | REGFI_NK_FLAG_NO_RM\
180                                    | REGFI_NK_FLAG_ROOT\
181                                    | REGFI_NK_FLAG_HIVE_LINK\
182                                    | REGFI_NK_FLAG_VOLATILE\
183                                    | REGFI_NK_FLAG_UNKNOWN1\
184                                    | REGFI_NK_FLAG_UNKNOWN2)
185
186/* HBIN block */
187typedef struct _regfi_hbin
188{
189  uint32 file_off;       /* my offset in the registry file */
190  uint32 ref_count;      /* how many active records are pointing to this
191                          * block (not used currently)
192                          */
193 
194  uint32 first_hbin_off; /* offset from first hbin block */
195  uint32 block_size;     /* block size of this block
196                          * Should be a multiple of 4096 (0x1000)
197                          */
198  uint32 next_block;     /* relative offset to next block. 
199                          * NOTE: This value may be unreliable!
200                          */
201
202  uint8 magic[REGFI_HBIN_MAGIC_SIZE]; /* "hbin" */
203} REGFI_HBIN;
204
205
206/* Subkey List -- list of key offsets and hashed names for consistency */
207typedef struct 
208{
209  /* Virtual offset of NK record or additional subkey list,
210   * depending on this list's type.
211   */
212  uint32 offset;
213
214  uint32 hash;
215} REGFI_SUBKEY_LIST_ELEM;
216
217
218typedef struct _regfi_subkey_list
219{
220  /* Real offset of this record's cell in the file */
221  uint32 offset;
222
223  uint32 cell_size;
224 
225  /* Number of immediate children */
226  uint32 num_children; 
227
228  /* Total number of keys referenced by this list and it's children */
229  uint32 num_keys;     
230
231  REGFI_SUBKEY_LIST_ELEM* elements;
232  uint8 magic[REGFI_CELL_MAGIC_SIZE];
233
234  /* Set if the magic indicates this subkey list points to child subkey lists */
235  bool recursive_type; 
236} REGFI_SUBKEY_LIST;
237
238
239typedef uint32 REGFI_VALUE_LIST_ELEM;
240typedef struct _regfi_value_list
241{
242  /* Actual number of values referenced by this list. 
243   * May differ from parent key's num_values if there were parsing errors.
244   */
245  uint32 num_values;
246
247  REGFI_VALUE_LIST_ELEM* elements;
248} REGFI_VALUE_LIST;
249
250
251/* Value record */
252typedef struct 
253{
254  uint32 offset;        /* Real offset of this record's cell in the file */
255  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
256
257  uint8* data;
258  char*  valuename;
259  uint16 name_length;
260  uint32 hbin_off;      /* offset from beginning of this hbin block */
261 
262  uint32 data_size;
263  uint32 data_off;      /* offset of data cell (virtual) */
264  uint32 type;
265  uint8  magic[REGFI_CELL_MAGIC_SIZE];
266  uint16 flag;
267  uint16 unknown1;
268  bool data_in_offset;
269} REGFI_VK_REC;
270
271
272/* Key Security */
273struct _regfi_sk_rec;
274
275typedef struct _regfi_sk_rec
276{
277  uint32 offset;        /* Real file offset of this record */
278  uint32 cell_size;     /* ((start_offset - end_offset) & 0xfffffff8) */
279
280  WINSEC_DESC* sec_desc;
281  uint32 hbin_off;      /* offset from beginning of this hbin block */
282 
283  uint32 prev_sk_off;
284  uint32 next_sk_off;
285  uint32 ref_count;
286  uint32 desc_size;     /* size of security descriptor */
287  uint16 unknown_tag;
288  uint8  magic[REGFI_CELL_MAGIC_SIZE];
289} REGFI_SK_REC;
290
291
292/* Key Name */
293typedef struct
294{
295  uint32 offset;        /* Real offset of this record's cell in the file */
296  uint32 cell_size;     /* Actual or estimated length of the cell. 
297                         * Always in multiples of 8.
298                         */
299
300  /* link in the other records here */
301  REGFI_VALUE_LIST* values;
302  REGFI_SUBKEY_LIST* subkeys;
303 
304  /* header information */
305  uint16 key_type;
306  uint8  magic[REGFI_CELL_MAGIC_SIZE];
307  NTTIME mtime;
308  uint16 name_length;
309  uint16 classname_length;
310  char* classname;
311  char* keyname;
312  uint32 parent_off;                /* pointer to parent key */
313  uint32 classname_off;
314 
315  /* max lengths */
316  uint32 max_bytes_subkeyname;      /* max subkey name * 2 */
317  uint32 max_bytes_subkeyclassname; /* max subkey classname length (as if) */
318  uint32 max_bytes_valuename;       /* max valuename * 2 */
319  uint32 max_bytes_value;           /* max value data size */
320 
321  /* unknowns */
322  uint32 unknown1;
323  uint32 unknown2;
324  uint32 unknown3;
325  uint32 unk_index;                 /* nigel says run time index ? */
326 
327  /* children */
328  uint32 num_subkeys;
329  uint32 subkeys_off;   /* offset of subkey list that points to NK records */
330  uint32 num_values;
331  uint32 values_off;    /* value lists which point to VK records */
332  uint32 sk_off;        /* offset to SK record */
333} REGFI_NK_REC;
334
335
336
337/* REGF block */
338typedef struct 
339{
340  /* Run-time information */
341  /************************/
342  /* file descriptor */
343  int fd;
344
345  /* For sanity checking (not part of the registry header) */
346  uint32 file_length;
347
348  /* Metadata about hbins */
349  range_list* hbins;
350
351  /* SK record cached since they're repeatedly reused */
352  lru_cache* sk_cache;
353
354  /* Error/warning/info messages returned by lower layer functions */
355  char* last_message;
356
357  /* Mask for error message types that will be stored. */
358  uint16 msg_mask;
359
360
361  /* Data parsed from file header */
362  /********************************/
363  uint8  magic[REGFI_REGF_MAGIC_SIZE];/* "regf" */
364
365 /* These sequence numbers should match if
366  * the hive was properly synced to disk.
367  */
368  uint32 sequence1;           
369  uint32 sequence2;
370
371  NTTIME mtime;
372  uint32 major_version;  /* Set to 1 in all known hives */
373  uint32 minor_version;  /* Set to 3 or 5 in all known hives */
374  uint32 type;           /* XXX: Unverified.  Set to 0 in all known hives */
375  uint32 format;         /* XXX: Unverified.  Set to 1 in all known hives */
376
377  uint32 root_cell;  /* Offset to root cell in the first (or any?) hbin block */
378  uint32 last_block; /* Offset to last hbin block in file */
379
380  uint32 cluster;    /* XXX: Unverified. Set to 1 in all known hives */
381
382  /* Matches hive's base file name. Stored in UTF-16LE */
383  uint8 file_name[REGFI_REGF_NAME_SIZE];
384
385  WINSEC_UUID* rm_id;       /* XXX: Unverified. */
386  WINSEC_UUID* log_id;      /* XXX: Unverified. */
387  WINSEC_UUID* tm_id;       /* XXX: Unverified. */
388  uint32 flags;             /* XXX: Unverified. */
389  uint32 guid_signature;    /* XXX: Unverified. */
390
391  uint32 checksum;          /* Stored checksum from file */
392  uint32 computed_checksum; /* Our own calculation of the checksum.
393                             * (XOR of bytes 0x0000 - 0x01FB) */
394
395  WINSEC_UUID* thaw_tm_id;  /* XXX: Unverified. */
396  WINSEC_UUID* thaw_rm_id;  /* XXX: Unverified. */
397  WINSEC_UUID* thaw_log_id; /* XXX: Unverified. */
398  uint32 boot_type;         /* XXX: Unverified. */
399  uint32 boot_recover;      /* XXX: Unverified. */
400
401  /* This seems to include random junk.  Possibly unsanitized memory left over
402   * from when header block was written.  For instance, chunks of nk records
403   * can be found, though often it's all 0s. */
404  uint8 reserved1[REGFI_REGF_RESERVED1_SIZE];
405
406  /* This is likely reserved and unusued currently.  (Should be all 0s.)
407   * Included here for easier access in looking for hidden data
408   * or doing research. */
409  uint8 reserved2[REGFI_REGF_RESERVED2_SIZE];
410
411} REGFI_FILE;
412
413
414/* XXX: Should move all caching (SK records, HBINs, NKs, etc) to a single
415 *      structure, probably REGFI_FILE.  Once key caching is in place,
416 *      convert key_positions stack to store just key offsets rather than
417 *      whole keys.
418 */
419typedef struct _regfi_iterator
420{
421  REGFI_FILE* f;
422  void_stack* key_positions;
423  REGFI_NK_REC* cur_key;
424  uint32 cur_subkey;
425  uint32 cur_value;
426} REGFI_ITERATOR;
427
428
429typedef struct _regfi_iter_position
430{
431  REGFI_NK_REC* nk;
432  uint32 cur_subkey;
433  /* We could store a cur_value here as well, but didn't see
434   * the use in it right now.
435   */
436} REGFI_ITER_POSITION;
437
438
439typedef struct _regfi_buffer
440{
441  uint8* buf;
442  uint32_t len;
443} REGFI_BUFFER;
444
445
446/******************************************************************************/
447/*                         Main iterator API                                  */
448/******************************************************************************/
449REGFI_FILE*           regfi_open(const char* filename);
450int                   regfi_close(REGFI_FILE* r);
451
452/* regfi_get_messages: Get errors, warnings, and/or verbose information
453 *                     relating to processing of the given registry file.
454 *
455 * Arguments:
456 *   file     -- the structure for the registry file
457 *
458 * Returns:
459 *   A newly allocated char* which must be free()d by the caller.
460 */
461char*                 regfi_get_messages(REGFI_FILE* file);
462void                  regfi_set_message_mask(REGFI_FILE* file, uint16 mask);
463
464REGFI_ITERATOR*       regfi_iterator_new(REGFI_FILE* fh);
465void                  regfi_iterator_free(REGFI_ITERATOR* i);
466bool                  regfi_iterator_down(REGFI_ITERATOR* i);
467bool                  regfi_iterator_up(REGFI_ITERATOR* i);
468bool                  regfi_iterator_to_root(REGFI_ITERATOR* i);
469
470bool                  regfi_iterator_find_subkey(REGFI_ITERATOR* i, 
471                                                 const char* subkey_name);
472bool                  regfi_iterator_walk_path(REGFI_ITERATOR* i, 
473                                               const char** path);
474const REGFI_NK_REC*   regfi_iterator_cur_key(REGFI_ITERATOR* i);
475const REGFI_SK_REC*   regfi_iterator_cur_sk(REGFI_ITERATOR* i);
476
477REGFI_NK_REC*         regfi_iterator_first_subkey(REGFI_ITERATOR* i);
478REGFI_NK_REC*         regfi_iterator_cur_subkey(REGFI_ITERATOR* i);
479REGFI_NK_REC*         regfi_iterator_next_subkey(REGFI_ITERATOR* i);
480
481bool                  regfi_iterator_find_value(REGFI_ITERATOR* i, 
482                                                const char* value_name);
483REGFI_VK_REC*         regfi_iterator_first_value(REGFI_ITERATOR* i);
484REGFI_VK_REC*         regfi_iterator_cur_value(REGFI_ITERATOR* i);
485REGFI_VK_REC*         regfi_iterator_next_value(REGFI_ITERATOR* i);
486
487
488/********************************************************/
489/* Middle-layer structure loading, linking, and caching */
490/********************************************************/
491REGFI_NK_REC*         regfi_load_key(REGFI_FILE* file, uint32 offset, 
492                                     bool strict);
493REGFI_VK_REC*         regfi_load_value(REGFI_FILE* file, uint32 offset, 
494                                       bool strict);
495REGFI_SUBKEY_LIST*    regfi_load_subkeylist(REGFI_FILE* file, uint32 offset,
496                                            uint32 num_keys, uint32 max_size,
497                                            bool strict);
498REGFI_VALUE_LIST*     regfi_load_valuelist(REGFI_FILE* file, uint32 offset, 
499                                           uint32 num_values, uint32 max_size,
500                                           bool strict);
501
502/* These are cached so return values don't need to be freed. */
503const REGFI_SK_REC*   regfi_load_sk(REGFI_FILE* file, uint32 offset,
504                                    bool strict);
505const REGFI_HBIN*     regfi_lookup_hbin(REGFI_FILE* file, uint32 voffset);
506
507
508
509/************************************/
510/*  Low-layer data structure access */
511/************************************/
512REGFI_FILE*           regfi_parse_regf(int fd, bool strict);
513REGFI_HBIN*           regfi_parse_hbin(REGFI_FILE* file, uint32 offset, 
514                                       bool strict);
515
516
517/* regfi_parse_nk: Parses an NK record.
518 *
519 * Arguments:
520 *   f        -- the registry file structure
521 *   offset   -- the offset of the cell (not the record) to be parsed.
522 *   max_size -- the maximum size the NK cell could be. (for validation)
523 *   strict   -- if true, rejects any malformed records.  Otherwise,
524 *               tries to minimally validate integrity.
525 * Returns:
526 *   A newly allocated NK record structure, or NULL on failure.
527 */
528REGFI_NK_REC*         regfi_parse_nk(REGFI_FILE* file, uint32 offset,
529                                     uint32 max_size, bool strict);
530
531REGFI_SUBKEY_LIST*    regfi_parse_subkeylist(REGFI_FILE* file, uint32 offset,
532                                             uint32 max_size, bool strict);
533
534REGFI_VK_REC*         regfi_parse_vk(REGFI_FILE* file, uint32 offset, 
535                                     uint32 max_size, bool strict);
536
537REGFI_BUFFER          regfi_load_data(REGFI_FILE* file, 
538                                      uint32 data_type, uint32 offset, 
539                                      uint32 length, uint32 max_size, 
540                                      bool data_in_offset, bool strict);
541
542REGFI_BUFFER          regfi_load_big_data(REGFI_FILE* file, 
543                                          uint32 offset, uint32 data_length,
544                                          uint32 cell_length, bool strict);
545
546REGFI_SK_REC*         regfi_parse_sk(REGFI_FILE* file, uint32 offset, 
547                                     uint32 max_size, bool strict);
548
549range_list*           regfi_parse_unalloc_cells(REGFI_FILE* file);
550
551bool                  regfi_parse_cell(int fd, uint32 offset, 
552                                       uint8* hdr, uint32 hdr_len,
553                                       uint32* cell_length, bool* unalloc);
554
555char*                 regfi_parse_classname(REGFI_FILE* file, uint32 offset,
556                                            uint16* name_length, 
557                                            uint32 max_size, bool strict);
558
559/* Dispose of previously parsed records */
560void                  regfi_free_key(REGFI_NK_REC* nk);
561void                  regfi_free_value(REGFI_VK_REC* vk);
562
563
564
565/************************************/
566/*    Private Functions             */
567/************************************/
568REGFI_NK_REC*         regfi_rootkey(REGFI_FILE* file);
569void                  regfi_subkeylist_free(REGFI_SUBKEY_LIST* list);
570uint32                regfi_read(int fd, uint8* buf, uint32* length);
571
572const char*           regfi_type_val2str(unsigned int val);
573int                   regfi_type_str2val(const char* str);
574
575char*                 regfi_get_sacl(WINSEC_DESC* sec_desc);
576char*                 regfi_get_dacl(WINSEC_DESC* sec_desc);
577char*                 regfi_get_owner(WINSEC_DESC* sec_desc);
578char*                 regfi_get_group(WINSEC_DESC* sec_desc);
579
580REGFI_SUBKEY_LIST*    regfi_merge_subkeylists(uint16 num_lists, 
581                                              REGFI_SUBKEY_LIST** lists,
582                                              bool strict);
583REGFI_SUBKEY_LIST*    regfi_load_subkeylist_aux(REGFI_FILE* file, uint32 offset,
584                                                uint32 max_size, bool strict,
585                                                uint8 depth_left);
586void                  regfi_add_message(REGFI_FILE* file, uint16 msg_type, 
587                                        const char* fmt, ...);
588REGFI_NK_REC*         regfi_copy_nk(const REGFI_NK_REC* nk);
589REGFI_VK_REC*         regfi_copy_vk(const REGFI_VK_REC* vk);
590
591#endif  /* _REGFI_H */
Note: See TracBrowser for help on using the repository browser.