Back to index

enigmail  1.4.3
Classes | Public Member Functions | Protected Attributes | Private Member Functions | Private Attributes
ElfRelHackCode_Section Class Reference
Inheritance diagram for ElfRelHackCode_Section:
Inheritance graph
[legend]
Collaboration diagram for ElfRelHackCode_Section:
Collaboration graph
[legend]

List of all members.

Classes

class  arm_plt32_relocation
class  arm_thm_jump24_relocation
class  gotoff_relocation
class  pc32_relocation

Public Member Functions

 ElfRelHackCode_Section (Elf_Shdr &s, Elf &e)
 ~ElfRelHackCode_Section ()
void serialize (std::ofstream &file, char ei_class, char ei_data)
bool isRelocatable ()
unsigned int getEntryPoint ()
const char * getName ()
unsigned int getType ()
unsigned int getFlags ()
unsigned int getAddr ()
unsigned int getSize ()
unsigned int getAddrAlign ()
unsigned int getEntSize ()
const char * getData ()
ElfSectiongetLink ()
SectionInfo getInfo ()
void shrink (unsigned int newsize)
unsigned int getOffset ()
int getIndex ()
Elf_ShdrgetShdr ()
ElfSectiongetNext ()
ElfSectiongetPrevious ()
void insertAfter (ElfSection *section, bool dirty=true)
void markDirty ()

Protected Attributes

Elf_Shdr shdr
char * data
const char * name

Private Member Functions

template<class relocation_type >
void apply_relocation (ElfSection *the_code, char *base, Elf_Rel *r, unsigned int addr)
template<class relocation_type >
void apply_relocation (ElfSection *the_code, char *base, Elf_Rela *r, unsigned int addr)
template<typename Rel_Type >
void apply_relocations (ElfRel_Section< Rel_Type > *rel, ElfSection *the_code)

Private Attributes

Elfelf
Elfparent
std::vector< ElfSection * > code
ElfSectioninit
int entry_point

Detailed Description

Definition at line 115 of file elfhack.cpp.


Constructor & Destructor Documentation

Definition at line 117 of file elfhack.cpp.

    : ElfSection(s, NULL, NULL), parent(e) {
        std::string file(rundir);
        init = parent.getDynSection()->getSectionForType(DT_INIT);
        file += "/inject/";
        switch (parent.getMachine()) {
        case EM_386:
            file += "x86";
            break;
        case EM_X86_64:
            file += "x86_64";
            break;
        case EM_ARM:
            file += "arm";
            break;
        default:
            throw std::runtime_error("unsupported architecture");
        }
        if (init == NULL)
            file += "-noinit";
        file += ".o";
        std::ifstream inject(file.c_str(), std::ios::in|std::ios::binary);
        elf = new Elf(inject);
        if (elf->getType() != ET_REL)
            throw std::runtime_error("object for injected code is not ET_REL");
        if (elf->getMachine() != parent.getMachine())
            throw std::runtime_error("architecture of object for injected code doesn't match");

        ElfSymtab_Section *symtab = NULL;

        // Get all executable sections from the injected code object.
        // Most of the time, there will only be one for the init function,
        // but on e.g. x86, there is a separate section for
        // __i686.get_pc_thunk.$reg
        // Find the symbol table at the same time.
        for (ElfSection *section = elf->getSection(1); section != NULL;
             section = section->getNext()) {
            if ((section->getType() == SHT_PROGBITS) &&
                (section->getFlags() & SHF_EXECINSTR)) {
                code.push_back(section);
                // We need to align this section depending on the greater
                // alignment required by code sections.
                if (shdr.sh_addralign < section->getAddrAlign())
                    shdr.sh_addralign = section->getAddrAlign();
            } else if (section->getType() == SHT_SYMTAB) {
                symtab = (ElfSymtab_Section *) section;
            }
        }
        assert(code.size() != 0);
        if (symtab == NULL)
            throw std::runtime_error("Couldn't find a symbol table for the injected code");

        // Find the init symbol
        entry_point = -1;
        int shndx = 0;
        Elf_SymValue *sym = symtab->lookup("init");
        if (sym) {
            entry_point = sym->value.getValue();
            shndx = sym->value.getSection()->getIndex();
        } else
            throw std::runtime_error("Couldn't find an 'init' symbol in the injected code");

        // Adjust code sections offsets according to their size
        std::vector<ElfSection *>::iterator c = code.begin();
        (*c)->getShdr().sh_addr = 0;
        for(ElfSection *last = *(c++); c != code.end(); c++) {
            unsigned int addr = last->getShdr().sh_addr + last->getSize();
            if (addr & ((*c)->getAddrAlign() - 1))
                addr = (addr | ((*c)->getAddrAlign() - 1)) + 1;
            (*c)->getShdr().sh_addr = addr;
        }
        shdr.sh_size = code.back()->getAddr() + code.back()->getSize();
        data = new char[shdr.sh_size];
        char *buf = data;
        for (c = code.begin(); c != code.end(); c++) {
            memcpy(buf, (*c)->getData(), (*c)->getSize());
            buf += (*c)->getSize();
            if ((*c)->getIndex() < shndx)
                entry_point += (*c)->getSize();
        }
        name = elfhack_text;
    }

Here is the call graph for this function:

Definition at line 200 of file elfhack.cpp.

                              {
        delete elf;
    }

Member Function Documentation

template<class relocation_type >
void ElfRelHackCode_Section::apply_relocation ( ElfSection the_code,
char *  base,
Elf_Rel r,
unsigned int  addr 
) [inline, private]

Definition at line 299 of file elfhack.cpp.

    {
        relocation_type relocation;
        Elf32_Addr value;
        memcpy(&value, base + r->r_offset, 4);
        value = relocation(the_code->getAddr(), r->r_offset, value, addr);
        memcpy(base + r->r_offset, &value, 4);
    }

Here is the call graph for this function:

template<class relocation_type >
void ElfRelHackCode_Section::apply_relocation ( ElfSection the_code,
char *  base,
Elf_Rela r,
unsigned int  addr 
) [inline, private]

Definition at line 309 of file elfhack.cpp.

    {
        relocation_type relocation;
        Elf32_Addr value = relocation(the_code->getAddr(), r->r_offset, r->r_addend, addr);
        memcpy(base + r->r_offset, &value, 4);
    }

Here is the call graph for this function:

template<typename Rel_Type >
void ElfRelHackCode_Section::apply_relocations ( ElfRel_Section< Rel_Type > *  rel,
ElfSection the_code 
) [inline, private]

Definition at line 317 of file elfhack.cpp.

    {
        assert(rel->getType() == Rel_Type::sh_type);
        char *buf = data + (the_code->getAddr() - code.front()->getAddr());
        // TODO: various checks on the sections
        ElfSymtab_Section *symtab = (ElfSymtab_Section *)rel->getLink();
        for (typename std::vector<Rel_Type>::iterator r = rel->rels.begin(); r != rel->rels.end(); r++) {
            // TODO: various checks on the symbol
            const char *name = symtab->syms[ELF32_R_SYM(r->r_info)].name;
            unsigned int addr;
            if (symtab->syms[ELF32_R_SYM(r->r_info)].value.getSection() == NULL) {
                if (strcmp(name, "relhack") == 0) {
                    addr = getNext()->getAddr();
                } else if (strcmp(name, "elf_header") == 0) {
                    // TODO: change this ungly hack to something better
                    ElfSection *ehdr = parent.getSection(1)->getPrevious()->getPrevious();
                    addr = ehdr->getAddr();
                } else if (strcmp(name, "original_init") == 0) {
                    addr = init->getAddr();
                } else if (strcmp(name, "_GLOBAL_OFFSET_TABLE_") == 0) {
                    // We actually don't need a GOT, but need it as a reference for
                    // GOTOFF relocations. We'll just use the start of the ELF file
                    addr = 0;
                } else if (strcmp(name, "") == 0) {
                    // This is for R_ARM_V4BX, until we find something better
                    addr = -1;
                } else {
                    throw std::runtime_error("Unsupported symbol in relocation");
                }
            } else {
                ElfSection *section = symtab->syms[ELF32_R_SYM(r->r_info)].value.getSection();
                assert((section->getType() == SHT_PROGBITS) && (section->getFlags() & SHF_EXECINSTR));
                addr = symtab->syms[ELF32_R_SYM(r->r_info)].value.getValue();
            }
            // Do the relocation
#define REL(machine, type) (EM_ ## machine | (R_ ## machine ## _ ## type << 8))
            switch (elf->getMachine() | (ELF32_R_TYPE(r->r_info) << 8)) {
            case REL(X86_64, PC32):
            case REL(386, PC32):
            case REL(386, GOTPC):
            case REL(ARM, GOTPC):
            case REL(ARM, REL32):
                apply_relocation<pc32_relocation>(the_code, buf, &*r, addr);
                break;
            case REL(ARM, PLT32):
                apply_relocation<arm_plt32_relocation>(the_code, buf, &*r, addr);
                break;
            case REL(ARM, THM_JUMP24):
                apply_relocation<arm_thm_jump24_relocation>(the_code, buf, &*r, addr);
                break;
            case REL(386, GOTOFF):
            case REL(ARM, GOTOFF):
                apply_relocation<gotoff_relocation>(the_code, buf, &*r, addr);
                break;
            case REL(ARM, V4BX):
                // Ignore R_ARM_V4BX relocations
                break;
            default:
                throw std::runtime_error("Unsupported relocation type");
            }
        }
    }

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned int ElfSection::getAddr ( ) [inherited]

Definition at line 483 of file elf.cpp.

{
    if (shdr.sh_addr != (Elf32_Word)-1)
        return shdr.sh_addr;

    // It should be safe to adjust sh_addr for all allocated sections that
    // are neither SHT_NOBITS nor SHT_PROGBITS
    if ((previous != NULL) && isRelocatable()) {
        unsigned int addr = previous->getAddr();
        if (previous->getType() != SHT_NOBITS)
            addr += previous->getSize();

        if (addr & (getAddrAlign() - 1))
            addr = (addr | (getAddrAlign() - 1)) + 1;

        return (shdr.sh_addr = addr);
    }
    return shdr.sh_addr;
}

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned int ElfSection::getAddrAlign ( ) [inline, inherited]

Definition at line 342 of file elfxx.h.

{ return shdr.sh_addralign; }

Here is the caller graph for this function:

const char* ElfSection::getData ( ) [inline, inherited]

Definition at line 344 of file elfxx.h.

{ return data; }

Here is the caller graph for this function:

unsigned int ElfRelHackCode_Section::getEntryPoint ( ) [inline]

Definition at line 229 of file elfhack.cpp.

                                 {
        return entry_point;
    }

Here is the caller graph for this function:

unsigned int ElfSection::getEntSize ( ) [inline, inherited]

Definition at line 343 of file elfxx.h.

{ return shdr.sh_entsize; }

Here is the caller graph for this function:

unsigned int ElfSection::getFlags ( ) [inline, inherited]

Definition at line 339 of file elfxx.h.

{ return shdr.sh_flags; }

Here is the caller graph for this function:

int ElfSection::getIndex ( ) [inherited]

Definition at line 541 of file elf.cpp.

{
    if (index != -1)
        return index;
    if (getType() == SHT_NULL)
        return (index = 0);
    ElfSection *reference;
    for (reference = previous; (reference != NULL) && (reference->getType() == SHT_NULL); reference = reference->getPrevious());
    if (reference == NULL)
        return (index = 1);
    return (index = reference->getIndex() + 1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

SectionInfo ElfSection::getInfo ( ) [inline, inherited]

Definition at line 346 of file elfxx.h.

{ return info; }

Here is the caller graph for this function:

ElfSection* ElfSection::getLink ( ) [inline, inherited]

Definition at line 345 of file elfxx.h.

{ return link; }

Here is the caller graph for this function:

const char* ElfSection::getName ( ) [inline, inherited]

Definition at line 337 of file elfxx.h.

{ return name; }

Here is the caller graph for this function:

ElfSection* ElfSection::getNext ( ) [inline, inherited]

Definition at line 360 of file elfxx.h.

{ return next; }

Here is the caller graph for this function:

unsigned int ElfSection::getOffset ( ) [inherited]

Definition at line 503 of file elf.cpp.

{
    if (shdr.sh_offset != (Elf32_Word)-1)
        return shdr.sh_offset;

    if (previous == NULL)
        return (shdr.sh_offset = 0);

    unsigned int offset = previous->getOffset();
    if (previous->getType() != SHT_NOBITS)
        offset += previous->getSize();

    Elf32_Word align = 0x1000;
    for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
        align = std::max(align, (*seg)->getAlign());

    Elf32_Word mask = align - 1;
    // SHF_TLS is used for .tbss which is some kind of special case.
    if (((getType() != SHT_NOBITS) || (getFlags() & SHF_TLS)) && (getFlags() & SHF_ALLOC)) {
        if ((getAddr() & mask) < (offset & mask))
            offset = (offset | mask) + (getAddr() & mask) + 1;
        else
            offset = (offset & ~mask) + (getAddr() & mask);
    }
    if ((getType() != SHT_NOBITS) && (offset & (getAddrAlign() - 1)))
        offset = (offset | (getAddrAlign() - 1)) + 1;

    // Two subsequent sections can't be mapped in the same page in memory
    // if they aren't in the same 4K block on disk.
    if ((getType() != SHT_NOBITS) && getAddr()) {
        if (((offset >> 12) != (previous->getOffset() >> 12)) &&
            ((getAddr() >> 12) == (previous->getAddr() >> 12)))
            throw std::runtime_error("Moving section would require overlapping segments");
    }

    return (shdr.sh_offset = offset);
}

Here is the call graph for this function:

Here is the caller graph for this function:

ElfSection* ElfSection::getPrevious ( ) [inline, inherited]

Definition at line 361 of file elfxx.h.

{ return previous; }

Here is the caller graph for this function:

Elf_Shdr & ElfSection::getShdr ( ) [inherited]

Definition at line 554 of file elf.cpp.

{
    getOffset();
    if (shdr.sh_link == (Elf32_Word)-1)
        shdr.sh_link = getLink() ? getLink()->getIndex() : 0;
    if (shdr.sh_info == (Elf32_Word)-1)
        shdr.sh_info = ((getType() == SHT_REL) || (getType() == SHT_RELA)) ?
                       (getInfo().section ? getInfo().section->getIndex() : 0) :
                       getInfo().index;

    return shdr;
}

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned int ElfSection::getSize ( ) [inline, inherited]

Definition at line 341 of file elfxx.h.

{ return shdr.sh_size; }

Here is the caller graph for this function:

unsigned int ElfSection::getType ( ) [inline, inherited]

Definition at line 338 of file elfxx.h.

{ return shdr.sh_type; }

Here is the caller graph for this function:

void ElfSection::insertAfter ( ElfSection section,
bool  dirty = true 
) [inline, inherited]

Definition at line 379 of file elfxx.h.

                                                             {
        if (previous != NULL)
            previous->next = next;
        if (next != NULL)
            next->previous = previous;
        previous = section;
        if (section != NULL) {
            next = section->next;
            section->next = this;
        } else
            next = NULL;
        if (next != NULL)
            next->previous = this;
        if (dirty)
            markDirty();
    }

Here is the call graph for this function:

Here is the caller graph for this function:

bool ElfRelHackCode_Section::isRelocatable ( ) [inline, virtual]

Reimplemented from ElfSection.

Definition at line 225 of file elfhack.cpp.

                         {
        return true;
    }
void ElfSection::markDirty ( ) [inline, inherited]

Definition at line 396 of file elfxx.h.

                     {
        if (link != NULL)
            shdr.sh_link = -1;
        if (info.index)
            shdr.sh_info = -1;
        shdr.sh_offset = -1;
        if (isRelocatable())
            shdr.sh_addr = -1;
        if (next)
            next->markDirty();
    }

Here is the call graph for this function:

Here is the caller graph for this function:

void ElfRelHackCode_Section::serialize ( std::ofstream &  file,
char  ei_class,
char  ei_data 
) [inline, virtual]

Reimplemented from ElfSection.

Definition at line 204 of file elfhack.cpp.

    {
        // Readjust code offsets
        for (std::vector<ElfSection *>::iterator c = code.begin(); c != code.end(); c++)
            (*c)->getShdr().sh_addr += getAddr();

        // Apply relocations
        for (ElfSection *rel = elf->getSection(1); rel != NULL; rel = rel->getNext())
            if ((rel->getType() == SHT_REL) || (rel->getType() == SHT_RELA)) {
                ElfSection *section = rel->getInfo().section;
                if ((section->getType() == SHT_PROGBITS) && (section->getFlags() & SHF_EXECINSTR)) {
                    if (rel->getType() == SHT_REL)
                        apply_relocations((ElfRel_Section<Elf_Rel> *)rel, section);
                    else
                        apply_relocations((ElfRel_Section<Elf_Rela> *)rel, section);
                }
            }

        ElfSection::serialize(file, ei_class, ei_data);
    }

Here is the call graph for this function:

void ElfSection::shrink ( unsigned int  newsize) [inline, inherited]

Definition at line 348 of file elfxx.h.

                                      {
        if (newsize < shdr.sh_size) {
            shdr.sh_size = newsize;
            if (next)
                next->markDirty();
        }
    }

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

std::vector<ElfSection *> ElfRelHackCode_Section::code [private]

Definition at line 381 of file elfhack.cpp.

char* ElfSection::data [protected, inherited]

Definition at line 431 of file elfxx.h.

Definition at line 380 of file elfhack.cpp.

Definition at line 383 of file elfhack.cpp.

Definition at line 382 of file elfhack.cpp.

const char* ElfSection::name [protected, inherited]

Definition at line 432 of file elfxx.h.

Definition at line 380 of file elfhack.cpp.

Elf_Shdr ElfSection::shdr [protected, inherited]

Definition at line 430 of file elfxx.h.


The documentation for this class was generated from the following file: