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);
}
Related
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.
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?
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.
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.
I'm trying to write a DWORD to registry using c#.
Using p/invoke because of registry reddirection.
I've searched for this issue and finally could get it working but i don't understand.
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint RegSetValueEx(
IntPtr hKey,
[MarshalAs(UnmanagedType.LPStr)]
string lpValueName,
int Reserved,
RegistryValueKind dwType,
ref IntPtr lpData,
int cbData);
int checkreturn = RegOpenKeyEx(HKeyLocalMachine, #"SOFTWARE\Test", 0, (int) RegistrySecurity.KEY_WOW64_64KEY | (int) RegistrySecurity.KEY_SET_VALUE, ref keyHandle);
const int dataStored = 0;
IntPtr p = new IntPtr(dataStored);
int size = Marshal.SizeOf(dataStored);
uint checkreturn2 = RegSetValueEx(keyHandle, "valueName", 0, RegistryValueKind.DWord, ref p, size);
This works if i put out or ref on lpData parameter, if i don't it returns error 998 (ERROR_NOACCESS), why is that? The same thing happens if i change the IntPtr to int, and pass the actual value, but this time i get an first exception AccessViolation on my code.
the winapi declaration for that it's *lpData, which i assume is what passing a IntPtr is.
_In_ const BYTE *lpData,
The api requires a pointer to the data plus the size of the data. You can't pass an int, or a char, or a bool. You need to pass a pointer to the data. If you pass something else, the API will interpret it as a pointer to the data, and random results will happen.
With P/Invoke, a ref to something is translated to a pointer to that something.
Now, you can
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint RegSetValueEx(
IntPtr hKey,
[MarshalAs(UnmanagedType.LPStr)]
string lpValueName,
int Reserved,
RegistryValueKind dwType,
ref uint lpData,
int cbData);
and then in cbData pass sizeof(uint) and this will work, because a ref for P/Invoke is a ref.
Only thing, I would suggest removing the
[MarshalAs(UnmanagedType.LPStr)]
because without it the P/Invoke will use the Unicode version of the method, that is more correct.