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 __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[]) { BOOL success = TRUE; /* assume success */ struct allhandles_t Comms = {0,0,0} ; /* variables to track storage to alter */ char *pTarget = NULL; unsigned int sizeTarget; if(0 != (PAL_Initialize(argc, argv))) { return FAIL; } /* hook up with the events created by the parent */ Comms.hEvToHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcToHelperEvName); if (!Comms.hEvToHelper) { Fail("WriteProcessMemory: OpenEvent of '%S' failed (%u). " "(the event should already exist!)\n", szcToHelperEvName, GetLastError()); } Comms.hEvFromHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcFromHelperEvName); if (!Comms.hEvToHelper) { Trace("WriteProcessMemory: OpenEvent of '%S' failed (%u). " "(the event should already exist!)\n", szcFromHelperEvName, GetLastError()); success = FALSE; goto EXIT; } Comms.valuesFileName = argv[1]; { char autoAllocatedOnStack[51]; /* Get the parent process to write to the local stack */ success &= wpmDoIt(Comms, autoAllocatedOnStack, sizeof(autoAllocatedOnStack), autoAllocatedOnStack + sizeof(int), sizeof(autoAllocatedOnStack) - 2 * sizeof(int), "const size array on stack with int sized guards"); } /* Get the parent process to write to stuff on the heap */ sizeTarget = 2 * sizeof(int) + 23 ; /* 23 is just a random prime > 16 */ if (!(pTarget = (char*)malloc(sizeTarget))) { Trace("WriteProcessMemory helper: unable to allocate '%s'->%d bytes of memory" "(%u).\n", argv[3], sizeTarget, GetLastError()); success = FALSE; goto EXIT; } success &= wpmDoIt(Comms, pTarget, sizeTarget, pTarget + sizeof(int), sizeTarget - 2 * sizeof(int), "array on heap with int sized guards"); /* just to be nice try something 16 - 2 * sizeof(int) bytes long */ { char autoAllocatedOnStack[16]; /* Get the parent process to write to the local stack */ success &= wpmDoIt(Comms, autoAllocatedOnStack, sizeof(autoAllocatedOnStack), autoAllocatedOnStack + sizeof(int), sizeof(autoAllocatedOnStack) - 2 * sizeof(int), "another 16 byte array on stack with int sized guards inside"); } /* NOTE: Don't try 0 bytes long. Win32 WriteProcessMemory claims * it writes 8 bytes in that case! */ /* and 1 byte long... */ { char autoAllocatedOnStack[1+ 2 * sizeof(int)]; /* Get the parent process to write to the local stack */ success &= wpmDoIt(Comms, autoAllocatedOnStack, sizeof(autoAllocatedOnStack), autoAllocatedOnStack + sizeof(int), 1, "no bytes with int sized guards outside on stack"); } EXIT: /* Tell the parent that we are done */ if (!DeleteFile(Comms.valuesFileName)) { Trace("helper: DeleteFile failed so parent (test1) is unlikely " "to exit cleanly\n"); } PEDANTIC(ResetEvent, (Comms.hEvToHelper)); if (!SetEvent(Comms.hEvFromHelper)) { Trace("helper: SetEvent failed so parent (test1) is unlikely " "to exit cleanly\n"); } free(pTarget); PEDANTIC(CloseHandle, (Comms.hEvToHelper)); PEDANTIC(CloseHandle, (Comms.hEvFromHelper)); if (!success) { Fail(""); } PAL_Terminate(); return success ? PASS : FAIL; }
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; }
int __cdecl main(int argc, char *argv[]) { BOOL success = TRUE; /* assume success */ DWORD dwRet; DWORD dwProcessId; char szEventName[MAX_LONGPATH]; PWCHAR uniString; if(0 != (PAL_Initialize(argc, argv))) { return FAIL; } /* Open the event to let test thread tell us to get started. */ uniString = convert(szcHelperProcessStartEvName); hProcessStartEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString); free(uniString); if (!hProcessStartEvent) { Fail("helper.main: OpenEvent of '%S' failed (%u). " "(the event should already exist!)\n", szcHelperProcessStartEvName, GetLastError()); } /* Wait for signal from test thread. */ dwRet = WaitForSingleObject(hProcessStartEvent, TIMEOUT); if (dwRet != WAIT_OBJECT_0) { Fail("helper.main: WaitForSingleObject '%s' failed\n" "LastError:(%u)\n", szcHelperProcessStartEvName, GetLastError()); } dwProcessId = GetCurrentProcessId(); if ( 0 >= dwProcessId ) { Fail ("helper.main: %s has invalid pid %d\n", argv[0], dwProcessId ); } /* Open the event to tell test thread we are ready. */ if (sprintf_s(szEventName, MAX_LONGPATH-1, "%s%d", szcHelperProcessReadyEvName, dwProcessId) < 0) { Fail ("helper.main: Insufficient event name string length for pid=%d\n", dwProcessId); } uniString = convert(szEventName); hProcessReadyEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString); free(uniString); if (!hProcessReadyEvent) { Fail("helper.main: OpenEvent of '%s' failed (%u). " "(the event should already exist!)\n", szEventName, GetLastError()); } /* Open the event to let test thread tell us to exit. */ if (sprintf_s(szEventName, MAX_LONGPATH-1, "%s%d", szcHelperProcessFinishEvName, dwProcessId) < 0) { Fail ("helper.main: Insufficient event name string length for pid=%d\n", dwProcessId); } uniString = convert(szEventName); hProcessFinishEvent = OpenEventW(EVENT_ALL_ACCESS, 0, uniString); free(uniString); if (!hProcessFinishEvent) { Fail("helper.main: OpenEvent of '%s' failed LastError:(%u).\n", szEventName, GetLastError()); } /* Tell the test thread we are ready. */ if (!SetEvent(hProcessReadyEvent)) { Fail("helper.main: SetEvent '%s' failed LastError:(%u)\n", hProcessReadyEvent, GetLastError()); } /* Wait for signal from test thread before exit. */ dwRet = WaitForSingleObject(hProcessFinishEvent, TIMEOUT); if (WAIT_OBJECT_0 != dwRet) { Fail("helper.main: WaitForSingleObject '%s' failed pid=%d\n" "LastError:(%u)\n", szcHelperProcessFinishEvName, dwProcessId, GetLastError()); } PEDANTIC(CloseHandle, (hProcessStartEvent)); PEDANTIC(CloseHandle, (hProcessReadyEvent)); PEDANTIC(CloseHandle, (hProcessFinishEvent)); PAL_Terminate(); return success ? PASS : FAIL; }