HiveBrain v1.2.0
Get Started
← Back to all entries
patterncMinor

Self-mutating C (x86_64)

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
mutatingx86_64self

Problem

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
#include
#include
#include
#include

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 depend

Solution

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);

Code Snippets

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

Context

StackExchange Code Review Q#38662, answer score: 7

Revisions (0)

No revisions yet.