コード例 #1
0
ファイル: memory.cpp プロジェクト: Arkshine/ReGameDLL_CS
// Finds section by the file name.
Section* HIDDEN GetSectionByName(const char *moduleName)
{
	Section *section = FindSectionByName(moduleName);
	if (section == NULL)
	{
		// Update sections info
		if (!ReloadProcessMemoryInfo())
			return NULL;
		section = FindSectionByName(moduleName);
	}
	return section;
}
コード例 #2
0
ファイル: PatchEntry.cpp プロジェクト: yurizhykin/selfrando
int main(int argc, const char *argv[]) {
    ssize_t bytes_written; // only used to silence compiler warnings 
    if (argc < 2)
        errx(EX_USAGE, "Usage: PatchEntry <binary>");

    if (elf_version(EV_CURRENT) == EV_NONE)
        errx(EX_SOFTWARE, "Invalid ELF version: %s", elf_errmsg(-1));

    int fd = open(argv[1], O_RDWR);
    if (fd == -1)
        err(EX_NOINPUT, "open() failed");

    Elf *e;
    e = elf_begin(fd, ELF_C_RDWR, NULL);
    if (e == nullptr)
        errx(EX_SOFTWARE, "Failed to read from ELF file: %s", elf_errmsg(-1));

    if (elf_kind(e) != ELF_K_ELF)
        errx(EX_SOFTWARE, "File is not an ELF object");

    // Read the ELF header to find the entry point
    // FIXME: check the class/architecture, make sure it's the same as ours
    GElf_Ehdr elf_hdr;
    if (gelf_getehdr(e, &elf_hdr) == NULL)
        errx(EX_SOFTWARE, "Failed to read ELF header: %s", elf_errmsg(-1));

    auto dt_init = FindDynamicInit(e);
    auto dt_init_ofs = 0;
    if (dt_init) {
        dt_init_ofs = dt_init->info.second.sh_offset +
                      dt_init->data->d_off +
                      dt_init->index * sizeof(Elf_Dyn) +
                      offsetof(Elf_Dyn, d_un);
    }

    auto pit_sym = FindSymbol(e, kProgramInfoTableName);
    auto pit_info = FindSectionDataByAddr(e, pit_sym.st_value);
    auto pit_ofs = std::get<0>(pit_info).second.sh_offset + // Section file offset
                   std::get<1>(pit_info)->d_off +           // Elf_Data offset
                   std::get<2>(pit_info);                   // Offset relative to Elf_Data
#if 1
    if (dt_init)
        printf("Old ELF entry:%p DT_INIT:%p@%x PIT:%p@%lx\n",
               (void*) elf_hdr.e_entry,
               (void*) dt_init->dyn_section.d_un.d_ptr,
               dt_init_ofs,
               (void*) pit_sym.st_value,
               pit_ofs);
    else
        printf("Old ELF entry:%p DT_INIT:NULL PIT:%p@%lx\n",
               (void*) elf_hdr.e_entry,
               (void*) pit_sym.st_value,
               pit_ofs);
#endif

    // Replace the ProgramInfoTable values
    auto pit_data = std::get<1>(pit_info);
    auto orig_pit = reinterpret_cast<TrapProgramInfoTable*>(
        reinterpret_cast<uint8_t*>(pit_data->d_buf) + std::get<2>(pit_info));
    TrapProgramInfoTable pit = *orig_pit; // Need to copy it here, since elf_end releases it
    if (pit.num_sections != 0)
       errx(EX_USAGE, "Binary already contains full ProgramInfoTable structure");
    if (dt_init)
        pit.orig_dt_init = dt_init->dyn_section.d_un.d_ptr;
    else
        pit.orig_dt_init = 0;
    pit.orig_entry = elf_hdr.e_entry;

    // Find executable sections in the binary (.text/.plt/others)
    // then copy them over to the PIT
    pit.num_sections = TRAP_NUM_SECTIONS;
    for (size_t i = 0; i < TRAP_NUM_SECTIONS; i++) {
        auto sec_info = FindSectionByName(e, kExecSections[i][0]);
        if (sec_info.first != nullptr) {
            pit.sections[i].start = sec_info.second.sh_addr;
            pit.sections[i].size = sec_info.second.sh_size;
        }
        auto trap_sec_info = FindSectionByName(e, kExecSections[i][1]);
        if (trap_sec_info.first != nullptr) {
            pit.sections[i].trap = trap_sec_info.second.sh_addr;
            pit.sections[i].trap_size = trap_sec_info.second.sh_size;
        }
    }

    // Set the new entry point addresses
    auto entry_trampoline_sym = FindSymbol(e, kEntryTrampolineName);
    auto init_trampoline_sym  = FindSymbol(e, kInitTrampolineName);
    elf_hdr.e_entry = entry_trampoline_sym.st_value;
    auto new_dt_init = static_cast<ArchPointer>(init_trampoline_sym.st_value);

    // Find export trampolines
    auto xptramp_info = FindSectionByName(e, ".xptramp");
    DynamicSymbolMap dyn_sym_map;
    ExportTrampolineVector xptramp_vec;
    size_t xptramp_shndx = 0;
    if (xptramp_info.first != nullptr) {
        pit.xptramp_start = xptramp_info.second.sh_addr;
        pit.xptramp_size  = xptramp_info.second.sh_size;
        dyn_sym_map = FindDynamicSymbols(e);
        xptramp_vec = FindExportTrampolines(e, xptramp_info);
        xptramp_shndx = elf_ndxscn(xptramp_info.first);
    }

    // Update the ELF header, then write it out
    // There's some pretty ugly behavior from libelf here:
    // if we let it handle the layout, it mis-aligns the data sections
    // It also doesn't seem to update the contents correctly,
    // so we do that manually
    elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT);
    gelf_update_ehdr(e, &elf_hdr);
    if (elf_update(e, ELF_C_WRITE) <= 0)
        errx(EX_SOFTWARE, "Couldn't update ELF file: %s", elf_errmsg(-1));
    elf_end(e);

    // FIXME: libelf shenanigans force us to
    // write data out to the file manually
    // 1) DT_INIT inside .dynamic
    if (dt_init) {
        printf("writing new DT_INIT: 0x%lu\n", new_dt_init);
        lseek(fd, dt_init_ofs, SEEK_SET);
        bytes_written = write(fd, &new_dt_init, sizeof(new_dt_init));
    }
    // 2) The ProgramInfoTable
    lseek(fd, pit_ofs, SEEK_SET);
    bytes_written = write(fd, &pit, sizeof(pit));
    // 3) Exported symbols
    WriteExportSymbols(fd, xptramp_info, xptramp_vec, xptramp_shndx, dyn_sym_map);
    close(fd);
    return 0;
}