func (mt *MetadataTable) Index(index uint32) ([]byte, error) { if mt.Rows == 0 { return nil, errors.New("Trying to dereference a nil table") } index-- if index >= mt.Rows { return nil, errors.New(fmt.Sprintf("Index outside of bounds: %x >= %x", index, mt.Rows)) } return mt.data[index*mt.RowSize:], nil }
func (o *optional_header) Validate() error { if o.Magic != pe32 && o.Magic != pe32p { return errors.New(fmt.Sprintf("Unkown optional header magic: %x", o.Magic)) } if len(o.RVAS) != 16 || o.RVAS[14].VirtualAddress == 0 || o.RVAS[14].Size == 0 { return ErrNotAssembly } return nil }
func (r *BinaryReader) Read(size int) ([]byte, error) { data := make([]byte, size) if size == 0 { return data, nil } if n, err := r.Reader.Read(data); err != nil { return nil, err } else if n != len(data) { return nil, errors.New("Didn't read the expected number of bytes") } return data, nil }
func (r *BinaryReader) ReadInterface(v interface{}) error { if ri, ok := v.(Reader); ok { return ri.Read(r) } t := reflect.ValueOf(v) if t.Kind() != reflect.Ptr { return errors.New(fmt.Sprintf("Expected a pointer not %s", t.Kind())) } v2 := t.Elem() switch v2.Kind() { case reflect.Uint64: if d, err := r.Uint64(); err != nil { return err } else { v2.SetUint(uint64(d)) } case reflect.Uint32: if d, err := r.Uint32(); err != nil { return err } else { v2.SetUint(uint64(d)) } case reflect.Uint16: if d, err := r.Uint16(); err != nil { return err } else { v2.SetUint(uint64(d)) } case reflect.Uint8: if d, err := r.Uint8(); err != nil { return err } else { v2.SetUint(uint64(d)) } case reflect.Int64: if d, err := r.Int64(); err != nil { return err } else { v2.SetInt(int64(d)) } case reflect.Int32: if d, err := r.Int32(); err != nil { return err } else { v2.SetInt(int64(d)) } case reflect.Int16: if d, err := r.Int16(); err != nil { return err } else { v2.SetInt(int64(d)) } case reflect.Int8: if d, err := r.Int8(); err != nil { return err } else { v2.SetInt(int64(d)) } case reflect.Float32: if f, err := r.Float32(); err != nil { return err } else { v2.SetFloat(float64(f)) } case reflect.Float64: if f, err := r.Float64(); err != nil { return err } else { v2.SetFloat(f) } case reflect.Struct: for i := 0; i < v2.NumField(); i++ { var ( f = v2.Field(i) f2 = v2.Type().Field(i) size = -1 err error ) if fi := f2.Tag.Get("if"); fi != "" { var e expression.EXPRESSION if !e.Parse(fi) { return e.Error() } else if ev, err := expression.Eval(&v2, e.RootNode()); err != nil { return err } else if ev == 0 { continue } } if l := f2.Tag.Get("length"); l != "" { switch l { case "uint8": if s, err := r.Uint8(); err != nil { return err } else { size = int(s) } case "uint16": if s, err := r.Uint16(); err != nil { return err } else { size = int(s) } case "uint32": if s, err := r.Uint32(); err != nil { return err } else { size = int(s) } case "uin64": if s, err := r.Uint64(); err != nil { return err } else { size = int(s) } default: var e expression.EXPRESSION if !e.Parse(l) { return e.Error() } else if ev, err := expression.Eval(&v2, e.RootNode()); err != nil { return err } else { size = ev } } } switch f.Type().Kind() { case reflect.String: var data []byte if size >= 0 { if data, err = r.Read(size); err != nil { return err } for i, v := range data { if v == '\u0000' { data = data[:i] break } } } else { var max = math.MaxInt32 if m := f2.Tag.Get("max"); m != "" { var e expression.EXPRESSION if !e.Parse(m) { return e.Error() } else if ev, err := expression.Eval(&v2, e.RootNode()); err != nil { return err } else { max = ev } } for i := 0; i < max; i++ { if u, err := r.Uint8(); err != nil { return err } else if u == '\u0000' { size = i + 1 break } else { data = append(data, u) } } } f.SetString(string(data)) case reflect.Slice: if size == -1 { return fmt.Errorf("SliceHeader require a known length, %+v", v) } if f.Type().Elem().Kind() == reflect.Int8 { if b, err := r.Read(size); err != nil { return err } else { f.Set(reflect.ValueOf(b)) } } else { var v3 = reflect.MakeSlice(f.Type(), size, size) for i := 0; i < size; i++ { if err = r.ReadInterface(v3.Index(i).Addr().Interface()); err != nil { return err } } f.Set(v3) } case reflect.Array: for i := 0; i < f.Type().Len(); i++ { if err = r.ReadInterface(f.Index(i).Addr().Interface()); err != nil { return err } } default: if err := r.ReadInterface(f.Addr().Interface()); err != nil { return fmt.Errorf("%+v: %s", v, err) } else { size = int(f.Type().Size()) } } if al := f2.Tag.Get("align"); al != "" { var ( e expression.EXPRESSION align int seek int ) if !e.Parse(al) { return e.Error() } else if ev, err := expression.Eval(&v2, e.RootNode()); err != nil { return err } else { align = ev } if align < size { seek = ((size + (align - 1)) &^ (align - 1)) - size } else if align > size { seek = align - size } if seek > 0 { if _, err := r.Seek(int64(seek), 1); err != nil { return err } } } } default: return errors.New(fmt.Sprintf("Don't know how to read type %s", v2.Kind())) } if val, ok := v.(Validateable); ok { return val.Validate() } return nil }
func (m *MetadataUtil) Size(t reflect.Type) (uint, error) { size := uint(0) name := t.Name() switch name { case "StringIndex": size = uint(m.StringHeap.RowSize) case "Guid": size = uint(m.GuidHeap.RowSize) case "BlobIndex": size = uint(m.BlobHeap.RowSize) default: if strings.HasSuffix(name, "EncodedIndex") { id := idx_name_lut[name] var ( tables = enc_lut[id] rows uint32 ) for _, t := range tables { if t == id_nullTable { continue } if s2 := m.Tables[t].Rows; s2 > rows { rows = s2 } } if rows<<util.Bits(len(tables)) < 1<<16 { size = 2 } else { size = 4 } } else if strings.HasSuffix(name, "Index") { if m.Tables[idx_name_lut[name]].Rows < 1<<16 { size = 2 } else { size = 4 } } else { switch t.Kind() { case reflect.Struct: for i := 0; i < t.NumField(); i++ { f := t.Field(i) if s, err := m.Size(f.Type); err != nil { return 0, err } else { size += s } } case reflect.Uint8: return 1, nil case reflect.Uint16: return 2, nil case reflect.Uint32: return 4, nil case reflect.Uint64: return 8, nil default: return 0, errors.New(fmt.Sprintf("Don't know the size of: %s, %s", t.Name(), t.Kind())) } } } return size, nil }
func (m *MetadataUtil) Create(br *binary.BinaryReader, v interface{}) error { t := reflect.ValueOf(v) if t.Kind() != reflect.Ptr { return errors.New(fmt.Sprintf("Expected a pointer not %s", t.Kind())) } v2 := t.Elem() name := v2.Type().Name() if name == "StringIndex" { size := m.StringHeap.RowSize index, err := m.ReadIndex(br, uint(size)) if err != nil { return err } data := m.StringHeap.data[index:m.StringHeap.Rows] for i := range data { if data[i] == '\u0000' { data = data[:i] break } } v2.SetString(string(data)) } else if name == "Guid" { size := m.GuidHeap.RowSize if index, err := m.ReadIndex(br, uint(size)); err != nil { return err } else if index != 0 { index = (index - 1) * 16 g := Guid(m.GuidHeap.data[index : index+16]) v2.Set(reflect.ValueOf(g)) } } else if strings.HasSuffix(name, "EncodedIndex") { size, err := m.Size(v2.Type()) if err != nil { return err } idx, err := m.ReadIndex(br, size) if err != nil { return err } var ( tables = enc_lut[idx_name_lut[name]] b = util.Bits(len(tables)) mask = uint32(0xffff << b) tbl = idx &^ mask ti ConcreteTableIndex ) idx = idx >> b ti.index = idx ti.table = tables[int(tbl)] ti.metadataUtil = m v2.Set(reflect.ValueOf(&ti)) } else if strings.HasSuffix(name, "Index") { size, err := m.Size(v2.Type()) if err != nil { return err } var ti ConcreteTableIndex if ti.index, err = m.ReadIndex(br, size); err != nil { return err } if name == "BlobIndex" { ti.table = id_Blob } else { ti.table = idx_name_lut[name] } ti.metadataUtil = m v2.Set(reflect.ValueOf(&ti)) } else { if v2.Kind() != reflect.Struct { return br.ReadInterface(v) } for i := 0; i < v2.NumField(); i++ { f := v2.Field(i) a := f.Addr() if err := m.Create(br, a.Interface()); err != nil { return err } } } return nil }
id_StandAloneSig = 0x11 // II.22.36 id_TypeDef = 0x02 // II.22.37 id_TypeRef = 0x01 // II.22.38 id_TypeSpec = 0x1B // II.22.39 id_nullTable = 0x100 id_Blob = 0x101 ) const ( bit_stringHeapIndexSize = (1 << iota) bit_guidHeapIndexSize bit_blobHeapIndexSize ) var ( ErrMetadata = errors.New("Metadata header isn't in the expected format") table_row_type_lut = map[int]reflect.Type{ id_Assembly: reflect.TypeOf(AssemblyRow{}), id_AssemblyOS: reflect.TypeOf(AssemblyOSRow{}), id_AssemblyProcessor: reflect.TypeOf(AssemblyProcessorRow{}), id_AssemblyRef: reflect.TypeOf(AssemblyRefRow{}), id_AssemblyRefOS: reflect.TypeOf(AssemblyRefOSRow{}), id_AssemblyRefProcessor: reflect.TypeOf(AssemblyRefProcessorRow{}), id_ClassLayout: reflect.TypeOf(ClassLayoutRow{}), id_Constant: reflect.TypeOf(ConstantRow{}), id_CustomAttribute: reflect.TypeOf(CustomAttributeRow{}), id_DeclSecurity: reflect.TypeOf(DeclSecurityRow{}), id_EventMap: reflect.TypeOf(EventMapRow{}), id_Event: reflect.TypeOf(EventRow{}), id_ExportedType: reflect.TypeOf(ExportedTypeRow{}), id_Field: reflect.TypeOf(FieldRow{}),
func (r *BinaryReader) ReadInterface(v interface{}) error { if ri, ok := v.(Reader); ok { return ri.Read(r) } t := reflect.ValueOf(v) if t.Kind() != reflect.Ptr { return errors.New(fmt.Sprintf("Expected a pointer not %s", t.Kind())) } v2 := t.Elem() switch v2.Kind() { case reflect.Uint64: if d, err := r.Uint64(); err != nil { return err } else { v2.SetUint(uint64(d)) } case reflect.Uint32: if d, err := r.Uint32(); err != nil { return err } else { v2.SetUint(uint64(d)) } case reflect.Uint16: if d, err := r.Uint16(); err != nil { return err } else { v2.SetUint(uint64(d)) } case reflect.Uint8: if d, err := r.Uint8(); err != nil { return err } else { v2.SetUint(uint64(d)) } case reflect.Int64: if d, err := r.Int64(); err != nil { return err } else { v2.SetInt(int64(d)) } case reflect.Int32: if d, err := r.Int32(); err != nil { return err } else { v2.SetInt(int64(d)) } case reflect.Int16: if d, err := r.Int16(); err != nil { return err } else { v2.SetInt(int64(d)) } case reflect.Int8: if d, err := r.Int8(); err != nil { return err } else { v2.SetInt(int64(d)) } case reflect.Float32: if f, err := r.Float32(); err != nil { return err } else { v2.SetFloat(float64(f)) } case reflect.Float64: if f, err := r.Float64(); err != nil { return err } else { v2.SetFloat(f) } case reflect.Struct: for i := 0; i < v2.NumField(); i++ { var ( f = v2.Field(i) f2 = v2.Type().Field(i) size = -1 err error ) if fi := f2.Tag.Get("if"); fi != "" { arr := strings.Split(fi, ",") if f3 := v2.FieldByName(arr[0]); !f3.IsValid() { return errors.New(fmt.Sprintf("No such field: %s in %s", arr[0], v2.Type().Name())) } else if test, err := strconv.ParseUint(arr[1], 0, 64); err != nil { return err } else { if f3.Uint() != test { continue } } } if l := f2.Tag.Get("length"); l != "" { if v3 := v2.FieldByName(l); v3.IsValid() { size = int(v3.Uint()) } else if size, err = strconv.Atoi(l); err != nil { return err } } switch f.Type().Kind() { case reflect.String: var data []byte if size >= 0 { if data, err = r.Read(size); err != nil { return err } } else { var max = math.MaxInt32 if m := f2.Tag.Get("max"); m != "" { if max, err = strconv.Atoi(m); err != nil { return err } } for i := 0; i < max; i++ { if u, err := r.Uint8(); err != nil { return err } else if u == '\u0000' { size = i + 1 break } else { data = append(data, u) } } } f.SetString(string(data)) case reflect.Slice: if size == -1 { return errors.New("SliceHeader require a known length") } if f.Type().Elem().Kind() == reflect.Int8 { if b, err := r.Read(size); err != nil { return err } else { f.Set(reflect.ValueOf(b)) } } else { var v3 = reflect.MakeSlice(f.Type(), size, size) for i := 0; i < size; i++ { if err = r.ReadInterface(v3.Index(i).Addr().Interface()); err != nil { return err } } f.Set(v3) } case reflect.Array: for i := 0; i < f.Type().Len(); i++ { if err = r.ReadInterface(f.Index(i).Addr().Interface()); err != nil { return err } } default: if err := r.ReadInterface(f.Addr().Interface()); err != nil { return err } else { size = int(f.Type().Size()) } } if al := f2.Tag.Get("align"); al != "" { if a, err := strconv.Atoi(al); err != nil { return err } else if seek := ((size + (a - 1)) &^ (a - 1)) - size; seek > 0 { if _, err := r.Seek(int64(seek), 1); err != nil { return err } } } } default: return errors.New(fmt.Sprintf("Don't know how to read type %s", v2.Kind())) } if val, ok := v.(Validateable); ok { return val.Validate() } return nil }
func (coff *coff_file_header) Validate() error { if bytes.Compare(coff.Magic, pe_magic) != 0 { return errors.New(fmt.Sprintf("PE Magic mismatch: %v", coff.Magic)) } return nil }
func (h *hash_tilde_stream_header) Validate() error { if h.Reserved != 0 || h.MajorVersion != 2 || h.MinorVersion != 0 /*|| h.Reserved2 != 1*/ { //TODO: Hmm spec says Reserved2 should be 1, but it appears to be 0x10? return errors.New(fmt.Sprintf("This does not appear to be a valid #~ stream header: %#v", h)) } return nil }
func (s *stream_header) Validate() error { if s.Name[0] != '#' { return errors.New(fmt.Sprintf("This does not appear to be a valid stream header: %#v", s)) } return nil }
func (s *section_table) Validate() error { if s.Name[0] != '.' { return errors.New(fmt.Sprintf("This does not appear to be a valid section header: %#v", s)) } return nil }