Thread: Self reading/modification

  1. #1
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733

    Self reading/modification

    I managed to get my gasp app working on it's parent process but now I need some help with getting it to access it's own memory (figures that it would be easier to get the parent process memory than it's own), once I have access on both I will test modifying the memory via a string I will print both before and after the expected modification to check it has been modified, anyways the code I'm using to open process memory is below, tell me if you see any problems and/or know of what to do when trying to access own memory, I might end up making specialized functions for self modification at this rate (which I would rather not).
    Code:
    void* proc_handle_wait( void *data ) {
    	proc_handle_t *handle = data;
    	int status = 0;
    	(void)pthread_detach( handle->thread );
    	
    	while ( handle->waiting ) {
    		waitpid(handle->notice.entryId,&status,0);
    		if ( WIFEXITED(status) || WIFSIGNALED(status) ) {
    			handle->running = 0;
    			break;
    		}
    	}
    	
    	handle->waiting = 0;
    	return data;
    }
    proc_handle_t* proc_handle_open( int *err, int pid )
    {
    	char path[256] = {0};
    	proc_handle_t *handle;
    	long attach_ret = -1;
    	
    #ifdef PTRACE_SEIZE
    	int ptrace_mode = PTRACE_SEIZE;
    #else
    	int ptrace_mode = PTRACE_ATTACH;
    	ERRMSG( ENOSYS,
    		"PTRACE_SEIZE not defined, defaulting to PTRACE_ATTACH");
    #endif
    
    	attach_ret = ptrace( ptrace_mode, pid, NULL, NULL );
    	if ( attach_ret != 0 ) {
    		if ( err ) *err = errno;
    		return NULL;
    	}
    	
    	if ( !(handle = calloc(sizeof(proc_handle_t),1)) ) {
    		if ( err ) *err = errno;
    		return NULL;
    	}
    	
    	if ( !proc_notice_info( err, pid, &(handle->notice) ) ) {
    		proc_handle_shut( handle );
    		return NULL;
    	}
    	
    	(void)sprintf( path, "/proc/%d/maps", pid );
    	if ( (handle->pagesFd = open(path,O_RDONLY)) < 0 ) {
    		proc_handle_shut( handle );
    		if ( err ) *err = errno;
    		ERRMSG( errno, "Couldn't open maps file" );
    		return NULL;
    	}
    	
    	(void)sprintf( path, "/proc/%d/mem", pid );
    	if ( (handle->rdMemFd = open(path,O_RDONLY)) < 0 ) {
    		proc_handle_shut( handle );
    		if ( err ) *err = errno;
    		ERRMSG( errno, "Couldn't open mem file in read only mode" );
    		return NULL;
    	}
    	
    	handle->wrMemFd = open(path,O_WRONLY);
    	handle->running = 1;
    #if 0
    	if ( pid != (getpid()) ) {
    		if ( pthread_create( &(handle->thread),
    			NULL, proc_handle_wait, handle ) ) {
    			proc_handle_shut( handle );
    			ERRMSG( errno, "Couldn't create pthread to check for SIGKILL" );
    			return NULL;
    		}
    		handle->waiting = 1;
    	}
    #endif
    
    	return handle;
    }
    
    void proc_handle_shut( proc_handle_t *handle ) {
    	/* Used only to prevent segfault from pthread_join, do nothing
    	 * with it */
    	void *data;
    	
    	/* Don't try to close NULL as that will segfault */
    	if ( !handle ) return;
    	
    	/* Ensure thread closes before we release the handle it's using */
    	if ( handle->waiting ) {
    		handle->waiting = 0;
    		(void)pthread_join( handle->thread, &data );
    	}
    	
    	/* Cleanup noticed info */
    	proc_notice_zero( &(handle->notice) );
    	
    	/* None of these need to be open anymore */
    	if ( handle->rdMemFd >= 0 ) close( handle->rdMemFd );
    	if ( handle->wrMemFd >= 0 ) close( handle->wrMemFd );
    	if ( handle->pagesFd >= 0 ) close( handle->pagesFd );
    	
    	/* Ensure that even if handle is reused by accident the most that
    	 * can happen is a segfault */
    	(void)memset(handle,0,sizeof(proc_handle_t));
    	
    	/* Ensure none of these are treated as valid in the above scenario*/
    	handle->rdMemFd = handle->wrMemFd = handle->pagesFd = -1;
    	
    	/* No need for the handle anymore */
    	free(handle);
    }
    Edit: gotta go to work so any suggestions or bugs pointed out won't be tried until I get back.
    Last edited by awsdert; 01-31-2020 at 06:36 AM.

  2. #2
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    I managed to avoid specialised functions, one problem however is that I seem to be unable to both modify memory and copy own memory, here's what I have for reading and modifying memory (the gasp_* stuff are just defines to either *64() or *() depending on the system features)
    Code:
    intptr_t proc_change_data(
    	int *err, proc_handle_t *handle,
    	intptr_t addr, void *src, size_t size ) {
    	intptr_t done;
    #ifndef gasp_pwrite
    	gasp_off_t off;
    #endif
    
    	errno = EXIT_SUCCESS;
    	
    	if ( !handle ) {
    		if ( err ) *err = EINVAL;
    		ERRMSG( errno, "Invalid handle" );
    		return 0;
    	}
    	
    	if ( handle->samepid ) {
    		(void)memmove( (void*)addr, src, size );
    		if ( err ) *err = errno;
    		if ( errno != EXIT_SUCCESS )
    			ERRMSG( errno, "Couldn't override VM" );
    		return size;
    	}
    
    #ifdef gasp_pwrite	
    	done = gasp_pwrite( handle->wrMemFd, src, size, addr );
    	if ( done > 0 ) {
    		if ( err ) *err = EXIT_SUCCESS;
    		return done;
    	}
    	if ( err ) *err = errno;
    	if ( errno == EIO )
    		return 0;
    	if ( errno != EXIT_SUCCESS )
    		ERRMSG( errno, "Couldn't override VM" );
    	return done;
    #else
    	off = gasp_lseek( handle->wrMemFd, 0, SEEK_CUR );
    	if ( errno != EXIT_SUCCESS ) {
    		if ( err ) *err = errno;
    		ERRMSG( errno, "Couldn't seek VM address" );
    		return 0;
    	}
    	
    	gasp_lseek( handle->wrMemFd, addr, SEEK_SET );
    	if ( errno != EXIT_SUCCESS ) {
    		if ( err ) *err = errno;
    		ERRMSG( errno, "Couldn't seek VM address" );
    		return 0;
    	}
    	
    	done = gasp_write( handle->wrMemFd, src, size );
    	if ( errno != EXIT_SUCCESS ) {
    		if ( err ) *err = errno;
    		ERRMSG( errno, "Couldn't override VM" );
    		return 0;
    	}
    	
    	gasp_lseek( handle->wrMemFd, off, SEEK_SET );
    #endif
    	return done;
    }
    Edit:
    Just for reference the output of my program:
    Code:
    ./gasp.elf -D HELLO="WORLD"
    gasp = 'gasp'
    Found:
    3B52 'gasp.elf'
    rdMemFd = 5, wrMemFd = 6
    Got address 0x7fca7b8805a8, gasp = 'gasp'
    Got address 0x7fca7b8805b5, gasp = 'gasp'
    Got address 0x7fca7b8805ee, gasp = 'gasp'
    3B53 'private_gasp.el'
    rdMemFd = -1, wrMemFd = -1
    gasp = 'gasp'
    The reason I kept printing the value of gasp is to confirm the change made it's way through
    Last edited by awsdert; 02-01-2020 at 05:35 AM.

  3. #3
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Finally found why I couldn't overwrite it, was on a page without write permissions, will make buffer and copy it to that and try there instead.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Bigint modification - please help
    By grigorianvlad in forum C++ Programming
    Replies: 7
    Last Post: 09-16-2010, 06:21 AM
  2. Hi Help with reading a file and string modification
    By doubty in forum C Programming
    Replies: 3
    Last Post: 08-06-2009, 02:11 AM
  3. Pointer modification
    By simpatico_qa in forum C Programming
    Replies: 1
    Last Post: 05-04-2009, 12:35 PM
  4. Help with code modification
    By DCMann2 in forum C Programming
    Replies: 7
    Last Post: 05-06-2008, 10:33 PM
  5. A little modification to the page
    By ammar in forum A Brief History of Cprogramming.com
    Replies: 12
    Last Post: 12-17-2002, 05:26 AM

Tags for this Thread