I think it's close, but not entirely what I had in mind. You can avoid both the callback and some of the data copies if you just let parse_dxbc() create a list / array of sections. So you'd have something like this:
struct dxbc_section { DWORD tag; const char *data; SIZE_T data_size; };
struct dxbc { UINT section_size; UINT section_count; struct dxbc_section *sections; };
with parse_dxbc() just calling something like dxbc_add_section() instead of chunk_handler(). The sections can just refer to the original data in the dxbc blob, it's then the responsibility of the caller to either make sure that data stays around for as long as the sections are needed or make a copy of the data.
d3dcompiler_get_blob_part() would then just iterate over all the sections and add the relevant ones to a second dxbc struct, which it would pass to dxbc_write_blob() afterwards. I don't think dxbc_remove_section() is very useful in general, you'll pretty much always just want to add sections to a new section list. It's also simply unused in your current patch. dxbc_release() should be called dxbc_destroy(), you're not doing any reference counting, and the naming would be more consistent if you renamed parse_dxbc() to dxbc_parse().