📄 regf.c
字号:
*data_type = vk->data_type; if (vk->data_length & 0x80000000) { vk->data_length &=~0x80000000; data->data = (uint8_t *)&vk->data_offset; data->length = vk->data_length; } else { *data = hbin_get(regf, vk->data_offset); } if (data->length < vk->data_length) { DEBUG(1, ("Read data less than indicated data length!\n")); } talloc_free(vk); return WERR_OK;}static WERROR regf_get_value_by_name(TALLOC_CTX *mem_ctx, struct hive_key *key, const char *name, uint32_t *type, DATA_BLOB *data){ int i; const char *vname; WERROR error; /* FIXME: Do binary search? Is this list sorted at all? */ for (i = 0; W_ERROR_IS_OK(error = regf_get_value(mem_ctx, key, i, &vname, type, data)); i++) { if (!strcmp(vname, name)) return WERR_OK; } if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) return WERR_BADFILE; return error;}static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx, const struct hive_key *key, uint32_t idx, const char **name, const char **classname, NTTIME *last_mod_time){ DATA_BLOB data; struct regf_key_data *ret; const struct regf_key_data *private_data = (const struct regf_key_data *)key; struct nk_block *nk = private_data->nk; uint32_t key_off=0; if (idx >= nk->num_subkeys) return WERR_NO_MORE_ITEMS; data = hbin_get(private_data->hive, nk->subkeys_offset); if (!data.data) { DEBUG(0, ("Unable to find subkey list\n")); return WERR_GENERAL_FAILURE; } if (!strncmp((char *)data.data, "li", 2)) { struct li_block li; struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience); DEBUG(10, ("Subkeys in LI list\n")); pull->data = data; if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) { DEBUG(0, ("Error parsing LI list\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } talloc_free(pull); SMB_ASSERT(!strncmp(li.header, "li", 2)); if (li.key_count != nk->num_subkeys) { DEBUG(0, ("Subkey counts don't match\n")); return WERR_GENERAL_FAILURE; } key_off = li.nk_offset[idx]; } else if (!strncmp((char *)data.data, "lf", 2)) { struct lf_block lf; struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience); DEBUG(10, ("Subkeys in LF list\n")); pull->data = data; if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) { DEBUG(0, ("Error parsing LF list\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } talloc_free(pull); SMB_ASSERT(!strncmp(lf.header, "lf", 2)); if (lf.key_count != nk->num_subkeys) { DEBUG(0, ("Subkey counts don't match\n")); return WERR_GENERAL_FAILURE; } key_off = lf.hr[idx].nk_offset; } else if (!strncmp((char *)data.data, "lh", 2)) { struct lh_block lh; struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience); DEBUG(10, ("Subkeys in LH list\n")); pull->data = data; if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) { DEBUG(0, ("Error parsing LH list\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } talloc_free(pull); SMB_ASSERT(!strncmp(lh.header, "lh", 2)); if (lh.key_count != nk->num_subkeys) { DEBUG(0, ("Subkey counts don't match\n")); return WERR_GENERAL_FAILURE; } key_off = lh.hr[idx].nk_offset; } else if (!strncmp((char *)data.data, "ri", 2)) { struct ri_block ri; struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); uint16_t i; uint16_t sublist_count = 0; DEBUG(10, ("Subkeys in RI list\n")); pull->data = data; if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) { DEBUG(0, ("Error parsing RI list\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(ri.header, "ri", 2)); for (i = 0; i < ri.key_count; i++) { DATA_BLOB list_data; /* Get sublist data blob */ list_data = hbin_get(private_data->hive, ri.offset[i]); if (!list_data.data) { DEBUG(0, ("Error getting RI list.")); talloc_free(pull); return WERR_GENERAL_FAILURE; } pull->data = list_data; if (!strncmp((char *)list_data.data, "li", 2)) { struct li_block li; DEBUG(10, ("Subkeys in RI->LI list\n")); if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) { DEBUG(0, ("Error parsing LI list from RI\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(li.header, "li", 2)); /* Advance to next sublist if necessary */ if (idx >= sublist_count + li.key_count) { sublist_count += li.key_count; continue; } key_off = li.nk_offset[idx - sublist_count]; sublist_count += li.key_count; break; } else if (!strncmp((char *)list_data.data, "lh", 2)) { struct lh_block lh; DEBUG(10, ("Subkeys in RI->LH list\n")); if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) { DEBUG(0, ("Error parsing LH list from RI\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(lh.header, "lh", 2)); /* Advance to next sublist if necessary */ if (idx >= sublist_count + lh.key_count) { sublist_count += lh.key_count; continue; } key_off = lh.hr[idx - sublist_count].nk_offset; sublist_count += lh.key_count; break; } else { DEBUG(0,("Unknown sublist in ri block\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } } talloc_free(pull); if (idx > sublist_count) { return WERR_NO_MORE_ITEMS; } } else { DEBUG(0, ("Unknown type for subkey list (0x%04x): %c%c\n", nk->subkeys_offset, data.data[0], data.data[1])); return WERR_GENERAL_FAILURE; } ret = regf_get_key (ctx, private_data->hive, key_off); if (classname != NULL) { if (ret->nk->clsname_offset != -1) { DATA_BLOB db = hbin_get(ret->hive, ret->nk->clsname_offset); *classname = talloc_strndup(ctx, (char*)db.data, ret->nk->clsname_length); } else *classname = NULL; } if (last_mod_time != NULL) *last_mod_time = ret->nk->last_change; if (name != NULL) *name = talloc_steal(ctx, ret->nk->key_name); talloc_free(ret); return WERR_OK;}static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx, const struct hive_key *key, uint32_t offset, const char *name, uint32_t *ret){ DATA_BLOB subkey_data; struct nk_block subkey; struct tdr_pull *pull; const struct regf_key_data *private_data = (const struct regf_key_data *)key; subkey_data = hbin_get(private_data->hive, offset); if (!subkey_data.data) { DEBUG(0, ("Unable to retrieve subkey HBIN\n")); return WERR_GENERAL_FAILURE; } pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); pull->data = subkey_data; if (NT_STATUS_IS_ERR(tdr_pull_nk_block(pull, ctx, &subkey))) { DEBUG(0, ("Error parsing NK structure.\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } talloc_free(pull); if (strncmp(subkey.header, "nk", 2)) { DEBUG(0, ("Not an NK structure.\n")); return WERR_GENERAL_FAILURE; } if (!strcasecmp(subkey.key_name, name)) { *ret = offset; } else { *ret = 0; } return WERR_OK;}static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx, const struct hive_key *key, const char *name, struct hive_key **ret){ DATA_BLOB data; const struct regf_key_data *private_data = (const struct regf_key_data *)key; struct nk_block *nk = private_data->nk; uint32_t key_off = 0; data = hbin_get(private_data->hive, nk->subkeys_offset); if (!data.data) { DEBUG(0, ("Unable to find subkey list\n")); return WERR_GENERAL_FAILURE; } if (!strncmp((char *)data.data, "li", 2)) { struct li_block li; struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); uint16_t i; DEBUG(10, ("Subkeys in LI list\n")); pull->data = data; if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) { DEBUG(0, ("Error parsing LI list\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } talloc_free(pull); SMB_ASSERT(!strncmp(li.header, "li", 2)); if (li.key_count != nk->num_subkeys) { DEBUG(0, ("Subkey counts don't match\n")); return WERR_GENERAL_FAILURE; } for (i = 0; i < li.key_count; i++) { W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, li.nk_offset[i], name, &key_off)); if (key_off != 0) break; } if (key_off == 0) return WERR_BADFILE; } else if (!strncmp((char *)data.data, "lf", 2)) { struct lf_block lf; struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); uint16_t i; DEBUG(10, ("Subkeys in LF list\n")); pull->data = data; if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) { DEBUG(0, ("Error parsing LF list\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } talloc_free(pull); SMB_ASSERT(!strncmp(lf.header, "lf", 2)); if (lf.key_count != nk->num_subkeys) { DEBUG(0, ("Subkey counts don't match\n")); return WERR_GENERAL_FAILURE; } for (i = 0; i < lf.key_count; i++) { if (strncmp(lf.hr[i].hash, name, 4)) { continue; } W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, lf.hr[i].nk_offset, name, &key_off)); if (key_off != 0) break; } if (key_off == 0) return WERR_BADFILE; } else if (!strncmp((char *)data.data, "lh", 2)) { struct lh_block lh; struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); uint16_t i; uint32_t hash; DEBUG(10, ("Subkeys in LH list\n")); pull->data = data; if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) { DEBUG(0, ("Error parsing LH list\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } talloc_free(pull); SMB_ASSERT(!strncmp(lh.header, "lh", 2)); if (lh.key_count != nk->num_subkeys) { DEBUG(0, ("Subkey counts don't match\n")); return WERR_GENERAL_FAILURE; } hash = regf_create_lh_hash(name); for (i = 0; i < lh.key_count; i++) { if (lh.hr[i].base37 != hash) { continue; } W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, lh.hr[i].nk_offset, name, &key_off)); if (key_off != 0) break; } if (key_off == 0) return WERR_BADFILE; } else if (!strncmp((char *)data.data, "ri", 2)) { struct ri_block ri; struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience); uint16_t i, j; DEBUG(10, ("Subkeys in RI list\n")); pull->data = data; if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) { DEBUG(0, ("Error parsing RI list\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(ri.header, "ri", 2)); for (i = 0; i < ri.key_count; i++) { DATA_BLOB list_data; /* Get sublist data blob */ list_data = hbin_get(private_data->hive, ri.offset[i]); if (list_data.data == NULL) { DEBUG(0, ("Error getting RI list.")); talloc_free(pull); return WERR_GENERAL_FAILURE; } pull->data = list_data; if (!strncmp((char *)list_data.data, "li", 2)) { struct li_block li; if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) { DEBUG(0, ("Error parsing LI list from RI\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(li.header, "li", 2)); for (j = 0; j < li.key_count; j++) { W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, li.nk_offset[j], name, &key_off)); if (key_off) break; } } else if (!strncmp((char *)list_data.data, "lh", 2)) { struct lh_block lh; uint32_t hash; if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) { DEBUG(0, ("Error parsing LH list from RI\n")); talloc_free(pull); return WERR_GENERAL_FAILURE; } SMB_ASSERT(!strncmp(lh.header, "lh", 2)); hash = regf_create_lh_hash(name); for (j = 0; j < lh.key_count; j++) { if (lh.hr[j].base37 != hash) { continue; } W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key, lh.hr[j].nk_offset, name, &key_off)); if (key_off) break; } } if (key_off) break; } talloc_free(pull); if (!key_off) return WERR_BADFILE; } else { DEBUG(0, ("Unknown subkey list type.\n")); return WERR_GENERAL_FAILURE; } *ret = (struct hive_key *)regf_get_key(ctx, private_data->hive, key_off); return WERR_OK;}static WERROR regf_set_sec_desc(struct hive_key *key, const struct security_descriptor *sec_desc){ const struct regf_key_data *private_data = (const struct regf_key_data *)key; struct sk_block cur_sk, sk, new_sk; struct regf_data *regf = private_data->hive; struct nk_block root; DATA_BLOB data; uint32_t sk_offset, cur_sk_offset; bool update_cur_sk = false; /* Get the root nk */ hbin_get_tdr(regf, regf->header->data_offset, regf, (tdr_pull_fn_t) tdr_pull_nk_block, &root); /* Push the security descriptor to a blob */ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, NULL, sec_desc, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) { DEBUG(0, ("Unable to push security descriptor\n")); return WERR_GENERAL_FAILURE; } /* Get the current security descriptor for the key */ if (!hbin_get_tdr(regf, private_data->nk->sk_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &cur_sk)) { DEBUG(0, ("Unable to find security descriptor for current key\n")); return WERR_BADFILE; } /* If there's no change, change nothing. */ if (memcmp(data.data, cur_sk.sec_desc, MIN(data.length, cur_sk.rec_size)) == 0) { return WERR_OK; } /* Delete the current sk if only this key is using it */ if (cur_sk.ref_cnt == 1) { /* Get the previous security descriptor for the key */ if (!hbin_get_tdr(regf, cur_sk.prev_offset, regf, (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) { DEBUG(0, ("Unable to find prev security descriptor for current key\n")); return WERR_BADFILE; } /* Change and store the previous security descriptor */ sk.next_offset = cur_sk.next_offset; hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block, cur_sk.prev_offset, &sk);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -