Hi, I'm new to this site and also to c++. I am currently in the process of learning c++ and would like the ability to read certain portions of a windows-based registry hive. I have found the source code for and compiled a working program that outputs all values within a specified registry file. What I am looking for is to limit the output to find one certain value within the key located in the registry hive file. I thought this would be as simple of a task as adding an if() to check if the key/values match the ones that i want before outputting.
(eg. Software\Microsoft\Windows NT\CurrentVersion\ProductId)
Here is the source code of the original program:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
struct offsets {
long block_size;
char block_type[2]; // "lf" "il" "ri"
short count;
long first;
long hash;
};
struct key_block {
long block_size;
char block_type[2]; // "nk"
char dummya[18];
int subkey_count;
char dummyb[4];
int subkeys;
char dummyc[4];
int value_count;
int offsets;
char dummyd[28];
short len;
short du;
char name;
};
struct value_block {
long block_size;
char block_type[2]; // "vk"
short name_len;
long size;
long offset;
long value_type;
short flags;
short dummy;
char name;
};
void walk ( char* path, key_block* key ) {
static char* root=(char*)key-0x20, *full=path;
// add current key name to printed path
memcpy(path++,"/",2); memcpy(path,&key->name,key->len); path+=key->len;
// print all contained values
for(int o=0;o<key->value_count;o++){ //
value_block* val = (value_block*)(((int*)(key->offsets+root+4))[o]+root);
// we skip nodes without values
if(!val->offset) continue;
// data are usually in separate blocks without types
char* data = root+val->offset+4;
// but for small values MS added optimization where
// if bit 31 is set data are contained wihin the key itself to save space
if(val->size&1<<31) {
data = (char*)&val->offset;
}
// notice that we use memcopy for key/value names everywhere instead of strcat
// reason is that malware/wiruses often write non nulterminated strings to
// hide from win32 api
*path='/'; if(!val->name_len) *path=' ';
memcpy(path+1,&val->name,val->name_len); path[val->name_len+1]=0;
printf("%s [%d] = ",full,val->value_type);
for(int i=0;i<(val->size&0xffff);i++) {
// print types 1 and 7 as unicode strings
if(val->value_type==1||val->value_type==7) {
if(data[i]) putchar(data[i]);
// and rest dump as binary data
} else {
printf("%02X",data[i]);
}
}
}
// for simplicity we can imagine keys as directories in filesystem and values
// as files.
// and since we already dumped values for this dir we will now iterate
// thru subdirectories in the same way
offsets* item = (offsets*)(root+key->subkeys);
for(int i=0;i<item->count;i++){
// in case of too many subkeys this list contain just other lists
offsets* subitem = (offsets*)((&item->first)[i]+root);
// usual directory traversal
if(item->block_type[1]=='f'||item->block_type[1]=='h') {
// for now we skip hash codes (used by regedit for faster search)
walk(path,(key_block*)((&item->first)[i*2]+root));
} else for(int j=0;j<subitem->count;j++) {
// also ms had chosen to skip hashes altogether in this case
walk(path,(key_block*)((&subitem->first)[item->block_type[1]=='i'?j*2:j]+root));
}
}
}
int main(int argc, char** argv) {
char path[0x1000]={0}, *data; FILE* f; int size;
if(argc<2||!(f=fopen(argv[1],"rb"))) return printf("hive path err");
fseek(f,0,SEEK_END);
if(!(size=ftell(f))) return printf("empty file");
rewind(f); data=(char*)malloc(size);
fread(data,size,1,f);
fclose(f);
// we just skip 1k header and start walking root key tree
walk(path,(key_block*)(data+0x1020));
free(data);
return 0;
}
I thank you in advance for any help you can offer.