Created
October 25, 2015 16:59
-
-
Save mniip/2c94874016ce263b37a4 to your computer and use it in GitHub Desktop.
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
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <malloc.h> | |
#include <sys/auxv.h> | |
char const *default_path = "/bin/sh"; | |
char const *const default_argv[] = {"/bin/sh", "-", NULL}; | |
char const *const default_envp[] = {NULL}; | |
#define EXECVE_X86 11 | |
/* Execute a 32bit execve syscall from a 64-bit context */ | |
uint32_t execve_32(uint32_t path, uint32_t argv, uint32_t envp) | |
{ | |
uint32_t r; | |
asm volatile("int $0x80" : "=a"(r) : "a"(EXECVE_X86), "b"(path), "c"(argv), "d"(envp)); | |
return r; | |
} | |
/* Allocate a chunk of space in 32bit-representable memory */ | |
void *alloc_low(size_t size) | |
{ | |
mallopt(M_MMAP_MAX, 0); | |
void *ptr = malloc(size); | |
mallopt(M_MMAP_MAX, 65536); | |
if(ptr >= (void *)0x100000000ULL) | |
{ | |
printf("[-] malloc could not allocate a low address: %p\n", ptr); | |
exit(EXIT_FAILURE); | |
} | |
return ptr; | |
} | |
/* Copy a string into 32bit-representable memory */ | |
char *copy_string_low(char const *string) | |
{ | |
char *dest = alloc_low(strlen(string) + 1); | |
strcpy(dest, string); | |
#ifdef DEBUG | |
printf("[*] Copied string '%s'@%p to %08x\n", string, string, (uint32_t)(uintptr_t)dest); | |
#endif | |
return dest; | |
} | |
/* Copy a list of strings into 32bit-representable memory and produce a list of 32-bit pointers */ | |
uint32_t *copy_list_low(char const *const strings[]) | |
{ | |
size_t length = 0; | |
while(strings[length]) | |
length++; | |
uint32_t *dest = alloc_low((length + 1) * sizeof(uint32_t)); | |
size_t i; | |
for(i = 0; i < length; i++) | |
dest[i] = (uint32_t)(uintptr_t)copy_string_low(strings[i]); | |
dest[length] = 0; | |
#ifdef DEBUG | |
printf("[*] Copied list %p (%ld items) to %08x\n", strings, length, (uint32_t)(uintptr_t)dest); | |
#endif | |
return dest; | |
} | |
void free_list(uint32_t *list) | |
{ | |
size_t i; | |
for(i = 0; list[i]; i++) | |
free((void *)(uintptr_t)list[i]); | |
free(list); | |
} | |
/* Wrapper for execve_32 that moves argv and envp into 32bit-representable locations */ | |
uint32_t execve_wrapped(char const *path, char const *const argv[], char const *const envp[]) | |
{ | |
uint32_t path_wrapped = (uint32_t)(uintptr_t)copy_string_low(path); | |
uint32_t argv_wrapped = (uint32_t)(uintptr_t)copy_list_low(argv); | |
uint32_t envp_wrapped = (uint32_t)(uintptr_t)copy_list_low(envp); | |
uint32_t r = execve_32(path_wrapped, argv_wrapped, envp_wrapped); | |
free((void *)(uintptr_t)path_wrapped); | |
free_list((void *)(uintptr_t)argv_wrapped); | |
free_list((void *)(uintptr_t)envp_wrapped); | |
return r; | |
} | |
int main(int argc, char const *const argv[], char const *const envp[]) | |
{ | |
char *platform = (char *)getauxval(AT_PLATFORM); | |
if(strcmp(platform, "x86_64")) | |
{ | |
printf("[-] platform is '%s', x86_64 required\n", platform); | |
return EXIT_FAILURE; | |
} | |
printf("[+] platform is '%s'\n", platform); | |
char const *rpath = default_path; | |
char const *const *rargv = default_argv; | |
char const *const *renvp = default_envp; | |
if(argc > 1) | |
{ | |
rpath = argv[1]; | |
rargv = argv + 1; | |
renvp = envp; | |
} | |
int result = execve_wrapped(rpath, rargv, renvp); | |
printf("[-] Execve returned: %d (%s)\n", result, strerror(-result)); | |
return EXIT_FAILURE; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment