func (m *MetadataUtil) ReadIndex(br *util.BinaryReader, size uint) (uint32, error) {
	if size == 2 {
		if v, e := br.Uint16(); e != nil {
			return 0, e
		} else {
			return uint32(v), nil
		}
	}
	return br.Uint32()
}
Example #2
0
func LoadAssembly(r io.ReadSeeker) (*Assembly, error) {

	var (
		br        = util.BinaryReader{r, binary.LittleEndian}
		err       error
		pe_offset uint32
		coff      coff_file_header
		cor20     image_cor20
		t         MetadataHeader
	)

	if _, err := r.Seek(pe_signature_offset, 0); err != nil {
		return nil, err
	}

	if pe_offset, err = br.Uint32(); err != nil {
		return nil, err
	} else if _, err := r.Seek(int64(pe_offset), 0); err != nil {
		return nil, err
	}

	if err := br.ReadInterface(&coff); err != nil {
		return nil, err
	}
	net := coff.OptionalHeader.RVAS[14]
	off := coff.VirtualToFileOffset(net.VirtualAddress)
	if _, err := br.Seek(int64(off), 0); err != nil {
		return nil, err
	}

	if err := br.ReadInterface(&cor20); err != nil {
		return nil, err
	}
	off = coff.VirtualToFileOffset(cor20.MetaData.VirtualAddress)
	if _, err := br.Seek(int64(off), 0); err != nil {
		return nil, err
	}
	if err := br.ReadInterface(&t); err != nil {
		return nil, err
	}
	if _, err := br.Seek(int64(off), 0); err != nil {
		return nil, err
	}
	if md, err := t.MetadataUtil(&br); err != nil {
		return nil, err
	} else {
		return &Assembly{*md}, nil
	}
}
func (mh *MetadataHeader) MetadataUtil(br *util.BinaryReader) (*MetadataUtil, error) {
	var (
		ret MetadataUtil
	)

	off, err := br.Seek(0, 1)
	if err != nil {
		return nil, err
	}
	base := off
	for _, h := range mh.StreamHeaders {
		switch h.Name {
		case "#~":
			off += int64(h.Offset)
		case "#Strings":
			if _, err := br.Seek(base+int64(h.Offset), 0); err != nil {
				return nil, err
			} else if ret.StringHeap.data, err = br.Read(int(h.Size)); err != nil {
				return nil, err
			}
			ret.StringHeap.Rows = h.Size
		case "#Blob":
			if _, err := br.Seek(base+int64(h.Offset), 0); err != nil {
				return nil, err
			} else if ret.BlobHeap.data, err = br.Read(int(h.Size)); err != nil {
				return nil, err
			}
			ret.BlobHeap.Rows = h.Size
		case "#GUID":
			if _, err := br.Seek(base+int64(h.Offset), 0); err != nil {
				return nil, err
			} else if ret.GuidHeap.data, err = br.Read(int(h.Size)); err != nil {
				return nil, err
			}
			ret.GuidHeap.Rows = h.Size
		}
	}
	if _, err := br.Seek(off, 0); err != nil {
		return nil, err
	}
	h := hash_tilde_stream_header{}
	if err := br.ReadInterface(&h); err != nil {
		return nil, err
	}

	if h.HeapSizes&bit_stringHeapIndexSize != 0 {
		ret.StringHeap.RowSize = 4
	} else {
		ret.StringHeap.RowSize = 2
	}
	if h.HeapSizes&bit_blobHeapIndexSize != 0 {
		ret.BlobHeap.RowSize = 4
	} else {
		ret.BlobHeap.RowSize = 2
	}
	if h.HeapSizes&bit_guidHeapIndexSize != 0 {
		ret.GuidHeap.RowSize = 4
	} else {
		ret.GuidHeap.RowSize = 2
	}

	for i := range ret.Tables {
		if valid := (h.Valid >> uint(i)) & 1; valid != 0 {
			if ret.Tables[i].Rows, err = br.Uint32(); err != nil {
				return nil, err
			}
			ret.Tables[i].RowType = table_row_type_lut[i]
		}
	}

	for i := range ret.Tables {
		if ret.Tables[i].Rows != 0 {
			if size, err := ret.Size(ret.Tables[i].RowType); err != nil {
				return nil, err
			} else {
				ret.Tables[i].RowSize = uint32(size)
				if ret.Tables[i].data, err = br.Read(int(ret.Tables[i].RowSize * ret.Tables[i].Rows)); err != nil {
					return nil, err
				}
			}
		}
	}
	return &ret, nil
}