Created
February 18, 2017 23:22
-
-
Save RobinDavid/65007e45d5a76cb2c0ca6152ed5fa841 to your computer and use it in GitHub Desktop.
Changing the right on the text section to make it writeable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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