this is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId")]
public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
[DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
public static extern Int32 ReadProcessMemory(IntPtr hProcess, int lpBaseAddress, out string buffer, int size, out int lpNumberOfBytesRead);
public List<int> Search(string ProcessName, int _Length, int Value)
{
Process[] P = Process.GetProcessesByName(ProcessName);
List<int> tmp = new List<int>();
if (P.Length < 0) return tmp;
try
{
if (P[0].HasExited)
return tmp;
}
catch { return tmp; }
byte[] buff = new byte[4];
int Address = P[0].MainModule.BaseAddress.ToInt32();
for (int i = 0; i < _Length; i++)
{
ReadProcessMemory(P[0].Handle, Address + i, buff, 4, 0);
if (BitConverter.ToInt32(buff, 0) == Value)
{
tmp.Add(Address + i);
}
}
return tmp;
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
listBox1.DataSource = Search("plugin-container", 0x100, 15035990);
}
}
}
the problem:
ReadProcessMemory(P[0].Handle, Address + i, buff, 4, 0);
That line is wrong
He marks it with a red line
Does anyone have any idea why he does not recognize this line?
Sorry about my bad English
Your P/Invoke definitions are not quite right. While lpBuffer is annotated as an __out parameter, this does not translate to the .Net P/Invoke meaning of out. If you notice it is an LPVOID, which if this was truly a .Net out it should be LPVOID* (pointer to a pointer).
Instead:
[DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
public static extern bool ReadProcessMemory(
IntPtr hProcess, // <-- Pointers should be IntPtr
IntPtr lpBaseAddress,
byte[] buffer, // <-- Using byte[], also IntPtr could be used
uint size, // <-- SIZE_T is unsigned
out uint lpNumberOfBytesRead);
Used like so:
uint bytesRead;
byte[] buffer = new byte[4];
IntPtr baseAddress = P[0].MainModule.BaseAddress;
for (int i = 0; i < _Length; i++)
{
IntPtr nextAddress = IntPtr.Add(baseAddress, i);
if (ReadProcessMemory(
P[0].Handle,
nextAddress,
buffer,
(uint)buffer.Length,
out bytesRead))
{
if (bytesRead == buffer.Length
&& BitConverter.ToInt32(buffer, 0) == Value)
{
tmp.Add(nextAddress);
}
else if (bytesRead != buffer.Length)
{
throw new InvalidOperationException(String.Format(
#"Read {0} bytes (expecting {1}) at {2:X}",
bytesRead,
buffer.Length,
nextAddress.ToInt64()));
}
}
else
{
throw new InvalidOperationException(String.Format(
#"Could not read {0} bytes at {1:X}",
buffer.Length,
nextAddress.ToInt64()));
}
}
return tmp;
Related
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
namespace BaseAddress
{
class Program`enter code here`
{
[DllImport("kernel32.dll")]
public static extern bool WriteProcessMemory(int hProcess, Int64 lpBaseAddress, byte[] lpBuffer,
int nSize, ref int lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(int hProcess,
Int64 lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);
const int PROCESS_WM_ALL = 0xFFFF;
static void Main(string[] args)
{
Process[] process = Process.GetProcessesByName("Notepad");
Console.WriteLine(GetBase("Notepad"));
Console.WriteLine(GetAdd("Notepad",FromHex("59-00-6F-00-59-00"));
}
public static long GetAdd(string app, byte[] findthis)
{
byte[] buffer = new byte[findthis.Length];
int bytesRead = 0;
long foundAddr = 0;
Process[] processes = Process.GetProcessesByName(app);
Process process = processes[0];
IntPtr procHandle = OpenProcess(PROCESS_WM_ALL, false, process.Id);
long addr = 13188986418;
Console.WriteLine(addr);
Console.WriteLine("Starting address 0x{0}", (addr).ToString("X"));
bool ret2 = ReadProcessMemory((int)procHandle, addr, buffer, buffer.Length, ref bytesRead);
string p = BitConverter.ToString(buffer,0);
string tmp = BitConverter.ToString(findthis, 0);
Console.WriteLine(p);
Console.WriteLine(tmp);
if (p == tmp)
{
foundAddr = addr;
Console.WriteLine("Found it at 0x{0}", foundAddr.ToString("X"));
} else
{
Console.WriteLine("NO");
}
return foundAddr;
}
static long GetBase(string app)
{
long add = 0;
using (Process proc = new Process())
{
Process[] processes = Process.GetProcessesByName(app);
ProcessModule pm;
ProcessModuleCollection pmc = processes[0].Modules;
for (int i = 0; i < pmc.Count; i++)
{
pm = pmc[i];
if(pm.ModuleName.Replace(".exe","") == processes[0].ProcessName)
{
add = pm.BaseAddress.ToInt64();
}
}
}
return add;
}
public static byte[] FromHex(string hex)
{
hex = hex.Replace("-", "");
byte[] raw = new byte[hex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return raw;
}
So what I'm trying to do is create a function that I can provide the process name ("Notepad" in this example) and a byte array (in hex) and then the program scans the process in memory, finds the first instance of the matching array, and provides the address of it.
This works for finding a byte array BUT i have to hard code the starting point
what i don't understand is how the base address is 140696861212672 (dec)
yet the address where the code actually is is 13188986418 (dec)
This is the console output:
140696861212672
13188986418
Starting address 0x3121FF632
59-00-6F-00-59-00
59-00-6F-00-59-00
Found it at 0x3121FF632
13188986418
Any idea how i can get this to start at the start of the memory, skip empty zones in memory and loop a chunk of byte array until the array is found?
Hope that makes sense. Any help is welcome.
I am new to C# and I am experiencing an issue when trying to display the value of a memory address.
This is the pointer and offset I am trying to get working:
Link to Cheat Engine Image
When I read the address "0x005040E8" with no offset I receive the correct value in the console:
Console result below:
Last Error: 0
Memory address 0x5040E8
Memory value 13828056
When I add an offset I receive a 16 length address which naturally has no value.
Console result below:
Last Error: 0
Memory address 0xCA0FE800D41E70
Memory value 0
Here is my code attempting to find the value of 0x005040E8 with an offset of 0x00011E98:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ConsoleApp3
{
using memoryTest;
class Program
{
static unsafe void Main(string[] args)
{
Process proc = Process.GetProcessesByName("testApp")[0];
var hProc = memapi.OpenProcess(memapi.ProcessAccessFlags.All, false, proc.Id);
var modBase = memapi.GetModuleBaseAddress(proc, "testApp");
//var modBase2 = memapi.GetModuleBaseAddress(proc.Id, "testApp");
var memoryAddr = memapi.FindDMAAddy(hProc, (IntPtr)(0x005040E8), new int[] { 0x00011E98 });
System.Console.WriteLine("Last Error: " + Marshal.GetLastWin32Error());
Console.WriteLine("Memory address " + "0x" + memoryAddr.ToString("X"));
var buffer = new byte[IntPtr.Size];
memapi.ReadProcessMemory(hProc, memoryAddr, buffer, buffer.Length, out var read);
Console.WriteLine("Memory value " + BitConverter.ToInt32(buffer, 0));
Console.ReadKey();
}
}
}
Here are the relevant functions:
public static extern bool ReadProcessMemory(
IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesRead);
public static IntPtr GetModuleBaseAddress(int procId, string modName)
{
IntPtr modBaseAddr = IntPtr.Zero;
IntPtr hSnap = CreateToolhelp32Snapshot(SnapshotFlags.Module | SnapshotFlags.Module32, procId);
if (hSnap.ToInt64() != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry = new MODULEENTRY32();
modEntry.dwSize = (uint)Marshal.SizeOf(typeof(MODULEENTRY32));
if (Module32First(hSnap, ref modEntry))
{
do
{
if (modEntry.szModule.Equals(modName))
{
modBaseAddr = modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, ref modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
public static IntPtr FindDMAAddy(IntPtr hProc, IntPtr ptr, int[] offsets)
{
var buffer = new byte[IntPtr.Size];
foreach (int i in offsets)
{
ReadProcessMemory(hProc, ptr, buffer, buffer.Length, out
var read);
ptr = (IntPtr.Size == 4) ? IntPtr.Add(new IntPtr(BitConverter.ToInt32(buffer, 0)), i) : ptr = IntPtr.Add(new IntPtr(BitConverter.ToInt64(buffer, 0)), i);
}
return ptr;
}
I do not believe using a base address is needed, I have tried FindDMAAddy(hProc, (IntPtr)(modebase + 0x005040E8), new int[] { 0x00011E98 }); but it still failed. Any help would be greatly appreciated.
Newbie to C#. I have written a WDF driver and DLL that work. I am creating an application in C# to access the hardware through the DLL. There is a specific function that is causing an ExecutionEngineException soon after it is first called. Here is the function definition from the DLL:
DECLDIR int ReadDatagram(int channel, unsigned long *msgID, unsigned int *msgType, int *msgLen, unsigned int *data);
In my C# application code, I import this function with the following lines:
[DllImport("pcmcanDLL.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
internal static extern int ReadDatagram(int channel, ref uint msgID, ref uint msgType, ref int msgLen, uint[] data);
When I start the application and open a channel, this function is periodically called by a timer. After a short indefinite time, I get the following exception message. If I comment out he call of this function, the application never has an issue.
Mesage: An unhandled exception of type 'System.ExecutionEngineException' occurred in mscorlib.dll
My application code is here. I believe I am handling the pointer arguments correctly because occasionally this will work a few times and the data is good in those ceases. Appreciate any insights.
private void rcvTimer_Tick(object sender, EventArgs e)
{
int channel = 1;
String dsplyString = "Packet Received\n";
uint msgID = 0, msgType = 0;
int msgLen = 0;
uint[] data = new uint[8];
ErrorTypes dllReturn = ErrorTypes.RCV_BUFFER_EMPTY;
do
{
dllReturn = (ErrorTypes)NativeMethods.ReadDatagram(channel, ref msgID, ref msgType, ref msgLen, data);
if (dllReturn != ErrorTypes.SUCCESS && dllReturn != ErrorTypes.RCV_BUFFER_EMPTY)
{
MessageBox.Show("Error receiving packet.", "Receipt Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
else if (dllReturn == ErrorTypes.SUCCESS)
{
dsplyString = String.Format("{0} {1} {2} {3}\n", channel, msgID, msgType, msgLen);
}
} while (dllReturn != ErrorTypes.RCV_BUFFER_EMPTY);
}
Try following
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
}
}
public enum ErrorTypes : int
{
RCV_BUFFER_EMPTY = 0,
SUCCESS = 1
}
public class Test
{
[DllImport("pcmcanDLL.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
internal static extern int ReadDatagram(int channel, ref uint msgID, IntPtr msgType, ref int msgLen, IntPtr dataPtr);
private void rcvTimer_Tick(object sender, EventArgs e)
{
int channel = 1;
String dsplyString = "Packet Received\n";
uint msgID = 0;
uint msgType = 0;
int msgLen = 0;
uint[] data = new uint[8];
ErrorTypes dllReturn = ErrorTypes.RCV_BUFFER_EMPTY;
IntPtr dataPtr = Marshal.AllocHGlobal(Marshal.SizeOf(data));
IntPtr msgTypePtr = Marshal.AllocHGlobal(Marshal.SizeOf(msgType));
do
{
Marshal.StructureToPtr(msgType, msgTypePtr, true);
Marshal.StructureToPtr(data, dataPtr, true);
dllReturn = (ErrorTypes)ReadDatagram(channel, ref msgID, msgTypePtr, ref msgLen, dataPtr);
if (dllReturn != ErrorTypes.SUCCESS && dllReturn != ErrorTypes.RCV_BUFFER_EMPTY)
{
MessageBox.Show("Error receiving packet.", "Receipt Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
else if (dllReturn == ErrorTypes.SUCCESS)
{
dsplyString = String.Format("{0} {1} {2} {3}\n", channel, msgID, msgType, msgLen);
}
} while (dllReturn != ErrorTypes.RCV_BUFFER_EMPTY);
Marshal.FreeHGlobal(dataPtr);
Marshal.FreeHGlobal(msgTypePtr);
}
}
}
This returns an integer from my program which calculates the total amount of experience in the game. It's operational, and it works.
class Program
{
[DllImport("kernel32.dll")]
public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
[In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);
static void Main(string[] args)
{
int add_base;
int add_player_exp = 0x3C1200;
Process p = Process.GetProcessesByName("Game")[0];
if (p != null)
{
add_base = p.MainModule.BaseAddress.ToInt32();
add_player_exp += add_base;
string output;
int exp;
exp = ReadInt32(p.Handle, add_player_exp);
output = String.Concat("Exp: ", exp.ToString());
Console.WriteLine(output);
Console.ReadKey();
}
}
private static int ReadInt32(IntPtr handle, long address)
{
return BitConverter.ToInt32(ReadBytes(handle, address, 4), 0);
}
private static byte[] ReadBytes(IntPtr handle, long address, uint bytesToRead)
{
IntPtr ptrBytesRead;
byte[] buffer = new byte[bytesToRead];
ReadProcessMemory(handle, new IntPtr(address), buffer, bytesToRead, out ptrBytesRead);
return buffer;
}
}
What is the equivalent code to retrieve a string from ReadProcessMemory?
To read a null terminate string regular c string (char array) from memory:
public static string ReadNullTerminatedString(IntPtr handle, IntPtr addr, int maxlength)
{
var bytearray = new byte[maxlength];
IntPtr bytesread = IntPtr.Zero;
ReadProcessMemory(handle, addr, bytearray, maxlength, out bytesread);
int nullterm = 0;
while (nullterm < bytesread.ToInt64() && bytearray[nullterm] != 0)
{
nullterm++;
}
string s = Encoding.ASCII.GetString(bytearray, 0, nullterm);
return s;
}
I've got a super simple program. My intention is to copy standard input to standard output. Here's the source code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace LALA
{
class LALA
{
static void Main()
{
int bufferSize = 40;
Console.OpenStandardInput().CopyTo(Console.OpenStandardOutput(), bufferSize);
}
}
}
If I set bufferSize to 40, then for any input I just see 'C o n', 'C o n s', or 'C o n s o l e' etc.
If I set bufferSize to 41, then everything is fine.
My question is am I doing something wrong, and by accident values above 41 work?
To clarify, this is the output when I type asd:
c:\some_path>ConsoleApplication2.exe
asd
C o n
Surprise! This appears to be internal buffer overflow and I'll share what I found, though it's not yet a real proof it makes sense to me.
The code for CopyTo method of the Stream class is: (taken with reflector)
public void CopyTo(Stream destination, int bufferSize)
{
//bunch of non relevant validations...
this.InternalCopyTo(destination, bufferSize);
}
Now the code for InternalCopyTo is:
private void InternalCopyTo(Stream destination, int bufferSize)
{
byte[] array = new byte[bufferSize];
int count;
while ((count = this.Read(array, 0, array.Length)) != 0)
{
destination.Write(array, 0, count);
}
}
The console stream instance is of type __ConsoleStream (sealed internal class in System.IO) and its Read method code:
public override int Read([In] [Out] byte[] buffer, int offset, int count)
{
//bunch of non relevant validations...
int errorCode = 0;
int num = __ConsoleStream.ReadFileNative(this._handle, buffer, offset, count, 0, out errorCode);
if (num == -1)
{
__Error.WinIOError(errorCode, string.Empty);
}
return num;
}
And finally ReadFileNative code of __ConsoleStream:
private unsafe static int ReadFileNative(SafeFileHandle hFile, byte[] bytes, int offset, int count, int mustBeZero, out int errorCode)
{
if (bytes.Length - offset < count)
{
throw new IndexOutOfRangeException(Environment.GetResourceString("IndexOutOfRange_IORaceCondition"));
}
if (bytes.Length == 0)
{
errorCode = 0;
return 0;
}
__ConsoleStream.WaitForAvailableConsoleInput(hFile);
int result;
int num;
fixed (byte* ptr = bytes)
{
num = __ConsoleStream.ReadFile(hFile, ptr + (IntPtr)offset / 1, count, out result, Win32Native.NULL);
}
if (num != 0)
{
errorCode = 0;
return result;
}
errorCode = Marshal.GetLastWin32Error();
if (errorCode == 109)
{
return 0;
}
return -1;
}
The ReadFile method is low level call:
[DllImport("kernel32.dll", SetLastError = true)]
private unsafe static extern int ReadFile(SafeFileHandle handle, byte* bytes, int numBytesToRead, out int numBytesRead, IntPtr mustBeZero);
My assumption at this point is that behind the scenes, 40 bytes are "reserved" somewhere to internal data so if the buffer is not more than that, you will see that reserved data which in this case of console application is the process name.
I will keep investigating this when I'll have more time and try to reproduce, this case is quite special since both streams point to the same "file" so you can write to it while reading it.