1 /*
2  * ntreg.h - NT Registry Hive access library, constants & structures
3  *
4  * NOTE: defines are not frozen. It can and will change every release.
5  *
6  *****
7  *
8  * NTREG - Window registry file reader / writer library
9  * Copyright (c) 1997-2013 Petter Nordahl-Hagen.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation;
14  * version 2.1 of the License.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  * See file LGPL.txt for the full license.
21  *
22  */
23 
24 
25 #ifndef _INCLUDE_NTREG_H
26 #define _INCLUDE_NTREG_H 1
27 
28 #define SZ_MAX     4096       /* Max unicode strlen before we truncate */
29 
30 #define KEY_ROOT   0x2c         /* Type ID of ROOT key node */
31 #define KEY_NORMAL 0x20       /* Normal nk key */
32 
33 #define ABSPATHLEN 4096
34 
35 
36 /* hbin page size. hbins are minimum this, and always multiple of this */
37 #define HBIN_PAGESIZE 0x1000
38 /* Hive filesize seems to always be multiple of this */
39 #define REGF_FILEDIVISOR 0x40000
40 
41 /* Larger than this, and values seems split into several blocks */
42 #define VAL_DIRECT_LIMIT 0x3fd0
43 
44 
45 /* Datatypes of the values in the registry */
46 
47 #define REG_NONE                    0  /* No value type */
48 #define REG_SZ                      1  /* Unicode nul terminated string */
49 #define REG_EXPAND_SZ               2  /* Unicode nul terminated string + env */
50 #define REG_BINARY                  3  /* Free form binary */
51 #define REG_DWORD                   4  /* 32-bit number */
52 #define REG_DWORD_BIG_ENDIAN        5  /* 32-bit number */
53 #define REG_LINK                    6  /* Symbolic Link (unicode) */
54 #define REG_MULTI_SZ                7  /* Multiple Unicode strings */
55 #define REG_RESOURCE_LIST           8  /* Resource list in the resource map */
56 #define REG_FULL_RESOURCE_DESCRIPTOR 9 /* Resource list in the hardware description */
57 #define REG_RESOURCE_REQUIREMENTS_LIST 10  /* Uh? Rait.. */
58 #define REG_QWORD                   11 /* Quad word 64 bit, little endian */
59 
60 #define REG_MAX 12
61 
62 
63 /* The first page of the registry file is some kind of header, lot of
64  * it's contents is unknown, and seems to be mostly NULLs anyway.
65  * Note also, that this is the only place in the registry I've been
66  * able to find _any_ kind of checksumming
67  */
68 
69 struct regf_header {
70 
71   int32_t id;            /* 0x00000000	D-Word	ID: ASCII-"regf" = 0x66676572 */
72   int32_t unknown1;      /* 0x00000004	D-Word	???? Mount count */
73   int32_t unknown2;      /* 0x00000008	D-Word	???? Always the same value as at 0x00000004  */
74   char timestamp[8];     /* 0x0000000C	Q-Word	last modify date in WinNT date-format */
75   int32_t unknown3;      /* 0x00000014	D-Word	1 */
76   int32_t unknown4;      /* 0x00000018	D-Word	3 - probably version #. 2 in NT3.51 */
77   int32_t unknown5;      /* 0x0000001C	D-Word	0 */
78   int32_t unknown6;      /* 0x00000020	D-Word	1 */
79   int32_t ofs_rootkey;   /* 0x00000024	D-Word	Offset of 1st key record */
80   int32_t filesize;      /* 0x00000028	D-Word	Offset of first non-used data at end of file */
81   int32_t unknown7;      /* 0x0000002C	D-Word	1 */
82   char name[0x1fc-0x30]; /* 0x00000030  Seems like the hive's name is buried here, max len unknown */
83   int32_t checksum;      /* 0x000001FC	D-Word	Xor sum of all D-Words from 0x00000000 to 0x000001FB */
84 };
85 
86 /* The page header, I don't know if the 14 "dummy" bytes has a meaning,
87  * they seem to be mostly NULLS
88  */
89 
90 struct  hbin_page {
91 
92   int32_t id;          /* 0x0000	D-Word	ID: ASCII-"hbin" = 0x6E696268  */
93   int32_t ofs_self;    /* 0x0004	D-Word	Offset to itself, could be for sanity check */
94   int32_t ofs_next;    /* 0x0008	D-Word	Relative offset to next hbin (practically length of this one)  */
95   char dummy1[14];     /*               0x14 to 0x001b may be timestamp in some windows versions, at least in first hbin */
96   int32_t len_page;    /* 0x001C	D-Word	Block-size??? Don't look like it. Most often zero. */
97 
98   int32_t firstlink;   /* 0x0020  First data block likage */
99   /*  char data[1];      0x0020   First data block starts here           */
100 
101 };
102 
103 /* Minimum block size utilized at end of hbin
104  * Make routines accept 0 size block when at end
105  */
106 #define HBIN_ENDFILL 0
107 
108 
109 
110 /* Security descriptor. I know how it's linked, but don't know
111    how the real security data is constructed, it may as well
112    be like the higher level security structs defined by MS in its
113    includes & NT docs. Currently, I have no use for it.
114    Note that keys sharing the exact same security settings will
115    most likely point to the same security descriptor, thus
116    saving space and making it fast to make objects inherit settings
117    (is inheritance supported? they speak of security inheritance as a "new"
118     feature in the filesystem on NT5, even though I think it was
119     also supported by the lower levels in the earlier versions)
120 */
121 struct sk_key {
122 
123   short id;          /* 0x0000	Word	ID: ASCII-"sk" = 0x6B73        */
124   short dummy1;      /* 0x0002	Word	Unused                         */
125   int32_t  ofs_prevsk;  /* 0x0004	D-Word	Offset of previous "sk"-Record */
126   int32_t  ofs_nextsk;  /* 0x0008	D-Word	Offset of next "sk"-Record     */
127   int32_t  no_usage;    /* 0x000C	D-Word	usage-counter                  */
128   int32_t  len_sk;      /* 0x0010	D-Word	Size of "sk"-record in bytes   */
129   char  data[4];     /* Security data up to len_sk bytes               */
130 
131 };
132 
133 /* This is the subkeylist/hash structure. NT4.0+.
134  * ID + count, then count number of offset/4byte "hash". (not true hash)
135  * Probably changed from the 3.x version to make it faster to
136  * traverse the registry if you're looking for a specific name
137  * (saves lookups in 'nk's that have the first 4 name chars different)
138  */
139 
140 struct lf_key {
141 
142   short id;         /* 0x0000	Word	ID: ASCII-"lf" = 0x666C or "lh" = 0x686c */
143   short no_keys;    /* 0x0002	Word	number of keys          */
144                     /* 0x0004	????	Hash-Records            */
145 
146  union {
147 
148     struct lf_hash {
149       int32_t ofs_nk;    /* 0x0000	D-Word	Offset of corresponding "nk"-Record  */
150       char name[4];   /* 0x0004	D-Word	ASCII: the first 4 characters of the key-name,  */
151     } hash[1];
152 
153       /* WinXP uses a more real hash instead (base 37 of uppercase name chars)  */
154       /* 		padded with 0's. Case sensitiv!                         */
155 
156     struct lh_hash {
157       int32_t ofs_nk;    /* 0x0000	D-Word	Offset of corresponding "nk"-Record  */
158       int32_t hash;      /* 0x0004	D-Word	ASCII: the first 4 characters of the key-name,  */
159     } lh_hash[1];
160   };
161 
162 };
163 
164 /* 3.x version of the above, contains only offset table, NOT
165  * any start of names "hash". Thus needs 'nk' lookups for searches.
166  */
167 struct li_key {
168 
169   short id;         /* 0x0000	Word	ID: ASCII-"li" = 0x696C */
170   short no_keys;    /* 0x0002	Word	number of keys          */
171                     /* 0x0004	????	Hash-Records            */
172   struct li_hash {
173     int32_t ofs_nk;    /* 0x0000	D-Word	Offset of corresponding "nk"-Record  */
174   } hash[1];
175 };
176 
177 
178 /* Indirect pointer list for value data, vk points to this instead of values data directly
179  * Seems to be used when value data is large, maybe larger than 3-4k.
180  */
181 struct db_key {
182 
183   short id;         /* 0x0000	Word	ID: ASCII-"li" = 0x6462 */
184   short no_part;    /* 0x0002	Word	number of data parts    */
185                     /* 0x0004	????	Pointers to data        */
186   int32_t ofs_data;    /* 0x0000	D-Word	Offset to list of data blocks  */
187   /* Something else seems to follow here, 4 bytes at least */
188   /* and why not list the data block in here ???? why make another list?? */
189 };
190 
191 
192 
193 /* This is a list of pointers to struct li_key, ie
194  * an extention record if many li's.
195  * This happens in NT4&5 when the lf hashlist grows larger
196  * than about 400-500 entries/subkeys??, then the nk_key->ofs_lf points to this
197  * instead of directly to an lf.
198  * The sub-indices this points to seems to be li (yes!) in NT4 and 2k.
199  * In XP and newer they point to lh which is more efficient.
200  * Likely to happen in HKLM\Software\classes (file extention list) and
201  * in SAM when many users.
202  */
203 struct ri_key {
204 
205   short id;         /* 0x0000	Word	ID: ASCII-"ri" = 0x6972 */
206   short no_lis;    /* 0x0002	Word	number of pointers to li */
207                     /* 0x0004	????	Hash-Records            */
208   struct ri_hash {
209       int32_t ofs_li;    /* 0x0000	D-Word	Offset of corresponding "li"-Record  */
210   } hash[1];
211 };
212 
213 
214 /* This is the value descriptor.
215  * If the sign bit (31st bit) in the length field is set, the value is
216  * stored inline this struct, and not in a seperate data chunk -
217  * the data itself is then in the ofs_data field, happens for DWORD all the time
218  * If the name size == 0, then the struct is probably cut short right
219  * after the val_type or flag.
220  * The flag meaning is rather unknown.
221  */
222 struct vk_key {
223 
224                     /* Offset	Size	Contents                 */
225   short id;         /* 0x0000	Word	ID: ASCII-"vk" = 0x6B76  */
226   short len_name;   /* 0x0002	Word	name length              */
227   int32_t  len_data;   /* 0x0004	D-Word	length of the data       */
228   int32_t  ofs_data;   /* 0x0008	D-Word	Offset of Data           */
229   int32_t  val_type;   /* 0x000C	D-Word	Type of value            */
230   short flag;       /* 0x0010	Word	Flag
231                                 0x1 ANSI encoding                */
232   short dummy1;     /* 0x0012	Word	Unused (data-trash)      */
233   char  keyname[1]; /* 0x0014	????	Name                     */
234 
235 };
236 
237 /* This is the key node (ie directory) descriptor, can contain subkeys and/or values.
238  * Note that for values, the count is stored here, but for subkeys
239  * there's a count both here and in the offset-table (lf or li struct).
240  * What happens if these mismatch is not known.
241  * What's the classname thingy? Can't remember seeing that used in
242  * anything I've looked at.
243  */
244 struct nk_key {
245 
246                         /* Offset	Size	Contents */
247   short id;             /*  0x0000	Word	ID: ASCII-"nk" = 0x6B6E                */
248   short type;           /*  0x0002	Word	for the root-key: 0x2C, otherwise 0x20 */
249 			/*              0x20 seems a flag for ANSI encoding            */
250                         /*            0x1000 is used in some places in Vista and newer */
251   char  timestamp[12];  /*  0x0004	Q-Word	write-date/time in windows nt notation */
252   int32_t  ofs_parent;     /*  0x0010	D-Word	Offset of Owner/Parent key             */
253   int32_t  no_subkeys;     /*  0x0014	D-Word	number of sub-Keys                     */
254   int32_t  dummy1;
255   int32_t  ofs_lf;         /*  0x001C	D-Word	Offset of the sub-key lf-Records       */
256   int32_t  dummy2;
257   int32_t  no_values;      /*  0x0024	D-Word	number of values                       */
258   int32_t  ofs_vallist;    /*  0x0028	D-Word	Offset of the Value-List               */
259   int32_t  ofs_sk;         /*  0x002C	D-Word	Offset of the sk-Record                */
260   int32_t  ofs_classnam;   /*  0x0030	D-Word	Offset of the Class-Name               */
261   int32_t  dummy3;         /*  0x0034   unknown   some of these may be used by vista   */
262   int32_t  dummy4;         /*  0x0038   unknown   and newer ??                         */
263   int32_t  dummy5;         /*  0x003c   unknown                                        */
264   int32_t  dummy6;         /*  0x0040   unknown                                        */
265   int32_t  dummy7;         /*  0x0044	unknown                                        */
266   short len_name;       /*  0x0048	Word	name-length                            */
267   short len_classnam;   /*  0x004A	Word	class-name length                      */
268   char  keyname[1];     /*  0x004C	????	key-name                               */
269 };
270 
271 /*********************************************************************************/
272 
273 /* Structure defines for my routines */
274 
275 struct ex_data {
276   int nkoffs;
277   struct nk_key *nk;
278   char *name;
279 };
280 
281 struct vex_data {
282   int vkoffs;
283   struct vk_key *vk;
284   int type;       /* Value type REG_??? */
285   int size;       /* Values size (normalized, inline accounted for) */
286   int val;        /* Actual value itself if type==REG_DWORD */
287   char *name;
288 };
289 
290 struct keyval {
291   int len;      /* Length of databuffer */
292   int data;    /* Data. Goes on for length of value */
293 };
294 
295 struct keyvala {
296   int len;      /* Length of databuffer */
297   int data[1];    /* Data. Goes on for length of value */
298 };
299 
300 /* Types to trav_path() */
301 #define TPF_NK           0
302 #define TPF_VK           1
303 #define TPF_ABS          64
304 #define TPF_EXACT        128
305 #define TPF_VK_SHORT     256        /* To get type field instead of data field, used in SAM */
306 #define TPF_NK_EXACT     (TPF_NK | TPF_EXACT)
307 #define TPF_VK_EXACT     (TPF_VK | TPF_EXACT)
308 #define TPF_VK_ABS       (TPF_VK | TPF_ABS)  /* Name is literal, not a path */
309 
310 
311 /* Hive open modes */
312 #define HMODE_RW        0
313 #define HMODE_RO        0x1
314 #define HMODE_OPEN      0x2
315 #define HMODE_DIRTY     0x4
316 #define HMODE_NOALLOC   0x8        /* Don't allocate new blocks */
317 #define HMODE_NOEXPAND  0x10       /* Don't expand file with new hbin */
318 #define HMODE_DIDEXPAND 0x20       /* File has been expanded */
319 #define HMODE_VERBOSE 0x1000
320 #define HMODE_TRACE   0x2000
321 #define HMODE_INFO    0x4000       /* Show some info on open and close */
322 
323 /* Suggested type of hive loaded, guessed by library, but not used by it */
324 #define HTYPE_UNKNOWN   0
325 #define HTYPE_SAM       1
326 #define HTYPE_SYSTEM    2
327 #define HTYPE_SECURITY  3
328 #define HTYPE_SOFTWARE  4
329 
330 
331 
332 /* Hive definition, allocated by openHive(), dealloc by closeHive()
333  * contains state data, must be passed in all functions
334  */
335 struct hive {
336   char *filename;        /* Hives filename */
337   int  filedesc;         /* File descriptor (only valid if state == OPEN) */
338   int  state;            /* Current state of hive */
339   int  type;             /* Suggested type of hive. NOTE: Library will guess when
340 			    it loads it, but application may change it if needed */
341   int  pages;            /* Number of pages, total */
342   int  useblk;           /* Total # of used blocks */
343   int  unuseblk;         /* Total # of unused blocks */
344   int  usetot;           /* total # of bytes in useblk */
345   int  unusetot;         /* total # of bytes in unuseblk */
346   int  size;             /* Hives size (filesize) in bytes, incl regf header */
347   int  rootofs;          /* Offset of root-node */
348   int  lastbin;          /* Offset to last HBIN */
349   int  endofs;           /* Offset of first non HBIN page, we can expand from here */
350   short nkindextype;     /* Subkey-indextype the root key uses */
351   char *buffer;          /* Files raw contents */
352 };
353 
354 /***************************************************/
355 
356 /* Various nice macros */
357 
358 #define CREATE(result, type, number)\
359     { \
360         if (!((result) = (type *) calloc ((number), sizeof(type)))) { \
361             perror("malloc failure"); \
362             abort() ; \
363        } \
364     }
365 #define ALLOC(result, size, number)\
366     { \
367         if (!((result) = (void *) calloc ((number), (size)))) { \
368             perror("malloc failure"); \
369             abort() ; \
370        } \
371     }
372 #define FREE(p) { if (p) { free(p); (p) = 0; } }
373 
374 /* Debug / verbosity message macro */
375 
376 #define VERB(h, string) \
377      { \
378        if ((h)->state & HMODE_VERBOSE) printf((string)); \
379      }
380 
381 #define VERBF(h, ...) \
382      { \
383        if ((h)->state & HMODE_VERBOSE) printf(__VA_ARGS__); \
384      }
385 
386 
387 /******* Function prototypes **********/
388 
389 char *str_dup( const char *str );
390 char *str_cat(char *str, char *add);
391 char *str_catf(char *str, const char *format, ... );
392 int fmyinput(char *prmpt, char *ibuf, int maxlen);
393 void hexprnt(char *s, unsigned char *bytes, int len);
394 void hexdump(char *hbuf, int start, int stop, int ascii);
395 int find_in_buf(char *buf, char *what, int sz, int len, int start);
396 int get_int( char *array );
397 void cheap_uni2ascii(char *src, char *dest, int l);
398 void cheap_ascii2uni(char *src, char *dest, int l);
399 void skipspace(char **c);
400 int gethex(char **c);
401 int gethexorstr(char **c, char *wb);
402 int debugit(char *buf, int sz);
403 struct keyval *reg_valcat(struct keyval *a, struct keyval *b);
404 
405 
406 int parse_block(struct hive *hdesc, int vofs,int verbose);
407 int ex_next_n(struct hive *hdesc, int nkofs, int *count, int *countri, struct ex_data *sptr);
408 int ex_next_v(struct hive *hdesc, int nkofs, int *count, struct vex_data *sptr);
409 int get_abs_path(struct hive *hdesc, int nkofs, char *path, int maxlen);
410 int trav_path(struct hive *hdesc, int vofs, char *path, int type);
411 int get_val_type(struct hive *hdesc, int vofs, char *path, int exact);
412 int set_val_type(struct hive *hdesc, int vofs, char *path, int exact, int type);
413 int get_val_len(struct hive *hdesc, int vofs, char *path, int exact);
414 void *get_val_data(struct hive *hdesc, int vofs, char *path, int val_type, int exact);
415 struct keyval *get_val2buf(struct hive *hdesc, struct keyval *kv,
416 			   int vofs, char *path, int type, int exact );
417 int get_dword(struct hive *hdesc, int vofs, char *path, int exact);
418 int put_buf2val(struct hive *hdesc, struct keyval *kv,
419 		int vofs, char *path, int type, int exact );
420 int put_dword(struct hive *hdesc, int vofs, char *path, int exact, int dword);
421 void export_key(struct hive *hdesc, int nkofs, char *name, char *filename, char *prefix);
422 void closeHive(struct hive *hdesc);
423 int writeHive(struct hive *hdesc);
424 struct hive *openHive(char *filename, int mode);
425 
426 void nk_ls(struct hive *hdesc, char *path, int vofs, int type);
427 
428 struct vk_key *add_value(struct hive *hdesc, int nkofs, char *name, int type);
429 void del_allvalues(struct hive *hdesc, int nkofs);
430 int del_value(struct hive *hdesc, int nkofs, char *name, int exact);
431 struct nk_key *add_key(struct hive *hdesc, int nkofs, char *name);
432 int del_key(struct hive *hdesc, int nkofs, char *name);
433 void rdel_keys(struct hive *hdesc, char *path, int nkofs);
434 struct keyval *get_class(struct hive *hdesc, int curnk, char *path);
435 
436 int add_bin(struct hive *hdesc, int size);
437 
438 void import_reg(struct hive *hdesc, char *filename, char *prefix);
439 
440 int de_escape(char *s, int wide);
441 
442 char *string_regw2prog(void *string, int len);
443 
444 
445 /* From edlib.c */
446 void regedit_interactive(struct hive *hive[], int no_hives);
447 void cat_dpi(struct hive *hdesc, int nkofs, char *path);
448 
449 
450 #endif
451 
452