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 }