Error read addres with function ReadProcessMemory c# - c#

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'.

Related

C# ReadProcessMemory

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.

Edit Memory Address via c#

i want to edit an active app (edit a memory address),
on address 00498D45 i want to edit its value
currect value :
MOV BYTE PTR SS:[EBP-423],7
to
updated value:
MOV BYTE PTR SS:[EBP-423],8
what i got till now is this (searched about it on the net and this how far i got):
thanks in advance!
using System.Runtime.InteropServices;
[Flags]
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VMOperation = 0x00000008,
VMRead = 0x00000010,
VMWrite = 0x00000020,
DupHandle = 0x00000040,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
Synchronize = 0x00100000
}
[DllImport("kernel32.dll")]
private static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out int lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
public static extern Int32 CloseHandle(IntPtr hProcess);
Process process = Process.GetProcessesByName("My Apps Name").FirstOrDefault();
public static bool WriteMemory(Process process, int address, long value, out int bytesWritten)
{
IntPtr hProc = OpenProcess(ProcessAccessFlags.All, false, process.Id);
byte[] val = BitConverter.GetBytes(value);
bool worked = WriteProcessMemory(hProc, new IntPtr(address), val, (UInt32) val.LongLength, out bytesWritten);
CloseHandle(hProc);
return worked;
}
From your other question:
WriteMemory(Process process,00498D45 , MOV BYTE PTR SS:[EBP-423],8)
There are so many problems with this, I don't know where to begin. First of all, that's not anywhere near correct C# syntax.
You're calling a function, but you have Process there like it's a signature.
00498D45 is not a valid constant in any base. If you mean hex, (which you probably do since you're dealing with addresses) then like all other C-like languages, that should be expressed as 0x00498D45.
That's x86 assembly code in ASCII (but it's not in a string, you just have a mess). You can't just plop ASCII assembly code into another process's address space!
Perhaps you should do a little more research on how compilation, and assembly work when building a program, and the guts of what your CPU is actually doing when it's executing a program. Also, I recommend reading through the sample code you've very obviously taken from somewhere and try to understand it. You'll be way better off learning what's going on, than asking everyone to help fix the stuff you've cobbled together. </rant>
Anyway, after you assemble your code, it looks like this (re dis-assembled):
C68559FEFFFF08 mov byte [ebp-0x1a7],0x8
That means that your instruction is actually the string of bytes C6 85 59 FE FF FF 08. So that is what you need to write into your target application.
This is the basis of what you're trying to do:
byte[] new_instr = new byte[] {0xC6, 0x85, 0x59, 0xFE, 0xFF, 0xFF, 0x08};
IntPtr target_addr = (IntPtr)0x00498D45;
int bytesWritten;
WriteProcessMemory(hProcess, target_addr, new_instr, (UInt32)new_instr.Length, out bytesWritten);
The WriteMemory memory function you've copy-and-pasted won't help you here. The problem is, it only writes a long which is 4 bytes. You need to write 7 bytes. So you'll either have to modify that function to use a byte[] parameter, or do it yourself.
I admire your ambition, but you should really start a bit lower. Write some C# code to get yourself familiar with programming in a C-like language. Then write some C to get familiar with crashing when you don't do things perfectly. Then try dabbling in assembly - perhaps writing small inline pieces into your C code. Finally then, you'll be ready to go hacking around the instructions of other running processes.
You can use an injection library like MemorySharp (I'm the author). All these functions are wrapped within a handy API, integrating an assembler (FASM syntax). Thus this piece of code perform what you want :
using (var m = new MemorySharp(ApplicationFinder.FromProcessName("My App").First()))
{
m.Assembly.Inject("MOV BYTE [EBP-423],8", new IntPtr(0x00498D45));
}

C# ReadProcessMemory - Accessing/Reading Pointers

I have the code to read a value from Memory which works when the memory address points to a static 4 byte value, but i'm trying to access a 4 byte value which is in a dynamic location and so need to search for the pointer first then search again to get the 4 byte value.
Below is the code I have which should return the address of the Pointer but it just outputs 0...
bAddr = (IntPtr)0x0017C370; // Base address to find the Pointer (Currently: 0x00267A50)
ReadProcessMemory(hProc, bAddr, buffer, 4, out bytesRW);
output = BitConverter.ToInt32(buffer, 0);
txtOutput.Text = output.ToString();
Pseudo code I see working as:
bAddr = (IntPtr)0x0017C370; // Base address to find the Pointer (Currently: 0x00267A50)
ReadProcessMemory(hProc, bAddr, buffer, 4, out bytesRW);
output = BitConverter.ToInt32(buffer, 0);
bAddr = (IntPtr)output; // Should now contain the address 0x00267A50
ReadProcessMemory(hProc, bAddr, buffer, 4, out bytesRW);
output = BitConverter.ToInt32(buffer, 0);
txtOutput.Text = output.ToString();
Can anyone shed any light on to what I need to be doing to find an address and then search for that address to find a value?
This is a pretty classical mistake when using pinvoke to execute Win32 functions, you are not doing any error checking. So any failure is undiagnosable. First make sure you declared it properly:
[DllImport("user32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
[In, Out] byte[] buffer, IntPtr size, out IntPtr lpNumberOfBytesRead);
Then execute it like this:
bool ok = ReadProcessMemory(...);
if (!ok) throw new System.ComponentModel.Win32Exception();
Now you'll know why it doesn't work. We can't otherwise help you figure out what goes wrong until you've at least tested it this way. The most basic problem is guessing the address wrong of course. And not having enough privileges, ReadProcessMemory is a highly privileged function for obvious reasons.

How to get all memory address space used by a process?

I need to know all memory address space used by a process. The memory space will later be scanned to locate values within the process and identify their locations / addresses. My current process for this is to take each module's base address through its (base address + memory size).
I'm testing this on a process with a known value at a known address. When I look up that specific address, I get the value I expect. However, when I scan (what I believe to be) all address space used by the process, I can't find the value anywhere.
I know that a numeric value "4143000" exists at 0x0CF8DC38 and 0x0CF8DDDC. When I call ReadMemoryBytes(module, module.BaseAddress, 4, (IntPtr)(0x0CF8DC38)) I get back bytes (152, 55, 63, 0). When I call BitConverter.GetBytes(4143000) I get back the same set of bytes. When I use a different memory scanner on that process, I find that value at those addresses.
However, when I scan the "known addresses", I don't find this value anywhere. It doesn't look like my code is even finding those addresses in use by the process.
Thusly, my question is twofold:
How can I find these addresses within this process?
I'm concerned I may be dealing with absolute addresses in system memory versus relative addresses within a process. Am I doing this right?
.
// (in the calling method)
foreach (ProcessModule module in process.Modules) {
ParameterizedThreadStart pst = new ParameterizedThreadStart(p => SearchModule(module, value));
Thread t = new Thread(pst);
t.Start(); }
private unsafe void SearchModule(ProcessModule module, string value)
{
Process process = getProcess;
int iVal;
double dVal;
int.TryParse(value, out iVal);
double.TryParse(value, out dVal);
for (Int64 addr = (Int64)module.BaseAddress; addr + value.Length < (Int64)module.BaseAddress + module.ModuleMemorySize; addr++)
{
// Compare ints
if (iVal > 0)
{
byte[] ExpectedBytes = BitConverter.GetBytes(iVal);
byte[] ActualBytes = ReadMemoryBytes(module, (IntPtr)addr, (uint)ExpectedBytes.Length, (IntPtr)addr);
bool isMatch = true;
for (int i = 0; i < ExpectedBytes.Length; i++)
if (ExpectedBytes[i] != ActualBytes[i])
isMatch = false;
if (isMatch)
PossibleAddresses.Add((IntPtr)addr);
}
}
private byte[] ReadMemoryBytes(ProcessModule mod, IntPtr memAddress, uint size, IntPtr BaseAddress)
{
byte[] buffer = new byte[size];
IntPtr bytesRead;
unsafe
{
ReadProcessMemory(processPointer, BaseAddress, buffer, size, out bytesRead);
return buffer;
}
}
[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);
The addresses you're getting are pointers to the managed (CLR) heap. They won't generally map to absolute memory addresses and they can move from call to call as the GC decides to run.
If you use "unsafe" code, you can get relative pointers as well as managing your own memory space. It's still on the heap but at least you're guaranteed the GC won't modify your address space.
Do not expect to be able to access things on the heap from non-CLR code without extensive wrapping. There are ways to do IPC between CLR-managed processes but you'd have to write access proxies to the "outside world" if you want a non-CLR process to get to your memory.

C++ function calling from C# application. Attempted to read or write protected memory

The problem below is ralated to my previous question
Converting static link library to dynamic dll
My first step was to develop a dll, that was done. (Thanks John Knoeller prakash. Your input was very helpful)
Now when i call the function in the dll from my c# application i get the error
"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
Here is the C++ definition
extern "C" DEMO2_API void Decompress(char* inp_buff, unsigned short*
inp_len, char* buffer_decomp,unsigned *output_len,unsigned short* errorCode);
My C# Converstion p/Involke
private static extern void Decompress(
byte[] inp_buff,
ref ushort inp_len,
byte[] buffer_decomp,
ref int output_len,
ref ushort errorCode
);
And I am calling it as below
byte[] dst = new byte[2048];
int outlen = 2048;
ushort errorCode = 0;
Decompress(src, (ushort )src.Length, dst, ref outlen,ref errorCode);
return dst;
What is wrong?
I see a signature mismatch on the inp_len parameter. In the C++ definition you use a pointer to a short unsigned int, while in the C# method you use a ushort.
for pointers you must use IntPtr .net type
#necrostaz
It is not necessary that we use IntPtr for pointers.
Look below all of these four declarations are valid and currently i am using it.
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, String lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, StringBuilder lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, String lParam);
question is still open
In addition to the missing "ref" on the inp_len declaration that Maurits pointed out, you need to make sure that your pointer sizes match.
If you're running on a 32-bit operating system you should be OK, but if your code runs on 64-bit too, then you need to ensure that either:
You mark your .net entry assembly as x86 (not Any CPU)
or
You supply a 32-bit and 64-bit build of the C++ dll and install the correct one for the interop to call.
I have had the same problem two years ago. In my case the reason for the access violation was that the memory was allocated outside the DLL. As a solution I added two functions for memory allocation and deallocation to the DLL.
Another solution could be a change of the .net security settings. Some keywords are "Code Access Security Police Tool" (caspol.exe) and ".NET Framework Configuration Tool" (mscorcfg.msc). In VS there is also a security tab in the project property dialog. I'm not an expert in .net security so someone else should know more details.
The following code runs without any problems. It's very similar to yours:
C++:
extern "C" __declspec(dllexport) void TestFunction(char* inp_buff,
unsigned short* inp_len,
char* buffer_decomp,
unsigned *output_len,
unsigned short* errorCode)
{
//copy input buffer to output buffer
int size = min(*inp_len,*output_len);
for(int i=0; i<size; i++)
buffer_decomp[i] = inp_buff[i];
errorCode = 0;
}
C#:
using System;
using System.Runtime.InteropServices;
class Program
{
[DllImport("TEST.DLL")]
public static extern void TestFunction(byte[] inp_buff,
ref ushort inp_len,
byte[] out_buff,
ref int out_len,
ref ushort errorCode);
static void Main(string[] args)
{
//prepare input buffer
byte[] inp_buff = new byte[20];
inp_buff[0] = (byte)'T';
inp_buff[1] = (byte)'E';
inp_buff[2] = (byte)'S';
inp_buff[3] = (byte)'T';
ushort inp_len = (ushort)inp_buff.Length;
//prepare output buffer
byte[] out_buff = new byte[20];
int out_len = out_buff.Length;
ushort errorCode = 0;
TestFunction(inp_buff, ref inp_len, out_buff, ref out_len, ref errorCode);
//see if copying was successful
for(int i=0; i<out_len; i++)
Console.Out.Write(out_buff[i]);
}
}
Try it out. I have taken a look at the open parts of the library you are using. Here is a direct excerpt of the function lzo_decomp:
in = lzo_malloc(IN_LEN);
out = lzo_malloc(OUT_LEN);
wrkmem = lzo_malloc(LZO1Z_999_MEM_COMPRESS);
if (in == NULL || out == NULL || wrkmem == NULL)
{
printf("out of memory\n");
}
in_len = IN_LEN;
lzo_memset(in,0,in_len );
lzo_memset ( out, 0, OUT_LEN );
memcpy ( out, &input_buffer, inp_buff_len);
lzo_free(wrkmem);
lzo_free(out);
lzo_free(in);
r = lzo1z_decompress(out,*inp_len,in,&out_len,NULL );
For serenity: "in" and "out" are not the function arguments for the input and output buffers but temporary pointers. What can you see (beside from bad formatted code)? The only two buffers lzo1z_decompress is called with are "in" and "out". And these two buffers are freed before the call. I'm not surprised that there is an access violation. I only can underline nobugz's advice: Contact the author.
The 4th parameter need to be passed using out mode instead of ref. That solved the problem.

Categories

Resources