Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Simple Memory Scanner Example
- * (c) 2014 atom0s [atom0s@live.com]
- */
- #include <Windows.h>
- #include <wchar.h>
- #include <iostream>
- #include <string>
- #include <TlHelp32.h>
- #include <vector>
- using namespace std;
- /**
- * @brief The target process to scan within.
- */
- const wchar_t *TARGET_NAME = L"ac_client.exe";
- const unsigned int ARRAY_SIZE = 8000;
- /**
- * @brief Obtains the process id of the given target.
- *
- * @return The process id if found, 0 otherwise.
- */
- void flushArrayToFile(FILE * file, uint32_t arr[]) {
- fwrite(arr, sizeof(uint32_t), sizeof(arr) / 4, file);
- }
- const int getFileSize(FILE * file) {
- fseek(file, 0, SEEK_END);
- return ftell(file);
- }
- unsigned int getTargetProcessId()
- {
- PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
- // Obtain a snapshot of the current process list..
- auto handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
- if (handle == INVALID_HANDLE_VALUE)
- return 0;
- // Obtain the first process..
- if (!::Process32First(handle, &pe32))
- {
- ::CloseHandle(handle);
- return 0;
- }
- // Loop each process looking for the target..
- do
- {
- if (!wcscmp(pe32.szExeFile, TARGET_NAME))
- {
- ::CloseHandle(handle);
- return pe32.th32ProcessID;
- }
- } while (::Process32Next(handle, &pe32));
- // Cleanup..
- ::CloseHandle(handle);
- return 0;
- }
- void showMbiInfo(MEMORY_BASIC_INFORMATION mbi) {
- cout << hex << "Base Address: " << mbi.BaseAddress << endl;
- cout << "Region Size: " << mbi.RegionSize << endl;
- }
- /**
- * @brief Entry point of this application.
- *
- * @param argc The count of arguments passed to this application.
- * @param argv The array of arguments passed to this application.
- *
- * @return Non-important return.
- */
- int __cdecl main(int argc, char* argv[])
- {
- // Obtain the target process id..
- auto processId = getTargetProcessId();
- cout << processId << endl;
- if (processId == 0)
- return 0;
- // Open a handle to the target..
- auto handle = ::OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, processId);
- if (handle == INVALID_HANDLE_VALUE)
- return 0;
- // Obtain the current system information..
- SYSTEM_INFO sysInfo = { 0 };
- ::GetSystemInfo(&sysInfo);
- auto addr_min = (unsigned long)sysInfo.lpMinimumApplicationAddress;
- auto addr_max = (unsigned long)sysInfo.lpMaximumApplicationAddress;
- cout << addr_min << " to " << addr_max << endl;
- cout << "Enter 4 byte value to search: " << endl;
- int value;
- cin >> value;
- uint32_t addresses[ARRAY_SIZE];
- int curIndex = 0;
- int foundCurrent = 0;
- int foundTotal = 0;
- FILE * file = fopen("addr.bin", "wb");
- // initial scan ("new scan")
- while (addr_min < addr_max)
- {
- MEMORY_BASIC_INFORMATION mbi = { 0 };
- if (!::VirtualQueryEx(handle, (LPCVOID)addr_min, &mbi, sizeof(mbi)))
- {
- printf_s("Failed to query memory.\n");
- break;
- }
- // Determine if we have access to the page..
- if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_GUARD) == 0) && ((mbi.Protect & PAGE_NOACCESS) == 0))
- {
- //
- // Below are flags about the current region of memory. If you want to specifically scan for only
- // certain things like if the area is writable, executable, etc. you can use these flags to prevent
- // reading non-desired protection types.
- //
- auto isCopyOnWrite = ((mbi.Protect & PAGE_WRITECOPY) != 0 || (mbi.Protect & PAGE_EXECUTE_WRITECOPY) != 0);
- auto isExecutable = ((mbi.Protect & PAGE_EXECUTE) != 0 || (mbi.Protect & PAGE_EXECUTE_READ) != 0 || (mbi.Protect & PAGE_EXECUTE_READWRITE) != 0 || (mbi.Protect & PAGE_EXECUTE_WRITECOPY) != 0);
- auto isWritable = ((mbi.Protect & PAGE_READWRITE) != 0 || (mbi.Protect & PAGE_WRITECOPY) != 0 || (mbi.Protect & PAGE_EXECUTE_READWRITE) != 0 || (mbi.Protect & PAGE_EXECUTE_WRITECOPY) != 0);
- // Dump the region into a memory block..
- auto dump = new unsigned char[mbi.RegionSize + 1];
- memset(dump, 0x00, mbi.RegionSize + 1); // initialize the whole array to 0
- if (!::ReadProcessMemory(handle, mbi.BaseAddress, dump, mbi.RegionSize, NULL))
- {
- printf_s("Failed to read memory of location: %08X\n", mbi.BaseAddress);
- break;
- }
- // Scan for 4 byte value
- for (int x = 0; x < mbi.RegionSize - 4; x += 4)
- {
- if (*(uint32_t*)(dump + x) == value) {
- foundTotal++;
- foundCurrent++;
- curIndex++;
- if (curIndex >= ARRAY_SIZE) {
- fwrite(addresses, sizeof(uint32_t), ARRAY_SIZE, file);
- foundCurrent -= ARRAY_SIZE;
- curIndex = 0;
- }
- addresses[curIndex] = (uint32_t)mbi.BaseAddress + x;
- cout << hex << addresses[curIndex] << endl;
- }
- }
- // Cleanup the memory dump..
- delete[] dump;
- }
- // Step the current address by this regions size..
- addr_min += mbi.RegionSize;
- }
- // dump what's left into the file and close
- fwrite(addresses, sizeof(uint32_t), foundCurrent, file);
- fclose(file);
- printf_s("Found %d results!\n", foundTotal);
- // below is testing to see if what we pull out of the file matches makes sense
- file = fopen("addr.bin", "rb");
- uint32_t buffer[50000];
- fread(buffer, sizeof(uint32_t), getFileSize(file) / 4, file);
- for (int i = 0; i < foundTotal; i++) {
- cout << "Read from file: " << buffer[i] << endl;
- }
- // below is just comments for how I would do a "next" scan but for now it's not there
- // but there's no point since pulling from files isn't working
- // in the next loop, do fread for ARRAY_SIZE number of elements,
- // or for the number of elements left in the file
- // (if found > ARRAY_SIZE, found -= ARRAY_SIZE?)
- // else use rest of found, then reset found to 0
- // then ReadProcessMemory the whole array
- std::system("pause");
- // Cleanup..
- ::CloseHandle(handle);
- return ERROR_SUCCESS;
- }
Add Comment
Please, Sign In to add comment