Skip to content

Instantly share code, notes, and snippets.

@RobinDavid
Created February 18, 2017 23:22
Show Gist options
  • Save RobinDavid/65007e45d5a76cb2c0ca6152ed5fa841 to your computer and use it in GitHub Desktop.
Save RobinDavid/65007e45d5a76cb2c0ca6152ed5fa841 to your computer and use it in GitHub Desktop.
Changing the right on the text section to make it writeable
#define _GNU_SOURCE
#include <unistd.h>
#include <dlfcn.h>
#include <sys/mman.h>
#include <link.h>
#include <errno.h>
/*
- info: pointer to a dl_phdr_info {
ElfW(Addr) dlpi_addr; // Base address of object
const char *dlpi_name; // (Null-terminated) name of object
const ElfW(Phdr) *dlpi_phdr; // Pointer to array of ELF program headers for this object
ElfW(Half) dlpi_phnum; // # of items in dlpi_phdr
}
- size: size of the dl_phdr_info
- data: whatever data sent to dl_iterate_phdr
With:
typedef struct {
Elf32_Word p_type; /: Segment type
Elf32_Off p_offset; // Segment file offset
Elf32_Addr p_vaddr; // Segment virtual address
Elf32_Addr p_paddr; // Segment physical address
Elf32_Word p_filesz; // Segment size in file
Elf32_Word p_memsz; // Segment size in memory
Elf32_Word p_flags; // Segment flags
Elf32_Word p_align; // Segment alignment
} Elf32_Phdr;
*/
static int do_write_protect_text(struct dl_phdr_info *info, size_t size, void *data)
{
const int protect = (data) ? PROT_READ | PROT_EXEC : PROT_READ | PROT_WRITE | PROT_EXEC;
size_t page;
size_t i;
page = sysconf(_SC_PAGESIZE);
if (size < sizeof (struct dl_phdr_info))
return ENOTSUP;
/* Ignore libraries. */
if (info->dlpi_name && info->dlpi_name[0] != '\0')
return 0;
/* Loop over each header. */
for (i = 0; i < (size_t)info->dlpi_phnum; i++)
if ((info->dlpi_phdr[i].p_flags & PF_X)) {
size_t ptr = (size_t)info->dlpi_phdr[i].p_vaddr;
size_t len = (size_t)info->dlpi_phdr[i].p_memsz;
/* Start at the beginning of the relevant page, */
if (ptr % page) {
len += ptr % page;
ptr -= ptr % page;
}
/* and use full pages. */
if (len % page)
len += page - (len % page);
/* Change protections. Ignore unmapped sections. */
if (mprotect((void *)ptr, len, protect))
if (errno != ENOMEM)
return errno;
}
return 0;
}
int write_protect_text(int protect)
{
int result;
result = dl_iterate_phdr(do_write_protect_text, (void *)(long)protect);
if (result)
errno = result;
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment