@ -233,19 +233,55 @@ struct HeapBlock
ULONG reserved ;
} ;
*/
// FIXME: NEEDS TESTING!
// FIXME: <warmist> i noticed that if you enumerate it twice, second time it returns wrong .text region size
static void GetDosNames ( std : : map < string , string > & table )
{
// Partially based on example from msdn:
// Translate path with device name to drive letters.
TCHAR szTemp [ 512 ] ;
szTemp [ 0 ] = ' \0 ' ;
if ( GetLogicalDriveStrings ( sizeof ( szTemp ) - 1 , szTemp ) )
{
TCHAR szName [ MAX_PATH ] ;
TCHAR szDrive [ 3 ] = " : " ;
BOOL bFound = FALSE ;
TCHAR * p = szTemp ;
do
{
// Copy the drive letter to the template string
* szDrive = * p ;
// Look up each device name
if ( QueryDosDevice ( szDrive , szName , MAX_PATH ) )
table [ szName ] = szDrive ;
// Go to the next NULL character.
while ( * p + + ) ;
} while ( * p ) ; // end of string
}
}
void Process : : getMemRanges ( vector < t_memrange > & ranges )
{
MEMORY_BASIC_INFORMATION MBI ;
//map<char *, unsigned int> heaps;
uint64_t movingStart = 0 ;
PVOID LastAllocationBase = 0 ;
map < char * , string > nameMap ;
map < string , string > dosDrives ;
// get page size
SYSTEM_INFO si ;
GetSystemInfo ( & si ) ;
uint64_t PageSize = si . dwPageSize ;
// get dos drive names
GetDosNames ( dosDrives ) ;
ranges . clear ( ) ;
// enumerate heaps
// HeapNodes(d->my_pid, heaps);
// go through all the VM regions, convert them to our internal format
@ -254,52 +290,106 @@ void Process::getMemRanges( vector<t_memrange> & ranges )
movingStart = ( ( uint64_t ) MBI . BaseAddress + MBI . RegionSize ) ;
if ( movingStart % PageSize ! = 0 )
movingStart = ( movingStart / PageSize + 1 ) * PageSize ;
// skip empty regions and regions we share with other processes (DLLs)
if ( ! ( MBI . State & MEM_COMMIT ) /*|| !(MBI.Type & MEM_PRIVATE)*/ )
// Skip unallocated address space
if ( MBI . State & MEM_FREE )
continue ;
// Find range and permissions
t_memrange temp ;
memset ( & temp , 0 , sizeof ( temp ) ) ;
temp . start = ( char * ) MBI . BaseAddress ;
temp . end = ( ( char * ) MBI . BaseAddress + ( uint64_t ) MBI . RegionSize ) ;
temp . read = MBI . Protect & PAGE_EXECUTE_READ | | MBI . Protect & PAGE_EXECUTE_READWRITE | | MBI . Protect & PAGE_READONLY | | MBI . Protect & PAGE_READWRITE ;
temp . write = MBI . Protect & PAGE_EXECUTE_READWRITE | | MBI . Protect & PAGE_READWRITE ;
temp . execute = MBI . Protect & PAGE_EXECUTE_READ | | MBI . Protect & PAGE_EXECUTE_READWRITE | | MBI . Protect & PAGE_EXECUTE ;
temp . valid = true ;
if ( ! GetModuleBaseName ( d - > my_handle , ( HMODULE ) temp . start , temp . name , 1024 ) )
temp . valid = true ;
if ( ! ( MBI . State & MEM_COMMIT ) )
temp . valid = false ; // reserved address space
else if ( MBI . Protect & PAGE_EXECUTE )
temp . execute = true ;
else if ( MBI . Protect & PAGE_EXECUTE_READ )
temp . execute = temp . read = true ;
else if ( MBI . Protect & PAGE_EXECUTE_READWRITE )
temp . execute = temp . read = temp . write = true ;
else if ( MBI . Protect & PAGE_EXECUTE_WRITECOPY )
temp . execute = temp . read = temp . write = true ;
else if ( MBI . Protect & PAGE_READONLY )
temp . read = true ;
else if ( MBI . Protect & PAGE_READWRITE )
temp . read = temp . write = true ;
else if ( MBI . Protect & PAGE_WRITECOPY )
temp . read = temp . write = true ;
// Merge areas with the same properties
if ( ! ranges . empty ( ) & & LastAllocationBase = = MBI . AllocationBase )
{
if ( nameMap . count ( ( char * ) temp . start ) )
auto & last = ranges . back ( ) ;
if ( last . end = = temp . start & &
last . valid = = temp . valid & & last . execute = = temp . execute & &
last . read = = temp . read & & last . write = = temp . write )
{
// potential buffer overflow...
strcpy ( temp . name , nameMap [ ( char * ) temp . start ] . c_str ( ) ) ;
last . end = temp . end ;
continue ;
}
else
}
# if 1
// Find the mapped file name
if ( GetMappedFileName ( d - > my_handle , temp . start , temp . name , 1024 ) )
{
int vsize = strlen ( temp . name ) ;
// Translate NT name to DOS name
for ( auto it = dosDrives . begin ( ) ; it ! = dosDrives . end ( ) ; + + it )
{
// filter away shared segments without a name.
if ( ! ( MBI . Type & MEM_PRIVATE ) )
int ksize = it - > first . size ( ) ;
if ( strncmp ( temp . name , it - > first . data ( ) , ksize ) ! = 0 )
continue ;
else
temp . name [ 0 ] = 0 ;
memcpy ( temp . name , it - > second . data ( ) , it - > second . size ( ) ) ;
memmove ( temp . name + it - > second . size ( ) , temp . name + ksize , vsize + 1 - ksize ) ;
break ;
}
}
else
temp . name [ 0 ] = 0 ;
# else
// Find the executable name
char * base = ( char * ) MBI . AllocationBase ;
if ( nameMap . count ( base ) )
{
strncpy ( temp . name , nameMap [ base ] . c_str ( ) , 1023 ) ;
}
else if ( GetModuleBaseName ( d - > my_handle , ( HMODULE ) base , temp . name , 1024 ) )
{
std : : string nm ( temp . name ) ;
nameMap [ base ] = nm ;
// this is our executable! (could be generalized to pull segments from libs, but whatever)
if ( d - > base = = temp . start )
if ( d - > base = = base )
{
for ( int i = 0 ; i < d - > pe_header . FileHeader . NumberOfSections ; i + + )
{
char sectionName [ 9 ] ;
/*char sectionName[9];
memcpy ( sectionName , d - > sections [ i ] . Name , 8 ) ;
sectionName [ 8 ] = 0 ;
string nm ;
nm . append ( temp . name ) ;
nm . append ( " : " ) ;
nm . append ( sectionName ) ;
nameMap [ ( char * ) temp . start + d - > sections [ i ] . VirtualAddress ] = nm ;
nm . append ( sectionName ) ; */
nameMap [ base + d - > sections [ i ] . VirtualAddress ] = nm ;
}
}
else
continue ;
}
else
temp . name [ 0 ] = 0 ;
# endif
// Push the entry
LastAllocationBase = MBI . AllocationBase ;
ranges . push_back ( temp ) ;
}
}