Skip to content

Instantly share code, notes, and snippets.

@mniip
Created October 25, 2015 16:59
Show Gist options
  • Save mniip/2c94874016ce263b37a4 to your computer and use it in GitHub Desktop.
Save mniip/2c94874016ce263b37a4 to your computer and use it in GitHub Desktop.
#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