Skip to content

Instantly share code, notes, and snippets.

@interfector
Created April 30, 2014 21:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save interfector/0fd830ea799b2f5f7c96 to your computer and use it in GitHub Desktop.
Save interfector/0fd830ea799b2f5f7c96 to your computer and use it in GitHub Desktop.
shared object injector
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <memory.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <dlfcn.h>
//#define _DEBUG
#define die(i,p) do{ perror(p); exit(i); }while(0)
#define push( addr, data ) addr -= 4; \
ptrace( PTRACE_POKETEXT, pid, addr, data );
void
memorySet(int pid, long addr, unsigned char* data, int size)
{
int i;
for (i = 0; i < size; i++)
ptrace (PTRACE_POKETEXT, pid, addr + i, *(int*) (data + i));
}
int
inject_memory(int pid, int dlopen_addr, char* libp)
{
long addr;
struct user_regs_struct regs;
struct user_regs_struct saved_regs;
long path;
if (ptrace( PTRACE_ATTACH, pid, NULL, NULL ))
die(4, "ptrace_attach");
waitpid(pid, NULL, 0);
if(ptrace( PTRACE_GETREGS, pid, &regs, &regs ))
die(5, "ptrace_getregs");
memcpy( &saved_regs, &regs, sizeof( regs ) );
#ifdef _DEBUG
printf("[#] Current %%eax: 0x%.8lx\n"
"[#] Current %%ebx: 0x%.8lx\n"
"[#] Current %%ecx: 0x%.8lx\n"
"[#] Current %%edx: 0x%.8lx\n"
"[#] Current %%esi: 0x%.8lx\n"
"[#] Current %%edi: 0x%.8lx\n"
"[#] Current %%esp: 0x%.8lx\n"
"[#] Current %%ebp: 0x%.8lx\n"
"[#] Current eflags: 0x%.8lx\n",
regs.eax, regs.ebx, regs.ecx,
regs.edx, regs.esi, regs.edi,
regs.esp, regs.ebp, regs.eflags );
#endif
printf("@ Current %%eip : 0x%.8lx\n", regs.eip);
printf("@ Current %%esp : 0x%.8lx\n", regs.esp);
addr = regs.esp - 1024;
memorySet( pid, addr, libp, strlen(libp) + 1 );
path = addr;
printf("@ Pushing arguments to 0x%.8lx\n", addr);
push( addr, regs.eip );
push( addr, 0x0badc0de );
push( addr, 0x00001102 );
push( addr, path );
push( addr, regs.eip );
regs.esp = addr;
regs.eip = (long)dlopen_addr + 2; /* two bytes(nops) subtracted by the kernel */
printf("@ Jumping to dlopen address...\n");
ptrace( PTRACE_SETREGS, pid, &regs, &regs );
if (ptrace(PTRACE_CONT, pid, NULL, NULL) < 0)
die(6, "ptrace_cont");
waitpid(pid, NULL, 0);
printf("@ Restore regs...\n", regs.eip);
ptrace( PTRACE_SETREGS, pid, NULL, &saved_regs );
ptrace( PTRACE_DETACH, pid, NULL, NULL );
return 0;
}
unsigned int
find_libc(int pid)
{
char path[1024];
char buf[1024], *start = NULL, *p = NULL;
unsigned long addr = NULL;
FILE *fp = NULL;
snprintf(path, sizeof(path), "/proc/%d/maps", pid);
if ((fp = fopen(path, "r")) == NULL)
die(3,"fopen");
while(fgets(buf, sizeof(buf), fp))
{
if (!strstr(buf, "r-xp"))
continue;
if (!(p = strstr(buf, "/")))
continue;
if (!strstr(p, "/libc-"))
continue;
start = strtok(buf, "-");
addr = (unsigned int)strtoul(start, NULL, 16);
break;
}
fclose(fp);
return addr;
}
int
main(int argc, char **argv)
{
unsigned int dlopen_addr = NULL;
unsigned int dlopen_mode = NULL;
unsigned int mylibc_addr = 0;
unsigned int pidlibc_addr = 0;
int pid;
unsigned char *shellcode;
int sh_size = 0;
int dlopen_offset = 0;
if (argc < 3) {
printf("Usage: %s <pid> <so path>\n", argv[0]);
return 1;
}
mylibc_addr = find_libc(getpid());
pid = (int)atoi(argv[1]);
pidlibc_addr = find_libc( pid );
#ifdef _DEBUG
printf("[#] PID: %d\n"
"[#] My libc address: 0x%.8lx\n"
"[#] %d's libc address: 0x%.8lx\n",
pid, mylibc_addr, pid, pidlibc_addr );
#endif
printf("Trying obtaining __libc_dlopen_mode address...");
dlopen_mode = dlsym(NULL, "__libc_dlopen_mode");
if (dlopen_mode)
dlopen_offset = dlopen_mode - mylibc_addr;
else
die(2, "dlsym");
printf("\t%p\n@ Offset: 0x%x\n", dlopen_mode, dlopen_offset);
dlopen_addr = pidlibc_addr + dlopen_offset;
printf("@ dlopen address: %p\n", dlopen_addr );
inject_memory(pid, dlopen_addr, argv[2]);
printf("\n[+] Injection done!\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment