Skip to content

Instantly share code, notes, and snippets.

@interfector
Created April 30, 2014 22:07
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/4d0c855ae9799bb68783 to your computer and use it in GitHub Desktop.
Save interfector/4d0c855ae9799bb68783 to your computer and use it in GitHub Desktop.
process memory control
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <memory.h>
#include <asm/unistd.h>
#include <sys/user.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <dirent.h>
#include <dlfcn.h>
#define _DEBUG
#define CH_BLOCK 40
#define die(i,p) do{ perror(p); exit(i); }while(0)
#define _die(i,p) do{ puts(p); exit(i); }while(0)
#define freeMap(m,c) do{ for(i = 0;i < c;i++) free(m[i].chunk); free(m); }while(0)
#define MAX_SIGS 31
struct MemoryMap {
char name[100];
unsigned int start;
unsigned int size;
unsigned int offset;
char perms[5];
unsigned int prot, flags;
unsigned char* chunk;
};
struct FileD {
char path[100];
char linked[100];
struct stat fst;
struct dirent* fp;
};
struct MemoryMap* parseMap(int, int*);
FILE* memfp = NULL;
void
modReg( struct user_regs_struct* regs, char* reg, char* value )
{
unsigned int addr = strtoll( value,NULL,16 );
if(!strcasecmp(reg, "eax"))
regs->eax = addr;
else if(!strcasecmp(reg, "ebx"))
regs->ebx = addr;
else if(!strcasecmp(reg, "ecx"))
regs->ecx = addr;
else if(!strcasecmp(reg, "edx"))
regs->edx = addr;
else if(!strcasecmp(reg, "esp"))
regs->esp = addr;
else if(!strcasecmp(reg, "ebp"))
regs->ebp = addr;
else if(!strcasecmp(reg, "esi"))
regs->esi = addr;
else if(!strcasecmp(reg, "edi"))
regs->edi = addr;
else if(!strcasecmp(reg, "eflags"))
regs->eflags = addr;
else if(!strcasecmp(reg, "eip"))
regs->eip = addr;
}
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));
}
struct FileD*
parseFd(int pid, int* count)
{
char path[1024];
DIR* dp = NULL;
struct dirent* ep;
struct FileD* fds = malloc(sizeof(struct FileD) * CH_BLOCK);
int i = 0;
snprintf(path, sizeof(path), "/proc/%d/fd/", pid);
if ((dp = opendir(path)) == NULL)
die(7,"fd_opendir");
while((ep = readdir(dp)))
{
if(!strcmp(ep->d_name,".") || !strcmp(ep->d_name,".."))
continue;
if( i % CH_BLOCK )
fds = realloc( fds, sizeof(struct FileD) * (i + CH_BLOCK));
fds[i].fp = malloc( sizeof(struct dirent) );
memcpy( &fds[i].fp, &ep, sizeof(struct dirent) );
snprintf(path, sizeof(path), "/proc/%d/fd/%s", pid, ep->d_name);
memset(fds[i].path, 0, 100 );
strcpy( fds[i].path, path );
if( stat( path, &fds[i].fst ) < 0 )
die(8,"fd_stat");
memset( fds[i].linked, 0, 100 );
if( !S_ISLNK( fds[i].fst.st_mode ) )
{
memset( fds[i].linked, 0, 100 );
readlink( fds[i].path, fds[i].linked, 100 );
}
i++;
}
*count = i;
return fds;
}
void
saveFd( int pid, struct FileD* fds, int fsize )
{
int i;
FILE* fp;
char path[1024] = { 0 };
if( pid == -1 )
strcpy(path, "mem_fd");
else
sprintf(path, "%d/fd", pid);
if((fp = fopen(path, "wb")) == NULL)
die(19,"savefd_open");
#ifdef _DEBUG
printf("[+] Saving file descriptors to %s\n", path );
#endif
for(i = 0;i < fsize;i++)
fwrite( &fds[i], sizeof(struct FileD), 1, fp );
fclose(fp);
}
struct FileD*
loadFd( int pid, int *fcount )
{
int i = 0;
FILE *fp;
char path[1024] = { 0 };
struct FileD* fds = malloc( sizeof(struct FileD) * CH_BLOCK );
if( pid == -1 )
strcpy(path, "mem_fd");
else
sprintf(path, "%d/fd", pid);
if((fp = fopen(path, "rb")) == NULL)
die(20,"loadfd_open");
#ifdef _DEBUG
printf("[+] Loading file descriptors from %s\n", path );
#endif
while(!feof(fp))
{
if( i % CH_BLOCK )
fds = realloc( fds, sizeof(struct FileD) * (i + CH_BLOCK));
fread( &fds[i], sizeof(struct FileD), 1, fp );
i++;
}
*fcount = --i;
return fds;
}
void
parsePerms( char* perms, char* string, unsigned int *prot, unsigned int *flags)
{
if( perms[0] == 'r' )
*prot |= PROT_READ;
if( perms[1] == 'w' )
*prot |= PROT_WRITE;
if( perms[2] == 'x' )
*prot |= PROT_EXEC;
if( perms[3] == 'p' )
*flags |= MAP_PRIVATE;
else if( perms[3] == 's' )
*flags |= MAP_SHARED;
if(!strcmp(string,""))
*flags |= MAP_ANONYMOUS;
}
struct MemoryMap*
parseMap(int pid, int* count)
{
char path[1024];
char buf[1024];
FILE *fp = NULL;
char perms[5] = { 0 };
char string[1024] = { 0 };
unsigned int start, end, offset, dummy;
struct MemoryMap* maps = malloc( sizeof(struct MemoryMap) * CH_BLOCK );
int i = 0;
snprintf(path, sizeof(path), "/proc/%d/maps", pid);
if ((fp = fopen(path, "r")) == NULL)
die(3,"maps_fopen");
snprintf(path, sizeof(path), "/proc/%d/mem", pid);
if ((memfp = fopen(path, "r")) == NULL)
die(4,"mem_fopen");
while(fgets(buf, sizeof(buf), fp))
{
memset( string, 0, 1024 );
sscanf( buf, "%08x-%08x %04s %08x %02d:%02d %d %s", &start, &end, perms, &offset, &dummy, &dummy, &dummy, string );
if( i % CH_BLOCK )
maps = realloc( maps, sizeof(struct MemoryMap) * (i + CH_BLOCK));
memset(maps[i].name, 0, 100 );
strcpy( maps[i].name, string );
maps[i].start = start;
maps[i].size = end - start;
maps[i].offset = offset;
strncpy(maps[i].perms, perms, 5);
parsePerms( perms, string, &maps[i].prot, &maps[i].flags );
if( maps[i].name[0] == 0 )
{
memset(maps[i].name, 0, 100 );
snprintf( maps[i].name, 18, "%08x-%08x", start, end );
maps[i].name[18] = 0;
}
fseek( memfp, maps[i].start, SEEK_SET );
maps[i].chunk = malloc( maps[i].size );
if( fread( maps[i].chunk, 1, maps[i].size, memfp ) != maps[i].size )
die(6,"mem_fread");
i++;
}
*count = i;
fclose(fp);
return maps;
}
unsigned char*
memoryDump( unsigned int start, unsigned int size )
{
unsigned char* chunk;
chunk = malloc( size );
fseek( memfp, start, SEEK_SET );
if( fread( chunk, 1, size, memfp ) != size )
die(6,"mem_fread");
return chunk;
}
int
memorySearch( unsigned char* chunk, unsigned char* key, int csize, int ksize )
{
int i;
for(i = 0;i < csize;i++)
if( !memcmp( chunk+i, key, ksize ) )
return i;
return -1;
}
int*
memorySearch2( unsigned char* chunk, unsigned char* key, int csize, int ksize, int *count )
{
int i;
int* vec = NULL;
int c = 0;
for(i = 0;i < csize;i++)
{
if( !memcmp( chunk+i, key, ksize ) )
{
if( !c )
vec = malloc(sizeof(int) * CH_BLOCK);
if( c % CH_BLOCK )
vec = realloc( vec, sizeof(int) * (c + CH_BLOCK));
vec[c++] = i;
}
}
*count = c;
return vec;
}
struct MemoryMap*
mapSearch( struct MemoryMap* maps, int msize, unsigned char* key, int ksize, int* offset )
{
int i, off;
for(i = 0;i < msize;i++)
{
#ifdef _DEBUG
printf("Testing Map #%d ( 0x%x + 0x%x )\n", i, maps[i].start, maps[i].size );
#endif
if( (off = memorySearch( maps[i].chunk, key, maps[i].size, ksize )) >= 0)
{
*offset = off;
return &maps[i];
}
}
return NULL;
}
struct MemoryMap**
mapSearch2( struct MemoryMap* maps, int msize, unsigned char* key, int ksize, int** offset, int* count )
{
int i, j, k, z, c = 0;
int* vec;
struct MemoryMap** fmp = NULL;
int* nvec;
for(i = 0;i < msize;i++)
{
#ifdef _DEBUG
printf("Testing Map #%d ( 0x%x + 0x%x )\n", i, maps[i].start, maps[i].size );
#endif
if( (vec = memorySearch2( maps[i].chunk, key, maps[i].size, ksize, &j )) )
{
for(k = 0;k < j;k++)
{
if( !c )
{
fmp = malloc(sizeof(struct MemoryMap) * CH_BLOCK);
nvec = malloc(sizeof(int) * CH_BLOCK);
}
if( c % CH_BLOCK )
{
fmp = realloc( fmp, sizeof(struct MemoryMap) * (i + CH_BLOCK));
nvec = realloc( nvec, sizeof(int) * (c + CH_BLOCK));
}
nvec[c] = vec[k];
fmp[c++] = &maps[i];
}
free( vec ); /* BOH */
}
}
*offset = nvec;
*count = c;
return fmp;
}
int
findAddr( struct MemoryMap* maps, int msize, unsigned int addr )
{
int i;
for(i = 0;i < msize;i++)
if( maps[i].start <= addr && addr <= (maps[i].start + maps[i].size) )
return i;
return -1;
}
void
saveMap( struct MemoryMap* maps, int msize, int pid )
{
FILE* fp;
char path[1024] = { 0 };
char* chunk_path;
int i;
sprintf(path, "%d", pid);
mkdir( path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
if( pid == -1 )
strcpy(path, "mem_maps");
else
sprintf(path, "%d/maps", pid);
#ifdef _DEBUG
printf("[+] Saving memory map to %s\n", path );
#endif
if((fp = fopen(path, "wb")) == NULL)
die(9,"savemap_open");
for(i = 0;i < msize;i++)
fwrite( &maps[i], sizeof(struct MemoryMap), 1, fp );
fclose( fp );
if( pid == -1 )
strcpy(path, "mem_chunks");
else
sprintf(path, "%d/chunks", pid);
mkdir( path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH );
chunk_path = strdup(path);
for(i = 0;i < msize;i++)
{
sprintf(path, "%s/%d", chunk_path, i);
#ifdef _DEBUG
printf("[+] Saving %d# Chunk to %s\n", i, path );
#endif
if((fp = fopen(path, "wb")) == NULL)
die(10,"savechunk_open");
fwrite( maps[i].chunk, maps[i].size, 1, fp );
fclose( fp );
}
}
struct MemoryMap*
loadMap( int pid, int* count )
{
FILE* fp;
char path[1024] = { 0 };
struct stat st;
int i = 0, size, offset = 0;
char* chunk_path;
struct MemoryMap* maps = malloc( sizeof(struct MemoryMap) * CH_BLOCK );
if( pid == -1 )
strcpy(path, "mem_maps");
else
sprintf(path, "%d/maps", pid);
#ifdef _DEBUG
printf("[+] Loading memory map from %s\n", path );
#endif
if((fp = fopen(path, "rb")) == NULL)
die(11,"loadmap_open");
if( stat(path,&st) < 0 )
die(12,"loadmap_stat");
size = (int)st.st_size;
while( !feof(fp) )
{
if( i % CH_BLOCK )
maps = realloc( maps, sizeof(struct MemoryMap) * (i + CH_BLOCK));
fread( &maps[i], sizeof(struct MemoryMap), 1, fp );
i++;
}
*count = --i;
if( pid == -1 )
strcpy(path, "mem_chunks");
else
sprintf(path, "%d/chunks", pid);
chunk_path = strdup(path);
for(i = 0;i < *count;i++)
{
sprintf(path, "%s/%d", chunk_path, i );
#ifdef _DEBUG
printf("[+] Loading %d# Chunk from %s\n", i, path );
#endif
maps[i].chunk = malloc( maps[i].size );
if((fp = fopen(path, "rb")) == NULL)
die(13,"loadchunk_open");
if( stat(path,&st) < 0 )
die(14,"loadchunk_stat");
size = (int)st.st_size;
if( maps[i].size != size )
die(15,"loadchunk_size");
fread( maps[i].chunk, size, 1, fp );
fclose( fp );
}
free( chunk_path );
return maps;
}
void
saveRegs( int pid, struct user_regs_struct regs, struct user_fpregs_struct fpregs )
{
FILE* fp;
char path[1024] = { 0 };
if( pid == -1 )
strcpy(path, "mem_regs");
else
sprintf(path, "%d/regs", pid);
#ifdef _DEBUG
printf("[+] Saving regs/fpregs to %s\n", path );
#endif
if((fp = fopen(path, "wb")) == NULL)
die(18,"saveregs_open");
fwrite( &regs, sizeof(struct user_regs_struct), 1, fp );
fwrite( &fpregs, sizeof(struct user_fpregs_struct), 1, fp );
fclose( fp );
}
int
loadRegs( int pid, struct user_regs_struct* regs, struct user_fpregs_struct* fpregs )
{
FILE* fp;
char path[1024] = { 0 };
if( pid == -1 )
strcpy(path, "mem_regs");
else
sprintf(path, "%d/regs", pid);
#ifdef _DEBUG
printf("[+] Loading regs/fpregs from %s\n", path );
#endif
if((fp = fopen(path, "rb")) == NULL)
die(19,"loadregs_open");
fread( regs, sizeof(struct user_regs_struct), 1, fp );
fread( fpregs, sizeof(struct user_fpregs_struct), 1, fp );
fclose( fp );
return 0;
}
void
printRegs( struct user_regs_struct *regs, struct user_fpregs_struct *fpregs )
{
if( regs )
printf("[@] REGS\n"
"[#] %%eip: 0x%.8lx\n"
"[#] %%eax: 0x%.8lx\n"
"[#] %%ebx: 0x%.8lx\n"
"[#] %%ecx: 0x%.8lx\n"
"[#] %%edx: 0x%.8lx\n"
"[#] %%esi: 0x%.8lx\n"
"[#] %%edi: 0x%.8lx\n"
"[#] %%esp: 0x%.8lx\n"
"[#] %%ebp: 0x%.8lx\n"
"[#] eflags: 0x%.8lx\n\n",
regs->eip,
regs->eax, regs->ebx, regs->ecx,
regs->edx, regs->esi, regs->edi,
regs->esp, regs->ebp, regs->eflags);
if( fpregs )
printf("[@] FPREGS:\n"
"[#] cwd: 0x%.8lx\n"
"[#] swd: 0x%.8lx\n"
"[#] twd: 0x%.8lx\n"
"[#] fip: 0x%.8lx\n"
"[#] fcs: 0x%.8lx\n"
"[#] foo: 0x%.8lx\n"
"[#] fos: 0x%.8lx\n",
fpregs->cwd, fpregs->swd, fpregs->twd,
fpregs->fip, fpregs->fcs, fpregs->foo, fpregs->fos );
}
void
banner(void)
{
printf(
"┏━╸╻ ╻╺┳╸┏┳┓┏━┓┏┳┓\n"
"┃ ┗━┫ ┃ ┃┃┃╺━┫┃┃┃\n"
"┗━╸ ╹ ╹ ╹ ╹┗━┛╹ ╹\n");
}
int
main(int argc, char **argv)
{
int pid, mcount = 0, nmcount = 0, i, offset, fcount = 0;
struct user_regs_struct regs;
struct user_fpregs_struct fpregs;
struct MemoryMap* maps = NULL;
struct FileD* fds = NULL;
unsigned int eip;
unsigned int esp, ebp;
banner();
if (argc < 3) {
printf("Usage: %s <mode> <pid>\n", argv[0]);
printf("\nModes:\n"
"help - Print this help\n"
"save - Save the session of the process\n"
"load - Load the session of the process\n"
"dump - Print infos about session of the process\n"
"search - Search for a pattern into the process memory (running)\n"
"searchdump - Search for a pattern into the dumped file\n"
"fd - Print infos about file descriptors of the process\n"
"findaddr - Print infos about the map linked to the address (running)\n"
"findaddrdump - Print infos about the map linked to the address in the dumped file\n"
"write - Write a content to a specified address in the process memory (running)\n"
"writedump - Write a content to a specified address in the dumped file\n"
"read - Read a content from a specified address in the process memory (running)\n"
"readdump - Read a content from a specified address in the dumped file\n"
"disas - Disassembly a content from a specified address in the dumped file\n"
"findcall - Search for calls (byte 0xe8) and check if it's a real call\n"
"findcave - Search for memory map useable as caveat\n"
"restore - Try to restore the process image from a pid to another\n"
"set - Sets register in the dumped file\n");
return 1;
}
pid = (int)atoi(argv[2]);
if(!strcmp(argv[1],"save") || !strcmp(argv[1],"load") || !strcmp(argv[1],"search") || !strcmp(argv[1],"search2") || !strcmp(argv[1],"fd") || !strcmp(argv[1],"findaddr") || !strcmp(argv[1],"write") || !strcmp(argv[1],"read"))
{
if (ptrace( PTRACE_ATTACH, pid, NULL, NULL ))
die(1, "ptrace_attach");
waitpid(pid, NULL, 0);
maps = parseMap( pid, &mcount );
fds = parseFd( pid, &fcount );
if(ptrace( PTRACE_GETREGS, pid, &regs, &regs ) < 0)
die(2, "ptrace_getregs");
if (ptrace(PTRACE_GETFPREGS, pid, &fpregs, &fpregs) < 0)
die(3, "ptrace_getfpregs");
}
if( !strcmp(argv[1], "save" ) )
{
saveMap( maps, mcount, pid );
saveRegs( pid, regs, fpregs );
saveFd( pid, fds, fcount );
} else if( !strcmp(argv[1],"load") ) {
struct MemoryMap* m = loadMap( pid, &nmcount );
for(i = 0;i < nmcount;i++)
memorySet(pid, maps[i].start, m[i].chunk, m[i].size);
eip = regs.eip;
esp = regs.esp;
ebp = regs.ebp;
loadRegs( pid, &regs, &fpregs );
printRegs( &regs, &fpregs );
ptrace( PTRACE_SETREGS, pid, &regs, &regs );
} else if( !strcmp(argv[1],"dump") ) {
struct MemoryMap* m = loadMap( pid, &nmcount );
for(i = 0;i < nmcount;i++)
printf("%08x-%08x %04s 0x%08x %s\n", m[i].start, m[i].start + m[i].size, m[i].perms, m[i].offset, m[i].name);
loadRegs( pid, &regs, &fpregs );
printRegs( &regs, &fpregs );
fds = loadFd( pid, &fcount );
for(i = 0;i < fcount;i++)
printf("%s : %s\n", fds[i].path, (fds[i].linked) ? fds[i].linked : "(null)" );
} else if( !strncmp(argv[1],"search2",7) ) {
if( !argv[3] )
_die(1, "[-] Search2: <pid> <string> [<len>]");
puts("[+] Searching(2) in memory maps...");
if(!strcmp(argv[1],"search2dump"))
maps = loadMap( pid, &nmcount );
int srcount, *sroff;
struct MemoryMap** map = mapSearch2( maps, nmcount, argv[3], (argv[4]) ? atoi(argv[4]) : strlen(argv[3]), &sroff, &srcount );
if( map )
{
for (i = 0; i < srcount; i++)
{
printf("%08x-%08x %04s 0x%08x %s\n", map[i]->start, map[i]->start + map[i]->size, map[i]->perms, map[i]->offset, map[i]->name);
printf("[*] Address: 0x%x\n\n", map[i]->start + sroff[i] );
}
free(map);
}
} else if( !strncmp(argv[1],"search",6) ) {
if( !argv[3] )
_die(1, "[-] Search: <pid> <string> [<len>]");
puts("[+] Searching in memory maps...");
if(!strcmp(argv[1],"searchdump"))
maps = loadMap( pid, &nmcount );
struct MemoryMap* map = mapSearch( maps, nmcount, argv[3], (argv[4]) ? atoi(argv[4]) : strlen(argv[3]), &offset );
if( map )
{
printf("%08x-%08x %04s 0x%08x %s\n", map->start, map->start + map->size, map->perms, map->offset, map->name);
printf("[*] Address: 0x%x\n", map->start + offset );
}
} else if( !strcmp(argv[1],"fd") ) {
struct FileD* fds = parseFd( pid, &fcount );
for(i = 0;i < fcount;i++)
printf("%s : %s\n", fds[i].path, (fds[i].linked) ? fds[i].linked : "(null)" );
} else if( !strncmp(argv[1],"findaddr",8) ) {
if( !argv[3] )
_die(1, "[-] Findaddr: <pid> <addr>");
puts("[+] Searching in memory maps...");
if(!strcmp(argv[1],"findaddrdump"))
maps = loadMap( pid, &nmcount );
int moff = findAddr( maps, nmcount, strtoll(argv[3],NULL,16) );
if( moff >= 0 )
{
struct MemoryMap* map = &maps[moff];
printf("[*] Found in #%d map...\n", moff );
printf("%08x-%08x %04s 0x%08x %s\n", map->start, map->start + map->size, map->perms, map->offset, map->name);
}
} else if( !strncmp(argv[1],"write",5) ) {
if( argc < 5 )
_die(1, "[-] Write: <pid> <addr> <string> [<len>]");
unsigned int addr = strtoll( argv[3],NULL,16 );
if(!strcmp(argv[1],"writedump"))
maps = loadMap( pid, &nmcount );
int moff = findAddr( maps, nmcount, addr );
if( moff < 0 )
{
printf("[-] Cannot find 0x%x in any maps.\n", addr);
return 1;
}
struct MemoryMap* map = &maps[moff];
if(!strcmp(argv[1],"writedump"))
{
FILE* fp;
char path[1024] = { 0 };
sprintf(path, "%d/chunks/%d", pid, moff );
if((fp = fopen(path, "r+b")) == NULL)
die(17,"writedump_open");
fseek( fp, (addr - map->start), SEEK_SET);
fwrite( argv[4], (argv[5]) ? atoi(argv[5]) : strlen(argv[4]), 1, fp );
fclose( fp );
printf("[*] Data written to 0x%x in #%d map\n", addr, moff );
} else {
memorySet(pid, addr, argv[4], (argv[5]) ? atoi(argv[5]) : strlen(argv[4]));
printf("[*] Data written to 0x%x.\n", addr);
ptrace( PTRACE_SETREGS, pid, &regs, &regs );
ptrace( PTRACE_CONT, pid, 0, 0 );
}
} else if( !strncmp(argv[1],"read",4)) {
if( argc < 5 )
_die(1, "[-] Read: <pid> <addr> <len>");
int addr = strtoll( argv[3],NULL,16 );
if(!strcmp(argv[1],"readdump"))
maps = loadMap( pid, &nmcount );
int moff = findAddr( maps, nmcount, addr );
if( moff < 0 )
{
printf("[-] Cannot find 0x%x in any maps.\n", addr);
return 1;
}
struct MemoryMap* map = &maps[moff];
if(!strcmp(argv[1],"readdump"))
{
FILE* fp;
char path[1024] = { 0 };
unsigned char* data;
int size;
size = atoi( argv[4] );
sprintf(path, "%d/chunks/%d", pid, moff );
if((fp = fopen(path, "rb")) == NULL)
die(18,"readdump_open");
fseek( fp, (addr - map->start), SEEK_SET);
data = malloc( size );
fread( data, size, 1, fp );
fclose( fp );
if(!strcmp(argv[1],"readdump"))
{
printf("[*] Data read from 0x%x in #%d map\nData:\n\n", addr, moff );
for (i = 0; i < size; i++)
{
if(i && !(i % 16))
putchar('\n');
printf("\\x%02x", (unsigned char)data[i] );
}
putchar('\n');
}
free(data);
}
} else if( !strcmp(argv[1],"findcall") ) {
if( argc < 4 )
_die(1, "[-] Findcall: <pid> <# map>");
int arg = atoi(argv[3]);
char exe_path[1024] = { 0 };
sprintf(exe_path, "/proc/%d/exe", pid);
maps = loadMap( pid, &nmcount );
if( arg < 0 || arg >= nmcount )
_die(1, "[-] Findcall: invalid map number.");
struct MemoryMap* map = &maps[arg];
for (i = 0; i < map->size; i++)
{
if( map->chunk[i] == 0xe8 )
{
int offset = *(int*)(map->chunk + i + 1);
int eip = map->start + i + 5;
int endpoint = eip + offset;
int moff = findAddr( maps, nmcount, endpoint );
if( moff >= 0 )
{
struct MemoryMap* endmap = &maps[moff];
if( !memcmp(endmap->chunk + (endpoint - endmap->start), "\x55\x89\xe5", 3) ||
(!memcmp(endmap->chunk + (endpoint - endmap->start), "\xff\x25", 2) ) &&
*(endmap->chunk + (endpoint - endmap->start) + 6) == 0x68 &&
*(endmap->chunk + (endpoint - endmap->start) + 11) == 0xe9) {
printf("- 0x%08x calls 0x%08x (return to 0x%08x).\n", map->start + i, endpoint, map->start + i + 5 );
}
}
}
}
} else if( !strcmp(argv[1],"restore") ) {
if( argc < 4 )
_die(1, "[-] Restore: <old pid> <new pid>");
struct MemoryMap* m = loadMap( pid, &nmcount );
int npid = atoi(argv[3]);
if (ptrace( PTRACE_ATTACH, npid, NULL, NULL ))
die(1, "ptrace_attach");
waitpid(npid, NULL, 0);
maps = parseMap( npid, &mcount );
if( mcount != nmcount )
_die(1, "[-] Restore: wrong number of VMAs.");
for(i = 0;i < nmcount;i++)
memorySet(npid, maps[i].start, m[i].chunk, m[i].size);
loadRegs( pid, &regs, &fpregs );
int moff = findAddr( m, nmcount, regs.eip );
struct MemoryMap* map = &m[moff];
if( map->start > maps[moff].start )
{
unsigned int offset = map->start - maps[moff].start;
printf("M#1: %x\tM#2: %x\nOffset: %x\n", map->start, maps[moff].start, offset);
regs.eip -= offset;
printf("Eip: %x\n", regs.eip );
}
printRegs( &regs, &fpregs );
ptrace( PTRACE_SETREGS, npid, &regs, &regs );
} else if( !strncmp(argv[1],"set",3) ) {
if( argc < 5 )
_die(1, "[-] Set: <pid> <register|signum> <value>");
if(!strcmp(argv[1],"set"))
{
loadRegs( pid, &regs, &fpregs );
printf("[#] OLD REGS:\n");
printRegs( &regs, NULL );
modReg( &regs, argv[3], argv[4] );
saveRegs( pid, regs, fpregs );
printf("[#] NEW REGS:\n");
printRegs( &regs, NULL );
} else if(!strcmp(argv[1],"setsig")) {
}
} else {
printf("Usage: %s <mode> <pid>\n", argv[0]);
exit(1);
}
if( mcount )
freeMap( maps, mcount );
if( fcount )
free( fds );
ptrace( PTRACE_DETACH, pid, NULL, NULL );
if( memfp )
fclose( memfp );
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment