📄 ntreg.c
字号:
return(size);}/* ================================================================ *//* ** Registry manipulation routines ** *//* "directory scan", return next name/pointer of a subkey on each call * nkofs = offset to directory to scan * lfofs = pointer to int to hold the current scan position, * set position to 0 to start. * sptr = pointer to struct to hold a single result * returns: -1 = error. 0 = end of key. 1 = more subkeys to scan * NOTE: caller must free the name-buffer (struct ex_data *name) */int ex_next_n(struct hive *hdesc, int nkofs, int *count, int *countri, struct ex_data *sptr){ struct nk_key *key, *newnkkey; int newnkofs; struct lf_key *lfkey; struct li_key *likey; struct ri_key *rikey; if (!nkofs) return(-1); key = (struct nk_key *)(hdesc->buffer + nkofs); if (key->id != 0x6b6e) { printf("ex_next error: Not a 'nk' node at 0x%0x\n",nkofs); return(-1); }#define EXNDEBUG 0 lfkey = (struct lf_key *)(hdesc->buffer + key->ofs_lf + 0x1004); rikey = (struct ri_key *)(hdesc->buffer + key->ofs_lf + 0x1004); if (rikey->id == 0x6972) { /* Is it extended 'ri'-block? */#if EXNDEBUG printf("%d , %d\n",*countri,*count);#endif if (*countri < 0 || *countri >= rikey->no_lis) { /* End of ri's? */ return(0); } /* Get the li of lf-struct that's current based on countri */ likey = (struct li_key *)( hdesc->buffer + rikey->hash[*countri].ofs_li + 0x1004 ) ; if (likey->id == 0x696c) { newnkofs = likey->hash[*count].ofs_nk + 0x1000; } else { lfkey = (struct lf_key *)( hdesc->buffer + rikey->hash[*countri].ofs_li + 0x1004 ) ; newnkofs = lfkey->hash[*count].ofs_nk + 0x1000; } /* Check if current li/lf is exhausted */#if EXNDEBUG printf("likey->no_keys = %d\n",likey->no_keys);#endif if (*count >= likey->no_keys-1) { /* Last legal entry in li list? */ (*countri)++; /* Bump up ri count so we take next ri entry next time */ (*count) = -1; /* Reset li traverse counter for next round, not used later here */ } } else { /* Plain handler */ if (key->no_subkeys <= 0 || *count >= key->no_subkeys) { return(0); } if (lfkey->id == 0x696c) { /* Is it 3.x 'li' instead? */ likey = (struct li_key *)(hdesc->buffer + key->ofs_lf + 0x1004); newnkofs = likey->hash[*count].ofs_nk + 0x1000; } else { newnkofs = lfkey->hash[*count].ofs_nk + 0x1000; } } sptr->nkoffs = newnkofs; newnkkey = (struct nk_key *)(hdesc->buffer + newnkofs + 4); sptr->nk = newnkkey; if (newnkkey->id != 0x6b6e) { printf("ex_next: ERROR: not 'nk' node at 0x%0x\n",newnkofs); return(-1); } else { if (newnkkey->len_name <= 0) { printf("ex_next: nk at 0x%0x has no name!\n",newnkofs); } else { sptr->name = (char *)malloc(newnkkey->len_name+1); if (!sptr->name) { printf("FATAL! ex_next: malloc() failed! Out of memory?\n"); abort(); } strncpy(sptr->name,newnkkey->keyname,newnkkey->len_name); sptr->name[newnkkey->len_name] = 0; } } /* if */ (*count)++; return(1); /* return( *count <= key->no_subkeys); */}/* "directory scan" for VALUES, return next name/pointer of a value on each call * nkofs = offset to directory to scan * lfofs = pointer to int to hold the current scan position, * set position to 0 to start. * sptr = pointer to struct to hold a single result * returns: -1 = error. 0 = end of key. 1 = more values to scan * NOTE: caller must free the name-buffer (struct vex_data *name) */int ex_next_v(struct hive *hdesc, int nkofs, int *count, struct vex_data *sptr){ struct nk_key *key /* , *newnkkey */ ; int vkofs,vlistofs; int *vlistkey; struct vk_key *vkkey; if (!nkofs) return(-1); key = (struct nk_key *)(hdesc->buffer + nkofs); if (key->id != 0x6b6e) { printf("ex_next_v error: Not a 'nk' node at 0x%0x\n",nkofs); return(-1); } if (key->no_values <= 0 || *count >= key->no_values) { return(0); } vlistofs = key->ofs_vallist + 0x1004; vlistkey = (int *)(hdesc->buffer + vlistofs); vkofs = vlistkey[*count] + 0x1004; vkkey = (struct vk_key *)(hdesc->buffer + vkofs); if (vkkey->id != 0x6b76) { printf("ex_next_v: hit non valuekey (vk) node during scan at offs 0x%0x\n",vkofs); return(-1); } /* parse_vk(hdesc, vkofs, 4); */ sptr->vk = vkkey; sptr->vkoffs = vkofs; sptr->name = 0; sptr->size = (vkkey->len_data & 0x7fffffff); if (vkkey->len_name >0) { CREATE(sptr->name,char,vkkey->len_name+1); memcpy(sptr->name,vkkey->keyname,vkkey->len_name); sptr->name[vkkey->len_name] = 0; } else { sptr->name = str_dup("@"); } sptr->type = vkkey->val_type; if (sptr->size) { if (vkkey->val_type == REG_DWORD) { if (vkkey->len_data & 0x80000000) { sptr->val = (int)(vkkey->ofs_data); } } } else if (vkkey->len_data == 0x80000000) { /* Data SIZE is 0, high bit set: special inline case, data is DWORD and in TYPE field!! */ /* Used a lot in SAM, and maybe in SECURITY I think */ sptr->val = (int)(vkkey->val_type); sptr->size = 4; sptr->type = REG_DWORD; } else { sptr->val = 0; sptr->size = 0; } (*count)++; return( *count <= key->no_values );}/* traceback - trace nk's back to root, * building path string as we go. * nkofs = offset to nk-node * path = pointer to pathstring-buffer * maxlen = max length of path-buffer * return: length of path string */int get_abs_path(struct hive *hdesc, int nkofs, char *path, int maxlen){ /* int newnkofs; */ struct nk_key *key; char tmp[ABSPATHLEN+1]; maxlen = (maxlen < ABSPATHLEN ? maxlen : ABSPATHLEN); key = (struct nk_key *)(hdesc->buffer + nkofs); if (key->id != 0x6b6e) { printf("get_abs_path: Not a 'nk' node!\n"); return(0); } if (key->type == KEY_ROOT) { /* We're at the root */ return(strlen(path)); } strncpy(tmp,path,ABSPATHLEN-1); if ( (strlen(path) + key->len_name) >= maxlen-6) { snprintf(path,maxlen,"(...)%s",tmp); return(strlen(path)); /* Stop trace when string exhausted */ } *path = '\\'; memcpy(path+1,key->keyname,key->len_name); strncpy(path+key->len_name+1,tmp,maxlen); return(get_abs_path(hdesc, key->ofs_parent+0x1004, path, maxlen)); /* go back one more */}/* Value index table lookup * hdesc - hive as usual * vlistofs - offset of table * name - value name to look for * returns index into table or -1 if err */int vlist_find(struct hive *hdesc, int vlistofs, int numval, char *name){ struct vk_key *vkkey; int i,vkofs; long *vlistkey; vlistkey = (long *)(hdesc->buffer + vlistofs); for (i = 0; i < numval; i++) { vkofs = vlistkey[i] + 0x1004; vkkey = (struct vk_key *)(hdesc->buffer + vkofs); if (vkkey->len_name == 0 && *name == '@') { /* @ is alias for nameless value */ return(i); } if (!strncmp(name, vkkey->keyname, strlen(name))) { /* name match? */ return(i); } } return(-1);}/* Recursevely follow 'nk'-nodes based on a path-string, * returning offset of last 'nk' or 'vk' * vofs - offset to start node * path - null-terminated pathname (relative to vofs, \ is separator) * type - type to return 0=nk 1=vk * return: offset to nk or vk (or NULL if not found) */int trav_path(struct hive *hdesc, int vofs, char *path, int type){ struct nk_key *key, *newnkkey; struct lf_key *lfkey; struct li_key *likey; struct ri_key *rikey; long *vlistkey; int newnkofs, plen, i, lfofs, vlistofs, adjust, r, ricnt, subs; char *buf; char part[ABSPATHLEN+1]; char *partptr; if (!hdesc) return(0); buf = hdesc->buffer; if (*path == '\\' && *(path+1) != '\\') { /* Start from root if path starts with \ */ path++; vofs = hdesc->rootofs+4; } key = (struct nk_key *)(buf + vofs); /* printf("check of nk at offset: 0x%0x\n",vofs); */ if (key->id != 0x6b6e) { printf("trav_path: Error: Not a 'nk' node!\n"); return(0); } /* Find \ delimiter or end of string, copying to name part buffer as we go, rewriting double \\s */ partptr = part; for(plen = 0; path[plen] && (path[plen] != '\\' || path[plen+1] == '\\'); plen++) { if (path[plen] == '\\' && path[plen+1] == '\\') plen++; /* Skip one if double */ *partptr++ = path[plen]; } *partptr = '\0'; /* printf("Name component: <%s>\n",part); */ adjust = (path[plen] == '\\' ) ? 1 : 0; /* printf("Checking for <%s> with len %d\n",path,plen); */ if (!plen) return(vofs-4); /* Path has no lenght - we're there! */ if ( (plen == 1) && (*path == '.')) { /* Handle '.' current dir */ return(trav_path(hdesc,vofs,path+plen+adjust,type)); } if ( (plen == 2) && !strncmp("..",path,2) ) { /* Get parent key */ newnkofs = key->ofs_parent + 0x1004; /* Return parent (or only root if at the root) */ return(trav_path(hdesc, (key->type == KEY_ROOT ? vofs : newnkofs), path+plen+adjust, type)); } /* at last name of path, and we want vk, and the nk has values */ if (!path[plen] && type == 1 && key->no_values) { /* printf("VK namematch for <%s>\n",part); */ vlistofs = key->ofs_vallist + 0x1004; vlistkey = (long *)(buf + vlistofs); i = vlist_find(hdesc, vlistofs, key->no_values, part); if (i != -1) { return(vlistkey[i] + 0x1000); } } if (key->no_subkeys > 0) { /* If it has subkeys, loop through the hash */ lfofs = key->ofs_lf + 0x1004; /* lf (hash) record */ lfkey = (struct lf_key *)(buf + lfofs); if (lfkey->id == 0x6972) { /* ri struct need special parsing */ /* Prime loop state */ rikey = (struct ri_key *)lfkey; ricnt = rikey->no_lis; r = 0; likey = (struct li_key *)( hdesc->buffer + rikey->hash[r].ofs_li + 0x1004 ) ; subs = likey->no_keys; if (likey->id != 0x696c) { /* Bwah, not li anyway, XP uses lh usually which is actually smarter */ lfkey = (struct lf_key *)( hdesc->buffer + rikey->hash[r].ofs_li + 0x1004 ) ; likey = NULL; } } else { if (lfkey->id == 0x696c) { /* li? */ likey = (struct li_key *)(buf + lfofs); } else { likey = NULL; } ricnt = 0; r = 0; subs = key->no_subkeys; } do { for(i = 0; i < subs; i++) { if (likey) newnkofs = likey->hash[i].ofs_nk + 0x1004; else newnkofs = lfkey->hash[i].ofs_nk + 0x1004; newnkkey = (struct nk_key *)(buf + newnkofs); if (newnkkey->id != 0x6b6e) { printf("ERROR: not 'nk' node! (strange?)\n"); } else { if (newnkkey->len_name <= 0) { printf("[No name]\n"); } else { if (!strncmp(part,newnkkey->keyname,plen)) { /* printf("Key at 0x%0x matches! recursing!\n",newnkofs); */ return(trav_path(hdesc, newnkofs, path+plen+adjust, type)); } } } /* if id OK */ } /* hash loop */ r++; if (ricnt && r < ricnt) { newnkofs = rikey->hash[r].ofs_li; likey = (struct li_key *)( hdesc->buffer + newnkofs + 0x1004 ) ; subs = likey->no_keys; if (likey->id != 0x696c) { /* Bwah, not li anyway, XP uses lh usually which is actually smarter */ lfkey = (struct lf_key *)( hdesc->buffer + rikey->hash[r].ofs_li + 0x1004 ) ; likey = NULL; } } } while (r < ricnt && ricnt); } /* if subkeys */ /* Not found */ return(0);}/* ls - list a 'nk' nodes subkeys and values * vofs - offset to start of data (skipping block linkage) * type - 0 = full, 1 = keys only. 2 = values only */void nk_ls(struct hive *hdesc, char *path, int vofs, int type){ struct nk_key *key; int nkofs; struct ex_data ex; struct vex_data vex; int count = 0, countri = 0; nkofs = trav_path(hdesc, vofs, path, 0); if(!nkofs) { printf("nk_ls: Key <%s> not found\n",path); return; } nkofs += 4; key = (struct nk_key *)(hdesc->buffer + nkofs); printf("ls of node at offset 0x%0x\n",nkofs); if (key->id != 0x6b6e) { printf("Error: Not a 'nk' node!\n"); debugit(hdesc->buffer,hdesc->size); } printf("Node has %ld subkeys and %ld values",key->no_subkeys,key->no_values); if (key->len_classnam) printf(", and class-data of %d bytes",key->len_classnam); printf("\n"); if (key->no_subkeys) { printf("offs key name\n"); while ((ex_next_n(hdesc, nkofs, &count, &countri, &ex) > 0)) { printf("[%6x] %c <%s>\n", ex.nkoffs, (ex.nk->len_classnam)?'*':' ',ex.name); FREE(ex.name); } } count = 0; if (key->no_values) { printf("offs size type value name [value if type DWORD]\n"); while ((ex_next_v(hdesc, nkofs, &count, &vex) > 0)) { printf("[%6x] %6d %-16s <%s>", vex.vkoffs, vex.size, (vex.type < REG_MAX ? val_types[vex.type] : "(unknown)"), vex.name); if (vex.type == REG_DWORD) printf(" %*d [0x%x]",25-strlen(vex.name),vex.val , vex.val); printf("\n"); FREE(vex.name); } }}/* Get the type of a value */int get_val_type(struct hive *hdesc, int vofs, char *path){ struct vk_key *vkkey; int vkofs; vkofs = trav_path(hdesc, vofs,path,1); if (!vkofs) { return -1; } vkofs +=4; vkkey = (struct vk_key *)(hdesc->buffer + vkofs);#if 0 if (vkkey->len_data & 0x80000000) return(REG_DWORD); /* Special case of INLINE storage */#endif return(vkkey->val_type);}/* Get len of a value, given current key + path */int get_val_len(struct hive *hdesc, int vofs, char *path){ struct vk_key *vkkey; int vkofs; int len; vkofs = trav_path(hdesc, vofs,path,1); if (!vkofs) { return -1; } vkofs +=4; vkkey = (struct vk_key *)(hdesc->buffer + vkofs); len = vkkey->len_data & 0x7fffffff; if ( vkkey->len_data == 0x80000000 ) { /* Special inline case, return size of 4 (dword) */ len = 4; } return(len);}/* Get void-pointer to value-data, also if inline. * If val_type != 0 a check for correct value type is done * Caller must keep track of value's length (call function above to get it) */void *get_val_data(struct hive *hdesc, int vofs, char *path, int val_type){ struct vk_key *vkkey; int vkofs; vkofs = trav_path(hdesc,vofs,path,1); if (!vkofs) { return NULL; } vkofs +=4; vkkey = (struct vk_key *)(hdesc->buffer + vkofs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -