Code:
#include <afx.h>
#include <windows.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <stdio.h>
#define MAX_I86_MEMORY_LIMIT 0x4c4b40 // 5MEG
#define PAGE_SIZE 4096
#pragma comment ( lib, "psapi.lib" )
#pragma comment ( lib, "advapi32.lib" )
FILE *outfile;
typedef union _PSAPI_WORKING_SET_BLOCK {
ULONG_PTR Flags;
struct {
ULONG_PTR Protection :5;
ULONG_PTR ShareCount :3;
ULONG_PTR Shared :1;
ULONG_PTR Reserved :3;
ULONG_PTR VirtualPage :20;
} ;
} PSAPI_WORKING_SET_BLOCK,
*PPSAPI_WORKING_SET_BLOCK;
typedef struct _PSAPI_WORKING_SET_INFORMATION {
ULONG_PTR NumberOfEntries;
PSAPI_WORKING_SET_BLOCK WorkingSetInfo[1];
} PSAPI_WORKING_SET_INFORMATION,
*PPSAPI_WORKING_SET_INFORMATION;
typedef struct MEMDIFF_SNAPSHOT
{
DWORD m_signature;
DWORD m_dwAllocSize;
DWORD m_fCompared; // 0 initially, 1 after filtering common pages
DWORD m_nPages; // Must come last!!!
} * PMEMDIFF_SNAPSHOT;
char * BuildErrorMessage( char* pMessage)
{
DWORD eNum;
CHAR sysMsg[256] = {0};
CHAR* p;
static CHAR *szReturn[512];
eNum = GetLastError( );
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
sysMsg, 256, NULL );
// Trim the end of the line and terminate it with a null
p = sysMsg;
while( ( *p > 31 ) || ( *p == 9 ) )
++p;
do { *p-- = 0; } while( ( p >= sysMsg ) &&
( ( *p == '.' ) || ( *p < 33 ) ) );
memset(szReturn, 0, sizeof szReturn);
sprintf((char *)szReturn,"WARNING: %s failed with error %d (%s)\n",pMessage, eNum, sysMsg );
return (char *)szReturn;
}
void ReadTheMemory(DWORD dwProcessId, DWORD dwInputAddress, DWORD dwInputBlockSize)
{
CString strLine, strArr, strTemp;
BYTE byte;
DWORD dwBlock = 0, dwOffset, dwBytesRead;
BYTE * pBuffer = new BYTE[dwInputBlockSize];
HANDLE hProcess = NULL;
if (NULL != pBuffer)
{
hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwProcessId);
if(hProcess == NULL)
{
fprintf(outfile, "OpenProcess failed\n");
return;
}
if (ReadProcessMemory( hProcess, (LPCVOID) dwInputAddress, pBuffer, dwInputBlockSize, &dwBytesRead) == TRUE)
{
for (dwBlock = 0; dwBlock < dwInputBlockSize; dwBlock += 16)
{
strLine.Format("[%08x]: ", dwInputAddress + dwBlock);
strArr.Empty();
// we'll use 16 bytes per line
for (dwOffset = 0; dwOffset < 16; dwOffset++)
{
byte = *(pBuffer + dwBlock + dwOffset);
strLine.Format("%02x ", byte);
// account for non-printable characters
if (32 <= byte && byte < 127)
strArr += byte;
else
strArr += '·';
}
strLine.Format ("%#x %#x (%lu) %s ", dwInputAddress, dwInputBlockSize, dwInputBlockSize, strArr);
fprintf(outfile, "%s\n", strLine);
}
}else fprintf(outfile, "%s\n",BuildErrorMessage("ReadProcessMemory"));
delete [] pBuffer;
CloseHandle( hProcess );
}
}
int VerifyProcessId(char *pProcessName)
{
HANDLE hSnap = INVALID_HANDLE_VALUE;
HANDLE hProcess = INVALID_HANDLE_VALUE;
PROCESSENTRY32 ProcessStruct;
ProcessStruct.dwSize = sizeof(PROCESSENTRY32);
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hSnap == INVALID_HANDLE_VALUE)
return -1;
if(Process32First(hSnap, &ProcessStruct) == FALSE)
return -1;
do
{
if(stricmp(strupr(ProcessStruct.szExeFile), pProcessName)==0)
{
CloseHandle( hSnap );
return ProcessStruct.th32ProcessID;
break;
}
}
while( Process32Next( hSnap, &ProcessStruct ) );
CloseHandle( hSnap );
return -1;
}
BOOL EnableTokenPrivilege (LPTSTR privilege)
{
HANDLE hToken;
TOKEN_PRIVILEGES token_privileges;
DWORD dwSize;
ZeroMemory (&token_privileges, sizeof (token_privileges));
token_privileges.PrivilegeCount = 1;
if ( !OpenProcessToken (GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
return FALSE;
if (!LookupPrivilegeValue ( NULL, privilege, &token_privileges.Privileges[0].Luid))
{
CloseHandle (hToken);
return FALSE;
}
token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges ( hToken, FALSE, &token_privileges, 0, NULL, &dwSize))
{
CloseHandle (hToken);
return FALSE;
}
CloseHandle (hToken);
return TRUE;
}
static FILE *OpenLogFile(void)
{
int iIndex;
for (iIndex = 0; iIndex < 0x10000; ++iIndex) {
char fname[4096];
sprintf(fname, "DUMP%04x.log", iIndex);
FILE *f = fopen(fname, "r");
if (f == NULL)
{
fprintf(stderr, "Log file being used: %s\n",fname);
return fopen(fname, "wt");
}
else {
fclose(f);
}
}
return NULL;
}
int main(int argc, char **argv )
{
DWORD dwProcessId;
DWORD dwAlloc = 0;
outfile = OpenLogFile();
if ( !EnableTokenPrivilege (SE_DEBUG_NAME) )
{
printf("EnabletokenPrivilege issue\n");
return 0;
}
if(outfile == NULL)
{
printf("Log file open failed\n");
return -1;
}
dwProcessId = VerifyProcessId(argv[1]);
if(dwProcessId == -1)
{
printf("Cannot determine Process id for %s, ABORTING!!\n",argv[1]);
return -1;
}
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessId );
PSAPI_WORKING_SET_INFORMATION *pv = NULL;
start:
dwAlloc += 0x2000;
pv = (PSAPI_WORKING_SET_INFORMATION *)VirtualAlloc(0, dwAlloc, MEM_COMMIT,PAGE_READWRITE);
if ( QueryWorkingSet ( hProcess, pv, dwAlloc ) == FALSE )
{
if ( dwAlloc < MAX_I86_MEMORY_LIMIT)
{
VirtualFree( pv, 0, MEM_RELEASE );
pv = NULL;
fprintf(outfile, "Not enough memory allocated: %d\n", dwAlloc);
goto start;
}
else
{
CloseHandle ( hProcess ) ;
fprintf(outfile, "Aborting, Not enough memory allocated, cannot allocate more than %d\n", dwAlloc);
return -1;
}
}
else
{
fprintf(outfile, "Number of entries: %d\n", pv->NumberOfEntries );
for(DWORD iIndex = 0; iIndex < pv->NumberOfEntries; iIndex++)
{
DWORD dwDumpAddress = pv->WorkingSetInfo[iIndex].VirtualPage << 12;
fprintf(outfile,"Virtual Page: 0x%06x (%d)\n",pv->WorkingSetInfo[iIndex].VirtualPage,pv->WorkingSetInfo[iIndex].VirtualPage );
switch(pv->WorkingSetInfo[iIndex].Protection)
{
case 0:
fprintf(outfile,"The page is not accessed.\n");
break;
case 1:
fprintf(outfile,"Read-only.\n");
break;
case 2:
fprintf(outfile,"Executable.\n");
break;
case 3:
fprintf(outfile,"Executable and read-only.\n");
break;
case 4:
fprintf(outfile,"Read/write.\n");
break;
case 5:
fprintf(outfile,"Copy-on-write.\n");
break;
case 6:
fprintf(outfile,"Executable and read/write.\n");
break;
case 7:
fprintf(outfile,"Executable and copy-on-write.\n");
break;
case 8:
fprintf(outfile,"The page is not accessed.\n");
break;
case 9:
fprintf(outfile,"Non-cacheable and read-only.\n");
break;
case 10:
fprintf(outfile,"Non-cacheable and executable.\n");
break;
case 11:
fprintf(outfile,"Non-cacheable, executable, and read-only.\n");
break;
case 12:
fprintf(outfile,"Non-cacheable and read/write.\n");
break;
case 13:
fprintf(outfile,"Non-cacheable and copy-on-write.\n");
break;
case 14:
fprintf(outfile,"Non-cacheable, executable, and read/write.\n");
break;
case 15:
fprintf(outfile,"Non-cacheable, executable, and copy-on-write.\n");
break;
case 16:
fprintf(outfile,"The page is not accessed.\n");
break;
case 17:
fprintf(outfile,"Guard page and read-only.\n");
break;
case 18:
fprintf(outfile,"Guard page and executable.\n");
break;
case 19:
fprintf(outfile,"Guard page, executable, and read-only.\n");
break;
case 20:
fprintf(outfile,"Guard page and read/write.\n");
break;
case 21:
fprintf(outfile,"Guard page and copy-on-write.\n");
break;
case 22:
fprintf(outfile,"Guard page, executable, and read/write.\n");
break;
case 23:
fprintf(outfile,"Guard page, executable, and copy-on-write.\n");
break;
case 24:
fprintf(outfile,"The page is not accessed.\n");
break;
case 25:
fprintf(outfile,"Non-cacheable, guard page, and read-only.\n");
break;
case 26:
fprintf(outfile,"Non-cacheable, guard page, and executable.\n");
break;
case 27:
fprintf(outfile,"Non-cacheable, guard page, executable, and read-only.\n");
break;
case 28:
fprintf(outfile,"Non-cacheable, guard page, and read/write.\n");
break;
case 29:
fprintf(outfile,"Non-cacheable, guard page, and copy-on-write.\n");
break;
case 30:
fprintf(outfile,"Non-cacheable, guard page, executable, and read/write.\n");
break;
case 31:
fprintf(outfile,"Non-cacheable, guard page, executable, and copy-on-write.\n");
default:
fprintf(outfile,"unknown\n");
break;
}
ReadTheMemory(dwProcessId, dwDumpAddress, PAGE_SIZE);
}
}
CloseHandle ( hProcess ) ;
fclose(outfile);
return 0 ;
}