I am writing a memory scanner in C #. It is able to find strings, but not numeric values. How can I improve it to find addresses with numbers in them?
Edit: I provide my application with a specific number or string to search in memory for the current process. I want to use this to change these values later, but for now I'm just trying to figure out where the values are stored.
Edit 2: it looks like it only works with strings found in executable files of downloaded files / modules; not the values that changed in-proc. Hmm
public class Search
{
public Search(int pid, string value) {
SearchValues = new List<string>();
PossibleAddresses = new List<IntPtr>();
PID = pid;
DoSearch(value); }
public int PID { get; set; }
public Process getProcess { get { return Process.GetProcessById(PID); } }
public List<string> SearchValues { get; private set; }
public List<IntPtr> PossibleAddresses { get; private set; }
public bool hasLockedOn { get; set; }
private IntPtr processPointer { get; set; }
public void DoSearch(string value)
{
SearchValues.Add(value);
IntPtr baseAddress, lastAddress;
Process process = getProcess;
baseAddress = process.MainModule.BaseAddress;
lastAddress = baseAddress + process.MainModule.ModuleMemorySize;
processPointer = OpenProcess((uint)(0x0010), 1, (uint)PID);
int iVal;
double dVal;
int.TryParse(value, out iVal);
double.TryParse(value, out dVal);
if (SearchValues.Count == 1)
for (int addr = (int)baseAddress; addr + value.Length < (int)lastAddress; addr++)
{
if (dVal > 0 && MemoryContainsNumber((IntPtr)addr, dVal, ((IntPtr)addr)))
PossibleAddresses.Add((IntPtr)addr);
else if (iVal > 0 && MemoryContainsNumber((IntPtr)addr, iVal, ((IntPtr)addr)))
PossibleAddresses.Add((IntPtr)addr);
else if (ReadMemory((IntPtr)addr, (uint)value.Length, (IntPtr)addr).Trim().ToLower() == value.Trim().ToLower())
PossibleAddresses.Add((IntPtr)addr);
}
else {
}
hasLockedOn = PossibleAddresses.Count == 1;
CloseHandle(processPointer);
}
private string ReadMemory(IntPtr memAddress, uint size, IntPtr BaseAddress)
{
byte[] buffer = new byte[size];
IntPtr bytesRead;
unsafe
{
ReadProcessMemory(processPointer, BaseAddress, buffer, size, out bytesRead);
return Encoding.Default.GetString(buffer);
}
}
private bool MemoryContainsNumber(IntPtr memAddress, int number, IntPtr BaseAddress)
{
byte[] numberBytes = BitConverter.GetBytes(number);
byte[] buffer = new byte[numberBytes.Length];
IntPtr bytesRead;
unsafe { ReadProcessMemory(processPointer, BaseAddress, buffer, (uint)numberBytes.Length, out bytesRead); }
for (int i = 0; i < buffer.Length; i++)
if (buffer[i] != numberBytes[i])
return false;
return true;
}
private bool MemoryContainsNumber(IntPtr memAddress, double number, IntPtr BaseAddress)
{
byte[] numberBytes = BitConverter.GetBytes(number);
byte[] buffer = new byte[numberBytes.Length];
IntPtr bytesRead;
unsafe { ReadProcessMemory(processPointer, BaseAddress, buffer, (uint)numberBytes.Length, out bytesRead); }
for (int i = 0; i < buffer.Length; i++)
if (buffer[i] != numberBytes[i])
return false;
return true;
}
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);
[DllImport("kernel32.dll")]
public static extern Int32 CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll")]
public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
public static extern Int32 WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesWritten);
}