Currently I'm writing a game trainer using C# (note that I'm only making one for fun, for a private server, and NOT for hacking the game to become the "best player ever") and it's working smoothly, but not the string.
When I write the string for the first time and I have 10 chars, it's working (it'll write for example: hellolady!). When I type 8 chars (for example hellolol) it will automatically write 10 chars, so the new string would be hellololy!.
I don't know why I get the problem, this is my WriteString:
public static bool WriteString(IntPtr handle, int address, string value)
{
int written;
byte[] data = Encoding.Default.GetBytes(value);
return WriteProcessMemory(handle, address, data, data.Length, out written);
}
My WriteProcessMemory:
[DllImport("Kernel32.dll")]
static extern bool WriteProcessMemory(IntPtr handle, int lpBaseAddress, byte[] lpBuffer, int nSize, out int lpNumberOfBytesWritten);
Hopefully somebody can help me with it.
Edit of the function which works, you have to use a null terminator at GetBytes, then it'll work.
public static bool WriteString(IntPtr handle, int address, string value)
{
int written;
byte[] data = Encoding.Default.GetBytes(value + "\0");
return WriteProcessMemory(handle, address, data, data.Length, out written);
}
Related
I have an error with reading the memory address of the game, where:
my code is this
public partial class MainWindow: Window
{
[DllImport ("kernel32.dll")]
public static extern IntPtr OpenProcess (int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport ("kernel32.dll")]
public static extern bool ReadProcessMemory (int hProcess, int lpBaseAddress, byte [] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);
const int PROCESS_WM_READ = 0x0010;
public MainWindow ()
{
arguments dir = new arguments ();
Process process = Process.GetProcessesByName (dir.proccessname) [0];
IntPtr processHandle = OpenProcess (PROCESS_WM_READ, false, process.Id);
int bytesRead = 0;
byte [] buffer = new byte [4];
ReadProcessMemory ((int) processHandle, dir.heal_Act, buffer, buffer.Length, ref bytesRead);
}
however, nothing reading appears:
in cheat engine read me the values
Read address with Cheat Engine
Where in the image appears the reading of the memory address and finally the value contained with 4 bytes in size
Read address with Cheat Engine
In addition, I do not know how the summation of the address is as shown in box 2 to obtain the contained value.
they could help me to propose the reading with the indicated address, since zero appears.
You need to run your process as administrator and you should compile this for the same architecture as the target process. If you're targetting x86, compile as x86.
Keep in mind your ReadProcessMemory define only takes 4 byte addresses as arguments, you will want to use IntPtr for the addresses so when you someday switch to x64 the args will be large enough for 64 bit pointers.
If these things don't solve your problem then you're offsets or addresses are wrong. In which case the best thing to do is to use the Visual Studio Debugger and compare what you see against what you see in Cheat Engine.
Also in your PROCESS_WM_READ you have a 'W' instead of a 'V'.
I'm basically trying to figure out how to search for a value in a process without giving an exact offset. The process can be anything (notepad, iexplorer, msword, etc.). Just looking for search a value between the first and last memory address of a process instead of giving a specific offset, which is I had to find from another application like ollydbg.
Here's what I have
const int PROCESS_WM_READ = 0x0010;
[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);
public static string search = "somestring";
static void Main(string[] args)
{
Process process = Process.GetProcessById(15728);
IntPtr processHandle = OpenProcess(PROCESS_WM_READ, false, process.Id);
int bytesRead = 0;
byte[] buffer = new byte[16];
ReadProcessMemory((int)processHandle, 0x20BC4ADE4C8, buffer, buffer.Length, ref bytesRead);
Console.WriteLine(Encoding.Unicode.GetString(buffer) +
" (" + bytesRead.ToString() + "bytes)");
if (Encoding.Unicode.GetString(buffer).Contains(somestring))
Console.WriteLine("Match");
else
Console.WriteLine("Didint Match");
Console.ReadLine();
}
You cannot avoid passing an address into ReadProcessMemory as it is required, and I don't believe there are any other APIs out there that allow you to read a process's memory.
So, what you have to do is pass in the base address. Rather than get the base address, you can calculate it yourself. This question can help.
Next you will need to find the size of the process's memory and pass that to the nSize parameter. But... that might be a bad idea because
you have to determine what that value is (I'm not sure how; you could brute force it by doing a binary search across the largest possible value and finding the largest value that doesn't force ReadProcessMemory to return false or perhaps using a performance counter or some other mechanism).
Deal with memory constraints of having to allocate a huge chunk of memory for your buffer.
So instead of reading all of the memory, make multiple calls to ReadProcessMemory with smaller buffer sizes. The algorithm could be something like
while not an error
read into a buffer, scanning it for your string
if found
return true;
bump the offset
If the above loop does not find your string, you're still not done because the string could have spanned the boundary between two buffers. To deal with this, create another loop that scan each boundary from boundary offset - string size to boundary offset + string size, returning true if found.
I have made a method that will read a multi-pointer by providing the wanted offsets + the start adress. (Code below). To summarize, Im trying to streamline this method and below I will explain my problem.
I have been strugling around with the conversion. The parameter is an IntPtr and the output of a read adress is an byte array, my first idea was: "Convert Byte array to IntPtr, reprocess it and finally convert the last read adress into a int32 (since the last adress is not a pointer it will never be read so converting here to Int32 should be allright)",
However that did not give a nice result. So currently Im stuck with the solution of converting Byte array to Int32, then Int32 to IntPtr. People do say that the bitconverter is a bad approach because it might cause issues on 64-bit platforms and I do also believe there is an approach that may give a better performence (since Im converting an object 2 times).
Finally if anyone think it would be possible to make a similar function in C++ and then P/Invoke it in C# (I guess it would be more efficient that way?) please tell me. (Im trying to adapt my programming knowledges. And find combination of languages very interesting)
[DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
[In, Out] byte[] buffer, Int32 sizeout, out IntPtr lpNumberOfBytesRead);
public Int32 ReadBytes(IntPtr Handle, IntPtr Address, int[] Offsets, int BytesToRead = 4)
{
IntPtr ptrBytesRead;
byte[] value = new byte[BytesToRead];
ReadProcessMemory(Handle, Address, value, BytesToRead, out ptrBytesRead);
//Read Offsets
for (int i = 0; i < Offsets.Length; i++)
{
ReadProcessMemory(Handle,
new IntPtr(BitConverter.ToInt32(value, 0) + Offsets[i]),
value,
BytesToRead,
out ptrBytesRead);
}
return BitConverter.ToInt32(value, 0);
}
Any ideas to streamline this method would be very well appreciated! Thanks on advance!
As #usr stated, the performance of the code will be entirely dominated by the calls to ReadProcessMemory. You should not expect to improve the performance from its current level.
However, you can make the code much easier to read by avoiding byte arrays and BitConverter. Like this:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
out IntPtr lpBuffer,
IntPtr nSize,
out IntPtr lpNumberOfBytesRead
);
private static IntPtr ReadProcessPointer(IntPtr hProcess, IntPtr Address)
{
IntPtr result;
IntPtr NumberOfBytesRead;
if (ReadProcessMemory(hProcess, Address, out result, (IntPtr)IntPtr.Size, out NumberOfBytesRead) == 0)
throw new Win32Exception();
return result;
}
public static IntPtr FollowPointers(IntPtr hProcess, IntPtr Address, int[] Offsets)
{
IntPtr ptr = ReadProcessPointer(hProcess, Address);
for (int i = 0; i < Offsets.Length; i++)
ptr = ReadProcessPointer(hProcess, ptr + Offsets[i]);
return ptr;
}
I have an API that takes three parameters:
HANDLE Connect(LPCSTR MachineName, LPCSTR ServerName, BOOL EnableDLLBuffering);
How can I use this method in C#?
What is the equivalence of LPCSTR? And what should be use in place of HANDLE?
The HANDLE equivalent is IntPtr (or you could use one of the subclasses of SafeHandle, many of which are defined in the namespace Microsoft.Win32.SafeHandles). The equivalent of LPCSTR is string or StringBuilder (but string is better, because you are passing the string to the method and the method won't modify it). You can even use a byte[] (as I have wrote you in the other response, but you must encode your string in the buffer, and add a \0 at the end... it's quite inconvenient). In the end an LPCSTR is a constant LPSTR that the method won't modify. It's better you set the CharSet.Ansi as in the other response.
[DllImport("YourDll.dll", CharSet = CharSet.Ansi)]
static extern IntPtr Connect(string machineName, string serverName, bool enableDLLBuffering);
and you call it as:
IntPtr ptr = Connect("MyMachine", "MyServer", true);
or, if you really want to do the encoding yourself:
[DllImport("YourDll.dll", CharSet = CharSet.Ansi)]
static extern IntPtr Connect(byte[] machineName, byte[] serverName, bool enableDLLBuffering);
and
public static byte[] GetBytesFromStringWithZero(Encoding encoding, string str)
{
int len = encoding.GetByteCount(str);
// Here we leave a "space" for the ending \0
// Note the trick to discover the length of the \0 in the encoding:
// It could be 1 (for Ansi, Utf8, ...), 2 (for Unicode, UnicodeBE), 4 (for UTF32)
// We simply ask the encoder how long it would be to encode it :-)
byte[] bytes = new byte[len + encoding.GetByteCount("\0")];
encoding.GetBytes(str, 0, str.Length, bytes, 0);
return bytes;
}
IntPtr ptr = Connect(
GetBytesFromStringWithZero(Encoding.Default, "MyMachine"),
GetBytesFromStringWithZero(Encoding.Default, "MyServer"),
true);
This variant is better if you have to call the method many many times always with the same strings, because you can cache the encoded versions of the string and gain something in speed (yes, normally it's an useless optimization)
According to How to map Win32 types to C# types when using P/Invoke?:
LPCSTR (C) - string (C#)
HANDLE (C) - IntPtr (C#)
I use StringBuilder:
[DllImport("user32.dll", CharSet = CharSet.Ansi)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
var sb = new StringBuilder();
var ret = GetClassName(hwnd, sb, 100);
var klass = sb.ToString();
Given the code below, ReadProcessMemory always returns an array of zeros. I'm trying to locate a string (which may be numeric) in a running process and identify all the locations where that string exists. But ReadProcessMemory always returns an array of zeros. Why is that?
I've tried running VS as administrator and removing the unsafe block.
processPointer has a correct value for the process handle.
BaseAddress does correctly iterate by one, and appears to be the memory location I'm looking for.
Despite obviously not finding any matches, it does run fairly quickly. Several seconds for a 72MB process.
.
// (other stuff in method...)
IntPtr baseAddress = process.MainModule.BaseAddress;
IntPtr lastAddress = baseAddress + process.MainModule.ModuleMemorySize;
processPointer = OpenProcess((uint)(0x0020), 1, (uint)PID);
for (int addr = (int)baseAddress; addr + value.Length < (int)lastAddress; addr++)
{
string ActualValue = ReadMemory((IntPtr)addr, (uint)value.Length, (IntPtr)addr);
if (string.IsNullOrEmpty(ActualValue)) continue;
if (ActualValue.Trim().ToLower() == value.Trim().ToLower())
PossibleAddresses.Add((IntPtr)addr);
}
// (other stuff in method...)
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 BitConverter.ToString(buffer); // always "00-00-00-00....."
}
return Encoding.Default.GetString(buffer); // Another way I tried to read the data
}
[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);
I was opening the handle with the wrong access type. 0x0010 is to read; 0x0020 is to write. I was hoping to get read/write with one open, but it looks like I'll have to handle that separately.
source: http://www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=15680