I'm trying to modify a value in the .text segment using protect to give me writing access:
int pageSize = sysconf(_SC_PAGE_SIZE);
int *toModify = (int *)(foo+5);
if (mprotect(toModify, pageSize, PROT_WRITE) < 0 ) {
perror("mprotect failed with error:");
return -1;
}
*toModify = 5;
printf("Modify :%i",foo());
mprotect does never work. It always returns an mprotect failed with error:: Invalid argument
error.
foo is a method that returns an int that is stored 5bytes after the function(thats the reason for foo+5)
I have executed the following code on OS X 10.9, and it appears to have the desired behavior. The output is “foo returns 23.”
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
extern int foo(void);
int main(void)
{
// New value to write into foo+5.
int NewValue = 23;
// Find page size for this system.
size_t pagesize = sysconf(_SC_PAGESIZE);
// Calculate start and end addresses for the write.
uintptr_t start = (uintptr_t) &foo + 5;
uintptr_t end = start + sizeof NewValue;
// Calculate start of page for mprotect.
uintptr_t pagestart = start & -pagesize;
// Change memory protection.
if (mprotect((void *) pagestart, end - pagestart,
PROT_READ | PROT_WRITE | PROT_EXEC))
{
perror("mprotect");
exit(EXIT_FAILURE);
}
// Write new bytes to desired location.
memcpy((void *) start, &NewValue, sizeof NewValue);
// Some systems could require an invalidate of instruction cache here.
// Try modified function.
printf("foo returns %d.\n", foo());
return 0;
}
For foo
, I used this assembly code. Both sources were built with cc -arch i386
.
.globl _foo
_foo:
nop
nop
nop
nop
mov $42, %eax
ret
You should modify code this way only as a learning exercise and not use it in any deployed application.