Created
April 30, 2014 22:07
-
-
Save interfector/4d0c855ae9799bb68783 to your computer and use it in GitHub Desktop.
process memory control
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 <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( ®s, 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, ®s, ®s ) < 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, ®s, &fpregs ); | |
printRegs( ®s, &fpregs ); | |
ptrace( PTRACE_SETREGS, pid, ®s, ®s ); | |
} 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, ®s, &fpregs ); | |
printRegs( ®s, &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, ®s, ®s ); | |
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, ®s, &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( ®s, &fpregs ); | |
ptrace( PTRACE_SETREGS, npid, ®s, ®s ); | |
} else if( !strncmp(argv[1],"set",3) ) { | |
if( argc < 5 ) | |
_die(1, "[-] Set: <pid> <register|signum> <value>"); | |
if(!strcmp(argv[1],"set")) | |
{ | |
loadRegs( pid, ®s, &fpregs ); | |
printf("[#] OLD REGS:\n"); | |
printRegs( ®s, NULL ); | |
modReg( ®s, argv[3], argv[4] ); | |
saveRegs( pid, regs, fpregs ); | |
printf("[#] NEW REGS:\n"); | |
printRegs( ®s, 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