Example #1
0
void *readTask(FILE *inputFile){
	Task *task = createTask();
	TaskIdList *list = NULL;
	int endedTasks=-1, metaSize=-1, taskState=-1, id=-1;
	char *metadata = NULL;

	READ_BEGIN(inputFile);

	list = (TaskIdList *)readTaskIdList(inputFile);
	setTaskDependsOnMe(task, list);
	taskIdListDestroy(list);

	list = (TaskIdList *)readTaskIdList(inputFile);
	setTaskMyDeps(task, list);
	taskIdListDestroy(list);
	
	hashIntVoidDeserialize(inputFile, task->children);

	// make the children point to its mother
	HashIntVoidIterator *it = createHashIntVoidIterator(task->children, 0);
	PosHandlerIntVoid pos = hashIntVoidIteratorNext(it, task->children);
	while (pos != NULL) {
		Task *child = posGetValue(pos);
		child->mother = task;
		
		pos = hashIntVoidIteratorNext(it, task->children);
	}
	hashIntVoidIteratorDestroy(it, task->children);

	READ_NUM("id", id);
	setTaskId(task, id);

	READ_NUM("endedTasks", endedTasks);
	setTaskEndedTasks(task, endedTasks);

	READ_NUM("metaSize", metaSize);
	if (metaSize > 0) {
		metadata = malloc(metaSize);
	} else {
		metadata = NULL;	
	}
	READ_BYTES(inputFile, metadata, metaSize);
	setTaskMetadata(task, metadata, metaSize);
	if(metadata != NULL){
		free(metadata);
	}

	READ_NUM("taskState", taskState);
	setTaskState(task, taskState);
	
	DataSpace* dataSpace = createDataSpace();	
	readDataSpace(inputFile, dataSpace);

	setTaskDataSpace(task, dataSpace);
	
	READ_END
	return (void *)task;
}
Example #2
0
bool PCProcess::hideDebugger()
{
	Dyninst::ProcControlAPI::Thread::const_ptr threadPtr_ = pcProc_->threads().getInitialThread();
	if (!threadPtr_)
		return false;
	Address tibPtr = threadPtr_->getThreadInfoBlockAddr();
    if (!tibPtr) {
        return false;
    }

    // read in address of PEB
    unsigned int pebPtr;
    if (!readDataSpace((void*)(tibPtr+48), getAddressWidth(), (void*)&pebPtr, false)) {
        fprintf(stderr, "%s[%d] Failed to read address of Process Environment "
                "Block at 0x%x, which is TIB + 0x30\n", FILE__,__LINE__,tibPtr+48);
        return false;
    }

    // patch up the processBeingDebugged flag in the PEB
    unsigned char flag;
    if (!readDataSpace((void*)(pebPtr+2), 1, (void*)&flag, true)) 
        return false;
    if (flag) {
        flag = 0;
        if (!writeDataSpace((void*)(pebPtr+2), 1, (void*)&flag)) 
            return false;
    }

    //while we're at it, clear the NtGlobalFlag
    if (!readDataSpace((void*)(pebPtr+0x68), 1, (void*)&flag, true)) 
        return false;
    if (flag) {
        flag = flag & 0x8f;
        if (!writeDataSpace((void*)(pebPtr+0x68), 1, (void*)&flag)) 
            return false;
    }

    // clear the heap flags in the PEB
    unsigned int heapBase;
    unsigned int flagWord;
    if (!readDataSpace((void*)(pebPtr+0x18), 4, (void*)&heapBase, true)) 
        return false;

    // clear the flags in the heap itself
    if (!readDataSpace((void*)(heapBase+0x0c), 4, (void*)&flagWord, true)) 
        return false;
    flagWord = flagWord & (~0x50000062);
    if (!writeDataSpace((void*)(heapBase+0x0c), 4, (void*)&flagWord)) 
        return false;
    if (!readDataSpace((void*)(heapBase+0x10), 4, (void*)&flagWord, true)) 
        return false;
    flagWord = flagWord & (~0x40000060);
    if (!writeDataSpace((void*)(heapBase+0x10), 4, (void*)&flagWord)) 
        return false;

    return true;
}
Example #3
0
bool process::loadDYNINSTlib() {
  /* Look for a function we can hijack to forcibly load dyninstapi_rt. 
     This is effectively an inferior RPC with the caveat that we're
     overwriting code instead of allocating memory from the RT heap. 
     (So 'hijack' doesn't mean quite what you might think.) */
  Address codeBase = findFunctionToHijack(this);	

  if( !codeBase ) { return false; }
  
  /* glibc 2.3.4 and higher adds a fourth parameter to _dl_open().
     While we could probably get away with treating the three and four
     -argument functions the same, check the version anyway, since
     we'll probably need to later. */
  bool useFourArguments = true;
  Symbol libcVersionSymbol;
  if( getSymbolInfo( "__libc_version", libcVersionSymbol ) ) {
    char libcVersion[ sizeof( int ) * libcVersionSymbol.size() + 1 ];
	libcVersion[ sizeof( int ) * libcVersionSymbol.size() ] = '\0';
    if( ! readDataSpace( (void *) libcVersionSymbol.addr(), libcVersionSymbol.size(), libcVersion, true ) ) {
      fprintf( stderr, "%s[%d]: warning, failed to read libc version, assuming 2.3.4+\n", __FILE__, __LINE__ );
      }
    else {
      startup_printf( "%s[%d]: libcVersion: %s\n", __FILE__, __LINE__, libcVersion );

      /* We could potentially add a sanity check here to make sure we're looking at 2.3.x. */
      int microVersion = ((int)libcVersion[4]) - ((int)'0');
      if( microVersion <= 3 ) {
	    useFourArguments = false;
        }
      } /* end if we read the version symbol */
    } /* end if we found the version symbol */

  if( useFourArguments ) { startup_printf( "%s[%d]: using four arguments.\n", __FILE__, __LINE__ ); }

  /* Fetch the name of the run-time library. */
  const char DyninstEnvVar[]="DYNINSTAPI_RT_LIB";
        
  if( ! dyninstRT_name.length() ) { // we didn't get anything on the command line
    if (getenv(DyninstEnvVar) != NULL) {
      dyninstRT_name = getenv(DyninstEnvVar);
    } else {
      pdstring msg = pdstring( "Environment variable " + pdstring( DyninstEnvVar )
			       + " has not been defined for process " ) + pdstring( getPid() );
      showErrorCallback(101, msg);
      return false;
    } /* end if enviromental variable not found */
  } /* end enviromental variable extraction */
        
  /* Save the (main thread's) current PC.*/
  savedPC = getRepresentativeLWP()->getActiveFrame().getPC();	
        
  /* _dl_open() takes three arguments: a pointer to the library name,
     the DLOPEN_MODE, and the return address of the current frame
     (that is, the location of the SIGILL-generating bundle we'll use
     to handleIfDueToDyninstLib()).  We construct the first here. */
        
  /* Write the string to entry, and then move the PC to the next bundle. */
  codeGen gen(BYTES_TO_SAVE);
        
  Address dyninstlib_addr = gen.used() + codeBase;
  gen.copy(dyninstRT_name.c_str(), dyninstRT_name.length()+1);
        
  Address dlopencall_addr = gen.used() + codeBase;
	
  /* At this point, we use the generic iRPC headers and trailers
     around the call to _dl_open.  (Note that pre-1.35 versions
     of this file had a simpler mechanism well-suited to boot-
     strapping a new port.  The current complexity is to handle
     the attach() case, where we don't know if execution was stopped
     at the entry the entry point to a function. */

  bool ok = theRpcMgr->emitInferiorRPCheader(gen);
  if( ! ok ) { return false; }
	
  /* Generate the call to _dl_open with a large dummy constant as the
     the third argument to make sure we generate the same size code the second
     time around, with the correct "return address." (dyninstlib_brk_addr) */
  // As a quick note, we want to "return" to the beginning of the restore
  // segment, not dyninstlib_brk_addr (or we skip all the restores).
  // Of course, we're not sure what this addr represents....

  pdvector< AstNode * > dlOpenArguments( 4 );
  AstNode * dlOpenCall;
	
  dlOpenArguments[ 0 ] = new AstNode( AstNode::Constant, (void *)dyninstlib_addr );
  dlOpenArguments[ 1 ] = new AstNode( AstNode::Constant, (void *)DLOPEN_MODE );
  dlOpenArguments[ 2 ] = new AstNode( AstNode::Constant, (void *)0xFFFFFFFFFFFFFFFF );
  if( useFourArguments ) { 
  	/* I derived the -2 as follows: from dlfcn/dlopen.c in the glibc sources, line 59,
  	   we find the call to _dl_open(), whose last argument is 'args->file == NULL ? LM_ID_BASE : NS'.
  	   Since the filename we pass in is non-null, this means we (would) pass in NS, which
  	   is defined to be __LM_ID_CALLER in the same file, line 48.  (Since glibc must be shared
  	   for us to be calling _dl_open(), we fall into the second case of the #ifdef.)  __LM_ID_CALLER
  	   is defined in include/dlfcn.h, where it has the value -2. */
    dlOpenArguments[ 3 ] = new AstNode( AstNode::Constant, (void *)(long unsigned int)-2 );
    }
  dlOpenCall = new AstNode( "_dl_open", dlOpenArguments );
	
  /* Remember where we originally generated the call. */
  codeBufIndex_t index = gen.getIndex();
	
  /* emitInferiorRPCheader() configures (the global) registerSpace for us. */
  dlOpenCall->generateCode( this, regSpace, gen, true, true );

  // Okay, we're done with the generation, and we know where we'll be.
  // Go back and regenerate it
  Address dlopenRet = codeBase + gen.used();
  gen.setIndex(index);

  /* Clean up the reference counts before regenerating. */
  removeAst( dlOpenCall );
  removeAst( dlOpenArguments[ 2 ] );
	
  dlOpenArguments[ 2 ] = new AstNode( AstNode::Constant, (void *)dlopenRet );
  dlOpenCall = new AstNode( "_dl_open", dlOpenArguments );
	
  /* Regenerate the call at the same original location with the correct constants. */
  dlOpenCall->generateCode( this, regSpace, gen, true, true );

  /* Clean up the reference counting. */
  removeAst( dlOpenCall );
  removeAst( dlOpenArguments[ 0 ] );
  removeAst( dlOpenArguments[ 1 ] );
  removeAst( dlOpenArguments[ 2 ] );
  if( useFourArguments ) { removeAst( dlOpenArguments[ 3 ] ); }

  // Okay, that was fun. Now restore. And trap. And stuff.
        
	
  unsigned breakOffset, resultOffset, justAfterResultOffset;
  ok = theRpcMgr->emitInferiorRPCtrailer(gen, breakOffset, false, 
					 resultOffset, justAfterResultOffset );
  if( ! ok ) { return false; }					 

  /* Let everyone else know that we're expecting a SIGILL. */
  dyninstlib_brk_addr = codeBase + breakOffset;

  assert(gen.used() < BYTES_TO_SAVE);

  /* Save the function we're going to hijack. */
  InsnAddr iAddr = InsnAddr::generateFromAlignedDataAddress( codeBase, this );
  /* We need to save the whole buffer, because we don't know how big gen is
     when we do the restore.  This could be made more efficient by storing
     gen.used() somewhere. */
  iAddr.saveBundlesTo( savedCodeBuffer, sizeof( savedCodeBuffer ) / 16 );

  /* Write the call into the mutatee. */
  InsnAddr jAddr = InsnAddr::generateFromAlignedDataAddress( codeBase, this );
  jAddr.writeBundlesFrom( (unsigned char *)gen.start_ptr(), gen.used() / 16 );

  /* Now that we know where the code will start, move the (main thread's) PC there. */
  getRepresentativeLWP()->changePC( dlopencall_addr, NULL );

  /* Let them know we're working on it. */
  setBootstrapState( loadingRT_bs );
  return true;
} /* end dlopenDYNINSTlib() */
Example #4
0
mapped_object* PCProcess::createObjectNoFile(Address addr)
{
    Address closestObjEnd = 0;
    for (unsigned i = 0; i < mapped_objects.size(); i++) {
        if (addr >= mapped_objects[i]->codeAbs() &&
            addr < (mapped_objects[i]->codeAbs() +
                    mapped_objects[i]->imageSize())) {
            fprintf(stderr,"createObjectNoFile called for addr %lx, "
                    "matching existing mapped_object %s %s[%d]\n", addr,
                    mapped_objects[i]->fullName().c_str(), FILE__,__LINE__);
            return mapped_objects[i];
        }
        if (addr >= (mapped_objects[i]->codeAbs() + 
                     mapped_objects[i]->imageSize()) &&  
            closestObjEnd < (mapped_objects[i]->codeAbs() + 
                             mapped_objects[i]->imageSize())) {
            closestObjEnd = mapped_objects[i]->codeAbs() + 
                            mapped_objects[i]->imageSize();
        }
    }

    Address testRead = 0;

    // WindowsAPI VirtualQueryEx rounds down to pages size,
    // so we need to round up first.
    Address ObjOffset = closestObjEnd % getMemoryPageSize();
    if (ObjOffset) {
        closestObjEnd = closestObjEnd - ObjOffset + getMemoryPageSize();
    }
    if (readDataSpace((void*)addr, getAddressWidth(), &testRead, false)) {
		// create a module for the region enclosing this address
        ProcControlAPI::Process::MemoryRegion memRegion;
        if (!pcProc_->findAllocatedRegionAround(addr, memRegion)) {
            mal_printf("ERROR: failed to find allocated region for page %lx, %s[%d]\n",
                       addr, FILE__, __LINE__);
			assert(0);
            return NULL;
        }

        mal_printf("[%lx %lx] is valid region containing %lx and corresponding "
                   "to no object, closest is object ending at %lx %s[%d]\n", 
                   memRegion.first, memRegion.second, addr, closestObjEnd, FILE__,__LINE__);

        // The size of the region returned by VirtualQueryEx is from BaseAddress
        // to the end, NOT from meminfo.AllocationBase, which is what we want.
        // BaseAddress is the start address of the page of the address parameter
        // that is sent to VirtualQueryEx as a parameter
        Address regionSize = memRegion.second - memRegion.first;

        // read region into this PCProcess
        void* rawRegion = malloc(regionSize);
		if (!readDataSpace((void *)memRegion.first, regionSize, rawRegion, true)) {
            mal_printf("Error: failed to read memory region [%lx, %lx]\n",
                       memRegion.first, memRegion.second);
			printSysError(GetLastError());
			assert(0);
            return NULL;
		}

		// set up file descriptor
        char regname[64];
        snprintf(regname, 63, "mmap_buffer_%lx_%lx", memRegion.first, memRegion.second);
        fileDescriptor desc(string(regname),
                            memRegion.first, /*  code  */
                            memRegion.first, /*  data  */
                            regionSize,       /* length */
                            rawRegion,        /* rawPtr */
                            true);            /* shared */
        mapped_object *obj = mapped_object::createMappedObject
            (desc, this, getHybridMode(), false);
        if (obj != NULL) {
            obj->setMemoryImg();
            //mapped_objects.push_back(obj);
	        addMappedObject(obj);

            obj->parse_img()->getOrCreateModule(
                obj->parse_img()->getObject()->getDefaultModule());
            return obj;
        } else {
            fprintf(stderr,"Failed to create object (that was not backed by a file) at %lx\n", memRegion.first);
            return NULL;
        }

    }

    return NULL;
}