Self-mutating C (x86_64) As a learning exercise I wrote a short C program that changes the instructions of a function at runtime in order to execute a shell. It's obviously dependent on x86_64 architecture and Linux (for the syscall number). Indeed, it does start a shell when I run it. I was told to post it here by someone on StackOverflow so what I'm wondering is if there is anything that I'm overlooking in the overall concept or if anything can be improved?

For the sake of brevity, below is only the final product. I wrote up a much longer explanation of the whole process on my blog, but I'm only concerned about the code below, not my long explanation of it.

#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;
#include &lt;errno.h&gt;
#include &lt;string.h&gt;
#include &lt;sys/mman.h&gt;

void foo(void);
int change_page_permissions_of_address(void *addr);

int main(void) {
    void *foo_addr = (void*)foo;

    // Change the permissions of the page that contains foo() to read, write, and execute
    // This assumes that foo() is fully contained by a single page
    if(change_page_permissions_of_address(foo_addr) == -1) {
        fprintf(stderr, "Error while changing page permissions of foo(): %s\n", strerror(errno));
        return 1;
    }

    puts("Calling foo");
    foo();

    char shellcode[] =
        "\x48\x31\xd2"                              // xor    %rdx, %rdx
        "\x48\x31\xc0"                              // xor    %rax, %rax
        "\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00"  // mov    $0x68732f6e69622f2f, %rbx
        "\x53"                                      // push   %rbx
        "\x48\x89\xe7"                              // mov    %rsp, %rdi
        "\x50"                                      // push   %rax
        "\x57"                                      // push   %rdi 
        "\x48\x89\xe6"                              // mov    %rsp, %rsi 
        "\xb0\x3b"                                  // mov    $0x3b, %al
        "\x0f\x05";                                 // syscall

    // Careful with the length of the shellcode here depending on what is after foo
    memcpy(foo_addr, shellcode, sizeof(shellcode));

    puts("Calling foo");
    foo();

    return 0;
}

void foo(void) {
    int i=0;
    i++;
    printf("i: %d\n", i);
}

int change_page_permissions_of_address(void *addr) {
    // Move the pointer to the page boundary
    int page_size = getpagesize();
    addr -= (unsigned long)addr % page_size;

    if(mprotect(addr, page_size, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) {
        return -1;
    }

    return 0;
}
There's one small bug in your code here:

memcpy(foo_addr, shellcode, sizeof(shellcode));


This copies the contents of shellcode, but being a string literal, shellcode includes a null terminator and sizeof(shellcode) is equal to 30, not 29. You should replace this line with:

memcpy(foo_addr, shellcode, sizeof(shellcode) - 1);