I'm trying to read a variable from another process' memory in C and upon first query, for which I'm using VirtualQueryEx function, some potentially matching values are returned. However, when I change the value of the variable in the process which I'm querying and query the addresses of the potentially matching values, none of them match.
The queried process is a simple test program (also written in C) that allows you to change the value in a variable and print the value.
I tried changing the variable in the queried program to be stored on the heap, not the stack, but to no avail.
I expected the values queried to change according to them changing in the target process, but instead, after the first query and upon changing the queried value to what it is now in the target process, none of the values from the first query match the following queries.
linked_list.c is a file which contains functions to use a linked list to store the addresses of the potentially matching values.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <windows.h>
#include "linked_list.h"
// FOR COMPILATION: -linked_list.c
int ask_current_value(){
char buffer[128];
printf("Current value: ");
fgets(buffer, sizeof(buffer), stdin);
*((char*)(memchr((void*)buffer, '\n', sizeof(buffer)))) = '\0';
return atoi(buffer);
}
void print_memory_from_linked_list(Node* pProcessMemoryPtrList, HANDLE hOpenedProcess){
// Simply formats the printing to not be so ugly
int value;
void* value_address;
// (First element of list is garbage data, not to be included)
for (int i = 1; i < linked_list_len(pProcessMemoryPtrList); i++){
value_address = fetch_linked_list_element(pProcessMemoryPtrList, i);
if (ReadProcessMemory(hOpenedProcess, value_address, &value, sizeof(value), NULL) != 0){
printf("%d@%p\n", value, value_address);
} else { printf("Func ReadProcessMemory failed non fatally\n"); }
}
}
int main(){
printf("Pid: ");
char str_pid[7]; // up to 99999 + \n and \0
fgets(str_pid, sizeof(str_pid), stdin);
*((char*)(memchr((void*)str_pid, '\n', sizeof(str_pid)))) = '\0';
int pid = atoi(str_pid);
// Get process handle
HANDLE hOpenedProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, false, pid);
if (hOpenedProcess == NULL){
printf("Smth went wrong, did u insert pid correct?\n");
exit(1);
}
Node* pProcessMemoryPtrList = init_linked_list((void*)&pid); // First element of list DO NOT TOUCH
int current_value;
current_value = ask_current_value();
MEMORY_BASIC_INFORMATION mbi;
unsigned char* addr = 0; // Addr to increment according to RegionSize
int value; // This stores the actual value queried from memory
// Query memory until reach end of memory region and increment addr to query each loop
while (VirtualQueryEx(hOpenedProcess, addr, &mbi, sizeof(mbi)) != 0){
// Check if memory region is commited and readable, no use if these arent true
if (mbi.State == MEM_COMMIT && (mbi.Protect & PAGE_READONLY)){
char* pMemoryBuffer = malloc(mbi.RegionSize); // Allocate region size sized buffer to store read memory
if (ReadProcessMemory(hOpenedProcess, addr, pMemoryBuffer, mbi.RegionSize, NULL) != 0){
// Loop accross the memory and search for possible matches
for (int i = 0; i <= mbi.RegionSize - sizeof(value); i++){
memcpy(&value, &pMemoryBuffer[i], sizeof(value));
// If value obtained from memory matches, add its addr to linked list
if (value == current_value){
uintptr_t offset = (uintptr_t)&pMemoryBuffer[i] - (uintptr_t)&pMemoryBuffer[0]; // Compute offset from buffer start
void* value_address = (void*)((uintptr_t)mbi.BaseAddress + offset); // Add offset to current address
pProcessMemoryPtrList = add_to_linked_list(pProcessMemoryPtrList, value_address);
}
}
} else { printf("Func ReadProcessMemory failed non fatally\n"); }
free(pMemoryBuffer); // Free the allocated buffer (RegionSize is dynamic)
} else { printf("Memory region does not match supplied properties (commited and readable)\n"); }
addr += mbi.RegionSize;
}
print_memory_from_linked_list(pProcessMemoryPtrList, hOpenedProcess);
while (1){
current_value = ask_current_value();
// linked_list_len() gets length of linked list
for (int i = 1; i < linked_list_len(pProcessMemoryPtrList); i++){
// fetch_linked_list_element() gets element at index n
void* value_address = fetch_linked_list_element(pProcessMemoryPtrList, i);
if (ReadProcessMemory(hOpenedProcess, value_address, &value, sizeof(value), NULL) != 0){
if (value == current_value){
printf("%d@%p\n", value, value_address);
} else {
pProcessMemoryPtrList = delete_element_at_index(pProcessMemoryPtrList, i);
}
} else { printf("Func ReadProcessMemory failed non fatally\n"); }
}
}
for (int i = linked_list_len(pProcessMemoryPtrList) - 1; i >= 0; i--){
delete_element_at_index(pProcessMemoryPtrList, i);
}
CloseHandle(hOpenedProcess);
return 0;
}
\nbefore callingatoi(). It will simply stop converting characters when it encounters\n, no error reported. 2) you should not be opening the target process withPROCESS_VM_WRITEpermission since you never callWriteProcessMemory().