source: trunk/include/regfi.h @ 157

Last change on this file since 157 was 157, checked in by tim, 14 years ago

reorganized data parsing in regfi

simplified some length validation

added big data support to reglookup-recover

fixed reglookup-recover's handling of data values in the offset

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