func sanity() { goBinGo := path.Join(config.Gosrcroot, "go/bin/go") log.Printf("check %v as the go binary", goBinGo) _, err := os.Stat(goBinGo) if err == nil { config.Go = "go/bin/go" } // but does the one in go/bin/OS_ARCH exist too? archgo := fmt.Sprintf("bin/%s_%s/go", config.Goos, config.Arch) linuxBinGo := path.Join(config.Gosrcroot, archgo) log.Printf("check %v as the go binary", linuxBinGo) _, err = os.Stat(linuxBinGo) if err == nil { config.Go = archgo goBinGo = linuxBinGo } log.Printf("Using %v as the go command", goBinGo) if config.Go == "" { log.Fatalf("Can't find a go binary! Is GOROOT set correctly?") } f, err := elf.Open(goBinGo) if err != nil { log.Fatalf("%v is not an ELF file; don't know what to do", goBinGo) } ds := f.SectionByType(elf.SHT_DYNAMIC) if ds != nil { log.Printf("U-root requires a staticically built go tree at present. %v is dynamic.", goBinGo) log.Fatalf("To fix this:\ncd %v/src\nexport CGO_ENABLED=0\nGOARCH=%v ./make.bash", config.Goroot, config.Arch) } }
func IsELF(fPath string) error { if _, err := elf.Open(fPath); err != nil { return err } return nil }
func cmdMode(cmd string, args []string) error { f, err := elf.Open(cmd) if err != nil { return err } defer f.Close() // Set mem limits for _, p := range f.Progs { if p.Type != elf.PT_LOAD { continue } if p.Vaddr < startAddr { startAddr = p.Vaddr } if addr := p.Vaddr + p.Memsz; addr > endAddr { endAddr = addr } } pt, err := ForkExec(cmd, args) if err != nil { return err } if err := pt.Wait(printPC); err != nil { return err } return nil }
func getDwarf(execname string) *dwarf.Data { e, err := elf.Open(execname) if err == nil { defer e.Close() d, err := e.DWARF() if err == nil { return d } } m, err := macho.Open(execname) if err == nil { defer m.Close() d, err := m.DWARF() if err == nil { return d } } p, err := pe.Open(execname) if err == nil { defer p.Close() d, err := p.DWARF() if err == nil { return d } } log.Fatal("can't get dwarf info from executable", err) return nil }
func FindFunc(fileName string, pc uint64) (s elf.Symbol, err error) { file, err := elf.Open(fileName) if err != nil { return elf.Symbol{}, err } symbols, err := file.Symbols() if err != nil { return elf.Symbol{}, err } funcSymbols := make(Symbols, 0) for _, symbol := range symbols { if elf.ST_TYPE(symbol.Info) == elf.STT_FUNC { funcSymbols = append(funcSymbols, symbol) } } n := len(funcSymbols) if n == 0 { return elf.Symbol{}, &ErrNoFunctions{} } sort.Sort(funcSymbols) i := sort.Search(n, func(i int) bool { return funcSymbols[i].Value >= pc }) if i != 0 || funcSymbols[i].Value <= pc { if i == n || (funcSymbols[i].Value != pc && i != 0) { i-- } return funcSymbols[i], nil } return elf.Symbol{}, &ErrFunctionNotFound{} }
func testBuildID(t *testing.T) { f, err := elf.Open("/proc/self/exe") if err != nil { if os.IsNotExist(err) { t.Skip("no /proc/self/exe") } t.Fatal("opening /proc/self/exe: ", err) } defer f.Close() c := 0 for i, s := range f.Sections { if s.Type != elf.SHT_NOTE { continue } d, err := s.Data() if err != nil { t.Logf("reading data of note section %d: %v", i, err) continue } for len(d) > 0 { // ELF standards differ as to the sizes in // note sections. Both the GNU linker and // gold always generate 32-bit sizes, so that // is what we assume here. if len(d) < 12 { t.Logf("note section %d too short (%d < 12)", i, len(d)) continue } namesz := f.ByteOrder.Uint32(d) descsz := f.ByteOrder.Uint32(d[4:]) typ := f.ByteOrder.Uint32(d[8:]) an := (namesz + 3) &^ 3 ad := (descsz + 3) &^ 3 if int(12+an+ad) > len(d) { t.Logf("note section %d too short for header (%d < 12 + align(%d,4) + align(%d,4))", i, len(d), namesz, descsz) continue } // 3 == NT_GNU_BUILD_ID if typ == 3 && namesz == 4 && bytes.Equal(d[12:16], []byte("GNU\000")) { c++ } d = d[12+an+ad:] } } if c > 1 { t.Errorf("found %d build ID notes", c) } }
func main() { file, err := elf.Open("hello") if err != nil { log.Fatalf("failed opening file: %s", err) } defer file.Close() printDwarfInformation(file) }
func main() { file, err := elf.Open("bash.elf") if err != nil { log.Fatalf("failed opening file: %s", err) } defer file.Close() printFileInformation(file) }
func crack(file string, t *testing.T) (*elf.File, *Table) { // Open self f, err := elf.Open(file) if err != nil { t.Fatal(err) } return parse(file, f, t) }
func main() { file, err := elf.Open("doozerd") if err != nil { log.Fatalf("failed opening file: %s", err) } defer file.Close() processGoInformation(file) }
func dynimport(obj string) { if f, err := elf.Open(obj); err == nil { sym, err := f.ImportedSymbols() if err != nil { fatalf("cannot load imported symbols from ELF file %s: %v", obj, err) } for _, s := range sym { targ := s.Name if s.Version != "" { targ += "@" + s.Version } fmt.Printf("#pragma dynimport %s %s %q\n", s.Name, targ, s.Library) } lib, err := f.ImportedLibraries() if err != nil { fatalf("cannot load imported libraries from ELF file %s: %v", obj, err) } for _, l := range lib { fmt.Printf("#pragma dynimport _ _ %q\n", l) } return } if f, err := macho.Open(obj); err == nil { sym, err := f.ImportedSymbols() if err != nil { fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err) } for _, s := range sym { if len(s) > 0 && s[0] == '_' { s = s[1:] } fmt.Printf("#pragma dynimport %s %s %q\n", s, s, "") } lib, err := f.ImportedLibraries() if err != nil { fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err) } for _, l := range lib { fmt.Printf("#pragma dynimport _ _ %q\n", l) } return } if f, err := pe.Open(obj); err == nil { sym, err := f.ImportedSymbols() if err != nil { fatalf("cannot load imported symbols from PE file %s: %v", obj, err) } for _, s := range sym { ss := strings.Split(s, ":", -1) fmt.Printf("#pragma dynimport %s %s %q\n", ss[0], ss[0], strings.ToLower(ss[1])) } return } fatalf("cannot parse %s as ELF, Mach-O or PE", obj) }
func data2c(name string, path string) (string, error) { var out []byte var in []byte if elf, err := elf.Open(path); err == nil { elf.Close() cwd, err := os.Getwd() tmpf, err := ioutil.TempFile(cwd, name) if err != nil { log.Fatalf("%v\n", err) } args := []string{"-o", tmpf.Name(), path} cmd := exec.Command(toolprefix+"strip", args...) cmd.Env = nil cmd.Stdin = os.Stdin cmd.Stderr = os.Stderr cmd.Stdout = os.Stdout log.Printf("%v", cmd.Args) err = cmd.Run() if err != nil { log.Fatalf("%v\n", err) } in, err = ioutil.ReadAll(tmpf) if err != nil { log.Fatalf("%v\n", err) } tmpf.Close() os.Remove(tmpf.Name()) } else { var file *os.File var err error if file, err = os.Open(path); err != nil { log.Fatalf("%v", err) } in, err = ioutil.ReadAll(file) if err != nil { log.Fatalf("%v\n", err) } file.Close() } total := len(in) out = []byte(fmt.Sprintf("static unsigned char ramfs_%s_code[] = {\n", name)) for len(in) > 0 { for j := 0; j < 16 && len(in) > 0; j++ { out = append(out, []byte(fmt.Sprintf("0x%02x, ", in[0]))...) in = in[1:] } out = append(out, '\n') } out = append(out, []byte(fmt.Sprintf("0,\n};\nint ramfs_%s_len = %v;\n", name, total))...) return string(out), nil }
func HasSection(path string) bool { file, err := elf.Open(path) if err != nil { return false } defer file.Close() return file.Section("goblet") != nil }
func main() { f, err := elf.Open(os.Args[0]) if err != nil { fmt.Println(" ", err) return } fmt.Println(f.FileHeader.ByteOrder) f.Close() }
func dump_elf(filename string) int { file, err := elf.Open(filename) if err != nil { fmt.Printf("Couldn’t open file : \"%s\" as an ELF.\n") return 2 } dump_dynstr(file) dump_symbols(file) return 0 }
func main() { // len(Args) f, e := elf.Open(os.Args[1]) if e != nil { println(e) return } text := f.Section(".text") gopclntab := f.Section(".gopclntab") gopclndata, e := gopclntab.Data() if e != nil { println(e) return } pclntab := gosym.NewLineTable(gopclndata, text.Addr) gosymtab := f.Section(".gosymtab") gosymdata, e := gosymtab.Data() symtab, e := gosym.NewTable(gosymdata, pclntab) if e != nil { println(e) return } args := make([]string, 3) args[0] = "/usr/bin/objdump" args[1] = "-D" args[2] = os.Args[1] cmd, e := exec.Run(args[0], args, os.Environ(), exec.DevNull, exec.Pipe, exec.MergeWithStdout) if e != nil { println(e) return } reader := bufio.NewReader(cmd.Stdout) for { line, e := reader.ReadString('\n') if e != nil { break } addr := extractAddrFromLine(line) function := symtab.PCToFunc(addr) if function != nil && function.Entry == addr { fmt.Printf("%08x <%s.%s>:\n", addr, function.Sym.PackageName(), function.Sym.BaseName()) } print(line) } f.Close() }
// The shared library does not have relocations against the text segment. func TestNoTextrel(t *testing.T) { sopath := filepath.Join(gorootInstallDir, soname) f, err := elf.Open(sopath) if err != nil { t.Fatal("elf.Open failed: ", err) } defer f.Close() if hasDynTag(f, elf.DT_TEXTREL) { t.Errorf("%s has DT_TEXTREL set", soname) } }
func elfData(t *testing.T, name string) *Data { f, err := elf.Open(name) if err != nil { t.Fatal(err) } d, err := f.DWARF() if err != nil { t.Fatal(err) } return d }
// ExtractSymbolTable attempts to parse the DWARF section of a binary and return // a symbol table. This currently just supports file names, and function // definitions func ExtractSymbolTable(binary string, offset uint64) (*SymbolTable, error) { files := make(SymbolTable) f, err := elf.Open(binary) if err != nil { return nil, err } defer f.Close() dwarfs, err := f.DWARF() if err != nil { return nil, err } dwarfReader := dwarfs.Reader() for { entry, _ := dwarfReader.Next() if entry == nil { break } /* TODO: This is all by value, make this references */ // For now, all we need are files and functions switch entry.Tag { case dwarf.TagCompileUnit: file := extractFile(entry) // file.Lowpc += offset // file.Highpc += offset name := file.Filename if name == "" { continue } files[name] = file /* TODO: Stupid inefficient */ case dwarf.TagSubprogram: fun := extractFunction(entry) // fun.Highpc += offset // fun.Lowpc += offset for _, v := range files { if contains(v, fun) { v.Functions[fun.Name] = fun } } } } return &files, nil }
func dynStrings(t *testing.T, path string, flag elf.DynTag) []string { f, err := elf.Open(path) defer f.Close() if err != nil { t.Fatalf("elf.Open(%q) failed: %v", path, err) } dynstrings, err := f.DynString(flag) if err != nil { t.Fatalf("DynString(%s) failed on %s: %v", flag, path, err) } return dynstrings }
func ELFAnal(input string, symbolsDump bool) ([][]int, error) { // An array of arrays for storing the section offsets var sectionData [][]int fmt.Printf("[+] Analyzing binary: %s\n", input) // Check for executable type elfFmt, err := elf.Open(input) if err != nil { return sectionData, err } defer elfFmt.Close() sections := elfFmt.Sections sectionCount := len(sections) fmt.Printf("[+] Number of sections: %d\n", sectionCount) for k := range sections { sec := sections[k] secName := sec.Name secSize := sec.Size secOffset := sec.Offset + 1 secEnd := int(secOffset) + int(secSize) - 1 fmt.Printf("\t Name: %s\n", secName) fmt.Printf("\t Size: %d\n", secSize) fmt.Printf("\t Offset: %d\n", secOffset) fmt.Printf("\t Section end: %d\n", secEnd) fmt.Println("") sectionData = append(sectionData, []int{int(secOffset), int(secEnd)}) } symbols, err := elfFmt.ImportedSymbols() if err != nil { return sectionData, err } numberOfSymbols := len(symbols) fmt.Printf("[+] Found %d symbols\n", numberOfSymbols) if numberOfSymbols > 0 && symbolsDump { for k := range symbols { symName := symbols[k] fmt.Printf("\t Name: %s\n", symName) } fmt.Println("") } return sectionData, nil }
func dynStrings(path string, flag elf.DynTag) []string { f, err := elf.Open(path) defer f.Close() if err != nil { log.Fatal("elf.Open failed: ", err) } dynstrings, err := f.DynString(flag) if err != nil { log.Fatal("dynstring failed: ", err) } return dynstrings }
func ReadFromBinary(filename string) ([]byte, error) { file, err := elf.Open(os.Args[0]) if err != nil { return []byte{}, err } sec := file.Section(filename) if sec == nil { return []byte{}, errors.New("no section for filename") } return sec.Data() }
func checkPIE(t *testing.T, name string) { f, err := elf.Open(name) if err != nil { t.Fatal("elf.Open failed: ", err) } defer f.Close() if f.Type != elf.ET_DYN { t.Errorf("%s has type %v, want ET_DYN", name, f.Type) } if hasDynTag(f, elf.DT_TEXTREL) { t.Errorf("%s has DT_TEXTREL set", name) } }
// gccDebug runs gcc -gdwarf-2 over the C program stdin and // returns the corresponding DWARF data and, if present, debug data block. func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) { runGcc(stdin, p.gccCmd()) if f, err := macho.Open(gccTmp); err == nil { d, err := f.DWARF() if err != nil { fatalf("cannot load DWARF output from %s: %v", gccTmp, err) } var data []byte if f.Symtab != nil { for i := range f.Symtab.Syms { s := &f.Symtab.Syms[i] // Mach-O still uses a leading _ to denote non-assembly symbols. if s.Name == "_"+"__cgodebug_data" { // Found it. Now find data section. if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) { sect := f.Sections[i] if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size { if sdat, err := sect.Data(); err == nil { data = sdat[s.Value-sect.Addr:] } } } } } } return d, f.ByteOrder, data } // Can skip debug data block in ELF and PE for now. // The DWARF information is complete. if f, err := elf.Open(gccTmp); err == nil { d, err := f.DWARF() if err != nil { fatalf("cannot load DWARF output from %s: %v", gccTmp, err) } return d, f.ByteOrder, nil } if f, err := pe.Open(gccTmp); err == nil { d, err := f.DWARF() if err != nil { fatalf("cannot load DWARF output from %s: %v", gccTmp, err) } return d, binary.LittleEndian, nil } fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp) panic("not reached") }
func ELFAnal(input string) ([]SectionData, []string, []string, error) { // An array of arrays for storing the section offsets var sectionData []SectionData var symbolsArr []string // Check for executable type elfFmt, err := elf.Open(input) if err != nil { return sectionData, []string{}, []string{}, NotValidELFFileError } defer elfFmt.Close() // Extract sections sections := elfFmt.Sections for k := range sections { sec := sections[k] secName := sec.Name secSize := sec.Size secOffset := sec.Offset + 1 secEnd := secOffset + secSize - 1 sd := SectionData{ Name: secName, Size: int(secSize), Offset: int(secOffset), End: int(secEnd), } sectionData = append(sectionData, sd) } // Get imported symbols symbols, err := elfFmt.ImportedSymbols() if err != nil { return sectionData, []string{}, []string{}, err } if len(symbols) > 0 { for k := range symbols { symbolsArr = append(symbolsArr, symbols[k].Name) } } // Get imported libraries libraries, err := elfFmt.ImportedLibraries() if err != nil { return sectionData, []string{}, []string{}, err } return sectionData, libraries, symbolsArr, nil }
func TestElf(filename, expectedArch, expectedOs string, isVerbose bool) error { file, err := elf.Open(filename) if err != nil { log.Printf("File '%s' is not an ELF file: %v\n", filename, err) return err } defer file.Close() if isVerbose { log.Printf("File '%s' is an ELF file (arch: %s, osabi: %s)\n", filename, file.FileHeader.Machine.String(), file.FileHeader.OSABI.String()) } if expectedOs == platforms.LINUX { if file.FileHeader.OSABI != elf.ELFOSABI_NONE && file.FileHeader.OSABI != elf.ELFOSABI_LINUX { return errors.New("Not a Linux executable") } } if expectedOs == platforms.NETBSD { if file.FileHeader.OSABI != elf.ELFOSABI_NETBSD { return errors.New("Not a NetBSD executable") } } if expectedOs == platforms.FREEBSD { if file.FileHeader.OSABI != elf.ELFOSABI_FREEBSD { return errors.New("Not a FreeBSD executable") } } if expectedOs == platforms.OPENBSD { if file.FileHeader.OSABI != elf.ELFOSABI_OPENBSD { return errors.New("Not an OpenBSD executable") } } if expectedArch == platforms.ARM { if file.FileHeader.Machine != elf.EM_ARM { return errors.New("Not an ARM executable") } } if expectedArch == platforms.X86 { if file.FileHeader.Machine != elf.EM_386 { return errors.New("Not a 386 executable") } } if expectedArch == platforms.AMD64 { if file.FileHeader.Machine != elf.EM_X86_64 { return errors.New("Not an AMD64 executable") } } return nil }
func (v *Volume) Create() (err error) { if err = os.MkdirAll(v.Path, 0755); err != nil { return } defer func() { if err != nil { v.Remove() } }() for _, d := range v.dirs { dir := path.Join(v.Path, v.Version, d.name) if err := os.MkdirAll(dir, 0755); err != nil { return err } for _, f := range d.files { obj, err := elf.Open(f) if err != nil { return err } defer obj.Close() ok, err := blacklisted(f, obj) if err != nil { return err } if ok { continue } l := path.Join(dir, path.Base(f)) if err := os.Link(f, l); err != nil { return err } soname, err := obj.DynString(elf.DT_SONAME) if err != nil { return err } if len(soname) > 0 { f = path.Join(v.Mountpoint, d.name, path.Base(f)) l = path.Join(dir, soname[0]) if err := os.Symlink(f, l); err != nil && !os.IsExist(err.(*os.LinkError).Err) { return err } } } } return nil }
func ExtractSection(path string) ([]byte, error) { file, err := elf.Open(path) if err != nil { return nil, err } defer file.Close() section := file.Section("goblet") if section == nil { return nil, errors.New("no goblet section found") } return section.Data() }
func (r *Reporter) SetExecutable(filename string) error { f, err := elf.Open(filename) if err != nil { return err } defer f.Close() symbols, err := f.Symbols() if err != nil { return err } sort.Sort(elfSymbolTable(symbols)) r.Resolver = elfSymbolTable(symbols) return nil }