int __cdecl main(int argc, char *argv[]) { PROCESS_INFORMATION pi; STARTUPINFO si; HANDLE hEvToHelper; HANDLE hEvFromHelper; DWORD dwExitCode; DWORD dwRet; char cmdComposeBuf[MAX_PATH]; PWCHAR uniString; if(0 != (PAL_Initialize(argc, argv))) { return FAIL; } /* Create the signals we need for cross process communication */ hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName); if (!hEvToHelper) { Fail("WriteProcessMemory: CreateEvent of '%S' failed. " "GetLastError() returned %d.\n", szcToHelperEvName, GetLastError()); } if (GetLastError() == ERROR_ALREADY_EXISTS) { Fail("WriteProcessMemory: CreateEvent of '%S' failed. " "(already exists!)\n", szcToHelperEvName); } hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName); if (!hEvToHelper) { Fail("WriteProcessMemory: CreateEvent of '%S' failed. " "GetLastError() returned %d.\n", szcFromHelperEvName, GetLastError()); } if (GetLastError() == ERROR_ALREADY_EXISTS) { Fail("WriteProcessMemory: CreateEvent of '%S' failed. " "(already exists!)\n", szcFromHelperEvName); } ResetEvent(hEvFromHelper); ResetEvent(hEvToHelper); if (!sprintf(cmdComposeBuf, "helper %s", commsFileName)) { Fail("Could not convert command line\n"); } uniString = convert(cmdComposeBuf); ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); /* Create a new process. This is the process that will ask for * memory munging */ if(!CreateProcess( NULL, uniString, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { Trace("ERROR: CreateProcess failed to load executable '%S'. " "GetLastError() returned %u.\n", uniString, GetLastError()); free(uniString); Fail(""); } free(uniString); while(1) { FILE *commsFile; char* pSrcMemory; char* pDestMemory; SIZE_T Count; SIZE_T wpmCount; char incomingCMDBuffer[MAX_PATH + 1]; int err; HANDLE readProcessHandle; DWORD readProcessID; char readProcessBuffer[REGIONSIZE]; // size 1024 BOOL bResult; size_t size = 0; readProcessID = pi.dwProcessId; /* wait until the helper tells us that it has given us * something to do */ dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT); if (dwRet != WAIT_OBJECT_0) { Trace("test1 WaitForSingleObjectTest: WaitForSingleObject " "failed (%u)\n", GetLastError()); break; /* no more work incoming */ } /* get the parameters to test WriteProcessMemory with */ if (!(commsFile = fopen(commsFileName, "r"))) { /* no file means there is no more work */ break; } if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile)) { Fail ("unable to read from communication file %s " "for reasons %u & %u\n", errno, GetLastError()); } PEDANTIC1(fclose,(commsFile)); sscanf(incomingCMDBuffer, LLFORMAT " " LLFORMAT, &pDestMemory, &Count); if (argc > 1) { Trace("Preparing to write to " LLFORMAT " bytes @ " LLFORMAT "('%s')\n", Count, pDestMemory, incomingCMDBuffer); } /* compose some data to write to the client process */ if (!(pSrcMemory = malloc(Count))) { Trace("could not dynamically allocate memory to copy from " "for reasons %u & %u\n", errno, GetLastError()); goto doneIteration; } memset(pSrcMemory, nextValue, Count); Trace("Preparing to write to " LLFORMAT " bytes @ " LLFORMAT " ('%s')[%u]\n", Count, pDestMemory, incomingCMDBuffer, pSrcMemory); /* do the work */ dwRet = WriteProcessMemory(pi.hProcess, pDestMemory, pSrcMemory, Count, &wpmCount); if (!dwRet) { Trace("%s: Problem: on a write to "LLFORMAT " bytes @ " LLFORMAT " ('%s')\n", argv[0], Count, pDestMemory, incomingCMDBuffer); Trace("test1 WriteProcessMemory returned a (!=0) (GLE=%u)\n", GetLastError()); } if(Count != wpmCount) { Trace("%s: Problem: on a write to " LLFORMAT " bytes @ " LLFORMAT " ('%s')\n", argv[0], Count, pDestMemory, incomingCMDBuffer); Trace("The number of bytes written should have been " LLFORMAT ", but was reported as " LLFORMAT " \n", Count, wpmCount); } readProcessHandle = OpenProcess( PROCESS_VM_READ, FALSE, readProcessID); if(NULL == readProcessHandle) { Fail("\nFailed to call OpenProcess API to retrieve " "current process handle error code=%u\n", GetLastError()); } /*zero the memory*/ memset(readProcessBuffer, 0, size); /*retrieve the memory contents*/ bResult = ReadProcessMemory( readProcessHandle, /*current process handle*/ pDestMemory, /*base of memory area*/ (LPVOID)readProcessBuffer, Count, /*buffer length in bytes*/ &size); if( !bResult || (Count != size) ) { Trace("\nFailed to call ReadProcessMemory API " "to retrieve the memory contents, error code=%u; Bresult[%u] Count[" LLFORMAT "], Size[%d]\n", GetLastError(), bResult, Count, size); err = CloseHandle(readProcessHandle); if(0 == err) { Trace("\nFailed to call CloseHandle API, error code=%u\n", GetLastError()); } dwExitCode = FAIL; } if( !memcmp (pDestMemory, readProcessBuffer, Count ) ) { Trace("Difference in memory contents, expected [%s], but received [%s]\n", pDestMemory, readProcessBuffer); dwExitCode = FAIL; } Trace("ReadProcessBuffer contains [%s]\n", readProcessBuffer); err = CloseHandle(readProcessHandle); free(pSrcMemory); doneIteration: PEDANTIC(ResetEvent, (hEvFromHelper)); PEDANTIC(SetEvent, (hEvToHelper)); } /* wait for the child process to complete */ WaitForSingleObject ( pi.hProcess, TIMEOUT ); /* this may return a failure code on a success path */ /* check the exit code from the process */ if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) { Trace( "GetExitCodeProcess call failed with error code %u\n", GetLastError() ); dwExitCode = FAIL; } PEDANTIC(CloseHandle, (hEvToHelper)); PEDANTIC(CloseHandle, (hEvFromHelper)); PEDANTIC(CloseHandle, (pi.hThread)); PEDANTIC(CloseHandle, (pi.hProcess)); PAL_TerminateEx(dwExitCode); return dwExitCode; }
int __cdecl main(int argc, char *argv[]) { PROCESS_INFORMATION pi; STARTUPINFO si; HANDLE hEvToHelper; HANDLE hEvFromHelper; DWORD dwExitCode; DWORD dwRet; BOOL success = TRUE; /* assume success */ char cmdComposeBuf[MAX_PATH]; PWCHAR uniString; if(0 != (PAL_Initialize(argc, argv))) { return FAIL; } /* Create the signals we need for cross process communication */ hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName); if (!hEvToHelper) { Fail("WriteProcessMemory: CreateEvent of '%S' failed. " "GetLastError() returned %u.\n", szcToHelperEvName, GetLastError()); } if (GetLastError() == ERROR_ALREADY_EXISTS) { Fail("WriteProcessMemory: CreateEvent of '%S' failed. " "(already exists!)\n", szcToHelperEvName); } hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName); if (!hEvToHelper) { Fail("WriteProcessMemory: CreateEvent of '%S' failed. " "GetLastError() returned %u.\n", szcFromHelperEvName, GetLastError()); } if (GetLastError() == ERROR_ALREADY_EXISTS) { Fail("WriteProcessMemory: CreateEvent of '%S' failed. " "(already exists!)\n", szcFromHelperEvName); } if (!sprintf(cmdComposeBuf, "helper %s", commsFileName)) { Fail("Could not convert command line\n"); } uniString = convert(cmdComposeBuf); ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); /* Create a new process. This is the process that will ask for * memory munging */ if(!CreateProcess( NULL, uniString, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { Trace("ERROR: CreateProcess failed to load executable '%S'. " "GetLastError() returned %u.\n", uniString, GetLastError()); free(uniString); Fail(""); } free(uniString); while(1) { FILE *commsFile; char* pSrcMemory; char* pDestMemory; int Count; DWORD wpmCount; DWORD dwExpectedErrorCode; char incomingCMDBuffer[MAX_PATH + 1]; /* wait until the helper tells us that it has given us * something to do */ dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT); if (dwRet != WAIT_OBJECT_0) { Trace("test1 WaitForSingleObjectTest: WaitForSingleObject " "failed (%u)\n", GetLastError()); break; /* no more work incoming */ } /* get the parameters to test WriteProcessMemory with */ if (!(commsFile = fopen(commsFileName, "r"))) { /* no file means there is no more work */ break; } if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile)) { Trace ("unable to read from communication file %s " "for reasons %u & %u\n", errno, GetLastError()); success = FALSE; PEDANTIC1(fclose,(commsFile)); /* it's not worth continuing this trial */ goto doneIteration; } PEDANTIC1(fclose,(commsFile)); sscanf(incomingCMDBuffer, "%u %u %u", &pDestMemory, &Count, &dwExpectedErrorCode); if (argc > 1) { Trace("Preparing to write to %u bytes @ %u ('%s')\n", Count, pDestMemory, incomingCMDBuffer); } /* compose some data to write to the client process */ if (!(pSrcMemory = malloc(Count))) { Trace("could not dynamically allocate memory to copy from " "for reasons %u & %u\n", errno, GetLastError()); success = FALSE; goto doneIteration; } memset(pSrcMemory, nextValue, Count); /* do the work */ dwRet = WriteProcessMemory(pi.hProcess, pDestMemory, pSrcMemory, Count, &wpmCount); if(dwRet != 0) { Trace("ERROR: Situation: '%s', return code: %u, bytes 'written': %u\n", incomingCMDBuffer, dwRet, wpmCount); Trace("ERROR: WriteProcessMemory did not fail as it should, as " "it attempted to write to a range of memory which was " "not completely accessible.\n"); success = FALSE; } if(GetLastError() != dwExpectedErrorCode) { Trace("ERROR: GetLastError() should have returned " "%u , but instead it returned %u.\n", dwExpectedErrorCode, GetLastError()); success = FALSE; } free(pSrcMemory); doneIteration: PEDANTIC(ResetEvent, (hEvFromHelper)); PEDANTIC(SetEvent, (hEvToHelper)); } /* wait for the child process to complete */ WaitForSingleObject ( pi.hProcess, TIMEOUT ); /* this may return a failure code on a success path */ /* check the exit code from the process */ if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) { Trace( "GetExitCodeProcess call failed with error code %u\n", GetLastError() ); dwExitCode = FAIL; } if(!success) { dwExitCode = FAIL; } PEDANTIC(CloseHandle, (hEvToHelper)); PEDANTIC(CloseHandle, (hEvFromHelper)); PEDANTIC(CloseHandle, (pi.hThread)); PEDANTIC(CloseHandle, (pi.hProcess)); PAL_Terminate(); return dwExitCode; }
int wpmDoIt(struct allhandles_t Comms, char * pBuffer, unsigned int lenBuffer, char * pDest, unsigned int lenDest, const char* storageDescription) { char *pCurr; FILE *commsFile; DWORD dwRet; if (pBuffer > pDest || lenDest > lenBuffer) { Trace("WriteProcessMemory::DoIt() test implementation: " "(pBuffer > pDest || lenDest > lenBuffer)\n"); return FALSE; } /* set up the storage */ memset(pBuffer, guardValue, lenBuffer); memset(pDest, initialValue, lenDest); /* tell the parent what RAM to adjust */ if(!(commsFile = fopen(Comms.valuesFileName, "w"))) { Trace("WriteProcessMemory: fopen of '%S' failed (%u). \n", Comms.valuesFileName, GetLastError()); return FALSE; } if (!fprintf(commsFile, "%u %u '%s'\n", pDest, lenDest, storageDescription)) { Trace("WriteProcessMemory: fprintf to '%S' failed (%u). \n", Comms.valuesFileName, GetLastError()); return FALSE; } PEDANTIC1(fclose, (commsFile)); /* Tell the parent the data is ready for it to adjust */ PEDANTIC(ResetEvent, (Comms.hEvToHelper)); PEDANTIC(SetEvent, (Comms.hEvFromHelper)); dwRet = WaitForSingleObject(Comms.hEvToHelper, TIMEOUT); /* parent is done */ if (dwRet != WAIT_OBJECT_0) { Trace("helper WaitForSingleObjectTest: WaitForSingleObject " "failed (%u)\n", GetLastError()); return FALSE; } /* check the stuff that SHOULD have changed */ for (pCurr = pDest; pCurr < (pDest + lenDest); pCurr++) { if ( *pCurr != nextValue) { Trace("When testing '%s': alteration test failed " "at %u offset %u. Found '%c' instead of '%c'\n.", storageDescription, pDest, pCurr - pDest, *pCurr, nextValue); Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); return FALSE; } } /* check the stuff that should NOT have changed */ for (pCurr = pBuffer; pCurr < pDest; pCurr++ ) { if ( *pCurr != guardValue) { Trace("When testing '%s': leading guard zone test failed " "at %u offset %u. Found '%c' instead of '%c'\n.", storageDescription, pDest, pCurr - pBuffer, *pCurr, guardValue); Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); return FALSE; } } for (pCurr = pDest + lenDest; pCurr < (pBuffer + lenBuffer); pCurr++ ) { if ( *pCurr != guardValue) { Trace("When testing '%s': trailing guard zone test failed " "at %u offset %u. Found '%c' instead of '%c'\n.", storageDescription, pDest + lenDest, pCurr - pBuffer, *pCurr, guardValue); Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer); return FALSE; } } return TRUE; }