64bit ReadProcessMemory access denied - c#

I've tried running this with Process.EnterDebugMode(), but it also doesn't work.
I want to read out the Notepad-memory but I don't know how to access it, or if the 64bit system is doing troubles.
This is what I've done:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
public class MemoryRead
{
[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
static extern bool ReadProcessMemory(int hProcess, Int64 lpBaseAddress, byte[] buffer, int size, ref int lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
static extern bool CloseHandle(IntPtr hObject);
static void Main(string[] args)
{
var pid = 10956; //notepad.exe
var processHandle = OpenProcess(0x10, false, pid);
byte[] buffer = new byte[24];
int bytesRead = 0;
ReadProcessMemory((int)processHandle, 0x21106B35770, buffer, buffer.Length, ref bytesRead); //0x21106B35770 is the address where "hello world" is written in notepad
Console.WriteLine(Encoding.Unicode.GetString(buffer) +
" (" + bytesRead.ToString() + "bytes)");
Console.ReadLine();
CloseHandle(processHandle);
Console.ReadLine();
}
}

Your PInvoke declaration of ReadProcessMemory is incorrect (though it should work on a 32 bit system).
As can be seen from the native declaration of this function
BOOL WINAPI ReadProcessMemory(
_In_ HANDLE hProcess,
_In_ LPCVOID lpBaseAddress,
_Out_ LPVOID lpBuffer,
_In_ SIZE_T nSize,
_Out_ SIZE_T *lpNumberOfBytesRead
);
its first parameter is HANDLE, and it is a PVOID:
A pointer to any type.
This type is declared in WinNT.h as follows:
typedef void *PVOID;
And pointer to anything in 64-bit process is a 64-bit value - IntPtr.
Basically the same goes to the size and lpNumberOfBytesRead parameters - they are 64 bit as well in a 64 bit process.
Thus your declaration should be something like:
[[DllImport("kernel32.dll", SetLastError = true)]]
[return: MarshalAs(UnmanagedType.Bool)]
static extern Boolean ReadProcessMemory(
[In] IntPtr hProcess,
[In] IntPtr lpBaseAddress,
[Out] Byte[] lpBuffer,
[In] UIntPtr nSize,
[Out] out UIntPtr lpNumberOfBytesRead
);
P.S.: And a bit of shameless self-promotion - if you ever have to work a lot with PInvoke, then there are a few good recommendations I've learned a hard way.

Related

Reading memory from another process on Mac

I'm building a library for reading memory that I'd like to expand to Mac OS.
Among many other functions, the one main function used by many of the methods is ReadProcessMemory;
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ReadProcessMemory(
[In] IntPtr hProcess,
[In] IntPtr lpBaseAddress,
[Out] byte[] lpBuffer,
[In] SIZE_T nSize,
[Out] out SIZE_T lpNumberOfBytesRead
);
I'm now wondering what the equivalent for this is on Mac. Looking around online (of course it's hardly documented at all), I think the method signature should look something like this;
[DllImport("...")]
[return: MarshalAs(UnmanagedType.I4)]
static extern int vm_read_overwrite(
[In] IntPtr target_task,
[In] IntPtr address,
[In] SIZE_T size,
[Out] byte[] data,
[Out] out SIZE_T outsize
);
vm_read_overwrite is also what's used by several Rust libraries.
What library/package is vm_read_overwrite part of? Is the signature correct? Perhaps additionally, can I use conditional compilation to use the different functions, or do I have to use RuntimeInformation.IsOSPlatform?
[DllImport("libc")]
static extern int vm_read_overwrite(
[In] IntPtr target_task,
[In] IntPtr address,
[In] uint size,
[Out] byte[] data,
[Out] out uint outsize
);
This works on my machine. Hope it helps.

SetFilePointer Strange Issue

I am trying to read sector from physical drive. but set file pointer is giving some strange error after some time
[DllImport("kernel32.dll", EntryPoint = "SetFilePointer", CallingConvention = CallingConvention.StdCall)]
static extern uint SetFilePointer(
[In] IntPtr hFile,
[In] int lDistanceToMove,
[In,Out] int lpDistanceToMoveHigh,
[In] EMoveMethod dwMoveMethod);
public void SetFilePointer(LARGE_INTEGER li)
{
SetFilePointer((IntPtr)handle, li.LowPart, li.HighPart, EMoveMethod.Begin);
}
//values
HighPart 381 int
LowPart -1323466752 int
If passed highPart as zero then its working . in C version its able to download without any issue. but in c# version when ever highvalue is not zero it gives exception.
Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
can you please suggest any correction
Update solved
as #mjwills suggested i have to change the signature to
[DllImport("kernel32.dll", EntryPoint = "SetFilePointer")]
static extern uint SetFilePointer(
[In] Microsoft.Win32.SafeHandles.SafeFileHandle hFile,
[In] int lDistanceToMove,
[In, Out] ref int lpDistanceToMoveHigh,
[In] EMoveMethod dwMoveMethod);
public void SetFilePointer(LARGE_INTEGER li)
{
SetFilePointer(shandle, li.LowPart, ref li.HighPart, EMoveMethod.Begin);
}

Wlanapi.dll Entrypoint not found exception

When I try to invoke WlanOpenHandle method of wlanapi.dll, code throws EntryPointNotFoundException.
C#:
[DllImport("wlanapi.dll", SetLastError = true)]
public static extern uint WlanOpenHandle([In] UInt32 clientVersion, [In, Out] IntPtr pReserved, [Out] out UInt32 negotiatedVersion, [Out] out IntPtr clientHandle);
C#:
uint dwClientVersion = 1;
IntPtr pReserved = IntPtr.Zero;
uint pdwNegotiatedVersion;
IntPtr phClientHandle;
var result = WlanOpenHandle(dwClientVersion, pReserved, out pdwNegotiatedVersion, out phClientHandle);
The web site says that entry point exist. What is the missing part?

Memory address from string

I have function to write memory, but I want to import address from string, how to do this?
Code:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(int hProcess, int lpBaseAddress,
byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesWritten);
and this:
WriteProcessMemory((int)processHandle, 0xffffffff, buffer, buffer.Length, ref bytesWritten);
I want to replace this "0xffffffff" to string, but I don't know how to do this. I try convert string with address to int, but this not working.
Use something like:
string str = "0xffffffffffffffff";
if (str.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
{
str = str.Substring(2);
}
IntPtr ptr = (IntPtr)long.Parse(str, NumberStyles.HexNumber);
Note that long.Parse doesn't support the 0x, so if present I remove it.
I'm using the long.Parse to support 64bit systems and 32bits systems.
Note that the PInvoke signature you are using is wrong... It will work for 32 bits, but the general one compatible with 32 and 64 bits is:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
IntPtr dwSize,
out IntPtr lpNumberOfBytesWritten);
If you need to manipilate the IntPtr you should always convert them to long, because a IntPtr can be 32 or 64 bits, so a long can always contain it.

PInvoke WPF HWND and const void*

I need to use the following C++ function in my WPF application:
/****************************************
* BOOL WINAPI SetWindowFeedbackSetting(
* _In_ HWND hwnd,
* _In_ FEEDBACK_TYPE feedback,
* _In_ DWORD dwFlags,
* _In_ UINT32 size,
* _In_opt_ const VOID *configuration
*);
*****************************************/
But I'm not sure how to Marshal it and how to PInvoke it. This is what I have so far:
public enum FEEDBACK_TYPE : uint {
FEEDBACK_TOUCH_CONTACTVISUALIZATION = 1,
FEEDBACK_PEN_BARRELVISUALIZATION = 2,
FEEDBACK_PEN_TAP = 3,
FEEDBACK_PEN_DOUBLETAP = 4,
FEEDBACK_PEN_PRESSANDHOLD = 5,
FEEDBACK_PEN_RIGHTTAP = 6,
FEEDBACK_TOUCH_TAP = 7,
FEEDBACK_TOUCH_DOUBLETAP = 8,
FEEDBACK_TOUCH_PRESSANDHOLD = 9,
FEEDBACK_TOUCH_RIGHTTAP = 10,
FEEDBACK_GESTURE_PRESSANDTAP = 11,
FEEDBACK_MAX = 0xFFFFFFFF
}
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)] // (1)
public static extern bool SetWindowFeedbackSetting(
[In] IntPtr hwnd,
[In] FEEDBACK_TYPE feedback,
[In] uint dwFlags,
[In] uint size, // (2)
[In, Optional] IntPtr configuration // (3)
);
So first, is (1),(2),(3) correct?
Second, if I want to PInvoke this function according to this C++ function call:
BOOL fEnabled = FALSE;
BOOL res = SetWindowFeedbackSetting(
hwnd,
FEEDBACK_TOUCH_CONTACTVISUALIZATION,
0,
sizeof(fEnabled),
&fEnabled
);
What it the way to send the HWND and the boolean?
I'm asking this question to better understand the pinvoke\Marshal mechanism and also since the way I tried is not working.
Thanks
Your translation is accurate. But personally, for convenience, I'd make one overload for each type you need to use. For a boolean:
[DllImport("user32.dll"])
public static extern bool SetWindowFeedbackSetting(
IntPtr hwnd,
FEEDBACK_TYPE feedback,
uint dwFlags,
uint size,
[In] ref bool configuration
);
I removed the attributes that were not needed because they restate default values.
Remember that the Win32 BOOL type, the default marshalling option for C# bool is a 4 byte type. So you must pass 4 as the size.
See this question to learn how to obtain a window handle for your WPF window: How to get the hWnd of Window instance?
From what I remember, P/Invoke mechanism has problems with passing/returning .NET's bool. I'd do:
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)] // (1)
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowFeedbackSetting(
[In] IntPtr hwnd,
[In] FEEDBACK_TYPE feedback,
[In] uint dwFlags,
[In] uint size, // (2)
[In, Optional] IntPtr configuration // (3)
);
Then, you have to get HWND for current window in WPF. This question: How to get the hWnd of Window instance? should help in this matter.
For your convenience:
Window window = Window.GetWindow(this);
var wih = new WindowInteropHelper(window);
IntPtr hWnd = wih.Handle;
(credit goes to Drahcir)
Finally, to get address of the boolean, I'd do the following:
int myBool; // Win32's BOOL is actually an 4-byte integral number, 0 or non-zero
GCHandle handle = GCHandle.Alloc(myBool, GCHandleType.Pinned);
try
{
IntPtr ptr = handle.AddrOfPinnedObject();
// use ptr
}
finally
{
handle.Free();
}

Categories

Resources