Skip to content

Commit

Permalink
Fix-up .dynamic section
Browse files Browse the repository at this point in the history
  • Loading branch information
Cryptogenic committed Dec 20, 2021
1 parent d8d15c1 commit 0b1fe04
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 2 deletions.
3 changes: 3 additions & 0 deletions cmd/create-fself/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ func main() {
err = orbisElf.RewriteProgramHeaders()
check(err)

// Overwrite .dynamic section header to point to the new dynamic table
err = orbisElf.RewriteDynamicSectionHeader()

// Commit
err = orbisElf.FinalFile.Close()
check(err)
Expand Down
13 changes: 11 additions & 2 deletions pkg/oelf/OELFGenProgramHeaders.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ func (orbisElf *OrbisElf) GenerateProgramHeaders() error {
procParamSection = orbisElf.ElfToConvert.Section(".data.sce_module_param")
}

// Get GNU_RELRO header pre-emptively (we'll need to check it to eliminate duplicate PT_LOAD headers)
gnuRelroSegment := orbisElf.getProgramHeader(elf.PT_GNU_RELRO, elf.PF_R)

// First pass: drop program headers that we don't need and copy all others
for _, progHeader := range orbisElf.ElfToConvert.Progs {
// PT_LOAD read-only should be consolidated into PT_LOAD for .text
Expand All @@ -33,12 +36,18 @@ func (orbisElf *OrbisElf) GenerateProgramHeaders() error {
}

// PT_LOAD for relro will be handled by SCE_RELRO, we can get rid of it
if relroSection != nil {
if progHeader.Type == elf.PT_LOAD && progHeader.Off == relroSection.Offset {
if gnuRelroSegment != nil {
if progHeader.Type == elf.PT_LOAD && progHeader.Off == gnuRelroSegment.Off {
continue
}
}

// GNU_RELRO will sometimes get generated even if no .data.rel.ro is present. This is bad for PS4 because the
// header will be unaligned and it's not necessary. Get rid of it if there's no relro section.
if progHeader.Type == elf.PT_GNU_RELRO && relroSection == nil {
continue
}

// GNU_STACK can be dropped, PS4 doesn't need it
if progHeader.Type == elf.PT_GNU_STACK {
continue
Expand Down
62 changes: 62 additions & 0 deletions pkg/oelf/OELFRewriteData.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,65 @@ func (orbisElf *OrbisElf) RewriteInterpreter(interpreter string) error {
_, err = orbisElf.FinalFile.WriteAt(interpreterBuff, rewriteOffset)
return err
}

// RewriteDynamicSectionHeader will overwrite the address of the .dynamic section with the given address. Returns
// an error if the write failed, nil otherwise.
func (orbisElf *OrbisElf) RewriteDynamicSectionHeader() error {
var (
inputFile *os.File
err error
)

// Get the section header offset info from the original file
inputHdr := new(elf.Header64)

if inputFile, err = os.Open(orbisElf.ElfToConvertName); err != nil {
return err
}

if _, err = inputFile.Seek(0, io.SeekStart); err != nil {
return err
}

if err = binary.Read(inputFile, orbisElf.ElfToConvert.ByteOrder, inputHdr); err != nil {
return err
}

sectionHeadersOffset := inputHdr.Shoff

// Find the dynamic header
for i := uint16(0); i < inputHdr.Shnum; i++ {
sectionHdr := new(elf.Section64)
sectionHeaderOffset := int64(sectionHeadersOffset + uint64(i*inputHdr.Shentsize))

if _, err = inputFile.Seek(sectionHeaderOffset, io.SeekStart); err != nil {
return err
}

if err = binary.Read(inputFile, orbisElf.ElfToConvert.ByteOrder, sectionHdr); err != nil {
return err
}

if sectionHdr.Type == uint32(elf.SHT_DYNAMIC) {
sectionHeaderBuff := new(bytes.Buffer)

// Rewrite the address
sectionHdr.Off = _offsetOfDynamic
sectionHdr.Addr = _offsetOfDynamic
sectionHdr.Size = _sizeOfDynamic

// Commit the write
if err := binary.Write(sectionHeaderBuff, binary.LittleEndian, sectionHdr); err != nil {
return err
}

if _, err := orbisElf.FinalFile.WriteAt(sectionHeaderBuff.Bytes(), sectionHeaderOffset); err != nil {
return err
}

break
}
}

return nil
}

0 comments on commit 0b1fe04

Please sign in to comment.