Readprocessmemory into string - c#

I know everything about process and what address i want to read, but i don't know how to use Readprocessmemory function. Do i need to add some usings or something?
I made this in C++, but how can i do it in C#?
char* ReadMemoryText(DWORD address,int size)
{
char ret[size];
DWORD processId;
HWND hwnd = FindWindow("WindowX",NULL);
if(tibia!=NULL)
{
GetWindowThreadProcessId(hwnd,&processId);
HANDLE phandle = OpenProcess(PROCESS_VM_READ, 0, processId);
if(!phandle)
{
cout<<GetLastError()<<endl;
cout <<"Could not get handle!\n";
cin.get();
}
ReadProcessMemory(phandle, (LPVOID)address, &ret,size,0);
char * rt = ret;
for(int i=0;i<size && ret[i]!=0;++i)
cout << ret[i];
return rt;
}
return NULL;
}

Here is an example of using C# that reads a char array from memory. In this case it's the local player's name string from Assault Cube.
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadProcessMemory(
IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesRead);
var nameAddr = ghapi.FindDMAAddy(hProc, (IntPtr)(modBase2 + 0x10f4f4), new int[] { 0x225 });
byte[] name = new byte[16];
ghapi.ReadProcessMemory(hProc, nameAddr, name, 16, out _);
Console.WriteLine(Encoding.Default.GetString(name));
We use pinvoke to get access to ReadProcessMemory exported from kernel32.dll
We use FindDMAAddy to get the address of the name variable. The char array is a fixed size of 16 bytes.
We use ReadProcessMemory using source and destination variables, size 16 and the last argument we just use "out _" because we don't care about bytesRead argument.
Then we need to convert that char array to a string type with proper encoding for which we use Encoding.Default.GetString().
Then write that line to the console.

Related

How to correctly marshal unsigned char* from c dll to c#

I am trying to prepare a simple GUI based AES-CMAC calculator.For this I have decided to create c dll out of open ssl libraries.[I Dont want to use .net for calculating AES-CMAC].This DLL ,I have tested with test application created in c++(console) and value generated are as per test vectors. But when I am trying to call this function from c#.I get wrong values.Here I am using byte[] instead of unsigned char*.
My code snippet for c function is
double calc_AES_CMAC(unsigned char* message ,unsigned char* key,unsigned char* cmac_16)
{
size_t mactlen;
CMAC_CTX *ctx = CMAC_CTX_new();
CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL);
CMAC_Update(ctx, message, sizeof(message));
CMAC_Final(ctx, cmac_16, &mactlen);
CMAC_CTX_free(ctx);
return 0;
}
And my calling C# code is
Firstly Function import
[DllImport("C:\\Users\\Sudhanwa\\Documents\\Visual Studio 2010\\Projects\\Ccsharpdll\\Debug\\Ccsharpdll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern double calc_AES_CMAC(byte[] message, byte[] key, byte[] output);
Secondly Button click event
byte [] null_arr = new byte[16];
// K: 2b7e1516 28aed2a6 abf71588 09cf4f3c
byte[] key = { 0x2b,0x7e,0x15,0x16,
0x28,0xae,0xd2,0xa6,
0xab,0xf7,0x15,0x88,
0x09,0xcf,0x4f,0x3c };
// M: 6bc1bee2 2e409f96 e93d7e11 7393172a Mlen: 128
byte[] message= { 0x6b,0xc1,0xbe,0xe2,
0x2e,0x40,0x9f,0x96,
0xe9,0x3d,0x7e,0x11,
0x73,0x93,0x17,0x2a };
byte [] cmac = new byte [16];
c = calc_AES_CMAC(message, key, cmac);
string ans = ByteArrayToString(cmac);
MessageBox.Show(ans);
In this code, I get 16 Byte hex output but this does not match with correct result.
You need to indicate to the marshaller that you expect that data is returned (and how much data) in the output parameter:
public static extern double calc_AES_CMAC(byte[] message, byte[] key,
[In, Out, MarshalAs(UnmanagedType.LPArray, SizeConst=16)] byte[] output);
Otherwise a copy of the current content of the array will be passed to the C++ function but any modifications will not be copied back to the C# caller.

C# Pinvoke Delphi ShortString System.AccessViolationException

My client just sent me a delphi dll to be consumed for my asp.net app, and below is the dll's signature:
function GerarChave(pChave: ShortString; pData: ShortString; pAcao: ShortString): PAnsiChar; stdcall;
How should I call it? I've tried everything like
[DllImport("CEIINT.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GerarChave")]
public static extern string GerarChave([MarshalAs(UnmanagedType.BStr)]string pChave, [MarshalAs(UnmanagedType.BStr)]string pData, [MarshalAs(UnmanagedType.BStr)]string pAcao);
string chave = "ABC123";
string data = "19/09/2019";
string acao = "0";
GerarChave(chave, data, acao);
but I always get a System.AccessViolationException error which says:
System.AccessViolationException... Attempted to read or write protected memory. This is often an indication that other memory is corrupt
Could anybody help me please? Thanks in advance!
Like David Heffernan said, you should try to get back to your client to request a DLL with more interoperable types.
If you have no other choice you could try to do the conversions manually, first by changing the signature to an byte array:
[DllImport("CEIINT.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "GerarChave")]
public static extern string GerarChave(
[MarshalAs(UnmanagedType.ByValArray, SizeConst=256)] byte[] pChave,
[MarshalAs(UnmanagedType.ByValArray, SizeConst=256)] byte[] pData,
[MarshalAs(UnmanagedType.ByValArray, SizeConst=256)] byte[] pAcao);
Then define the following method to convert a string to a Delphi ShortString:
public byte[] GetDelphiShortString(string str)
{
var bytes = new byte[256];
bytes[0] = (byte)Encoding.Default.GetBytes(str, 0, str.Length, bytes, 1);
return bytes;
}
Finally, you should be able to call the Delphi function via:
GerarChave(GetDelphiShortString(chave), GetDelphiShortString(data), GetDelphiShortString(acao));

Send raw data to print not working

I want to send raw data to print, avoiding printer selection (fast print).
I am trying to use this helper provided by Microsoft: https://support.microsoft.com/en-us/kb/322091#top
However, when I call to the method:
RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, s);
My printer starts to works (makes some noise) but It never takes the white paper and starts to print.
I have tried it with my two printers and the behavior is the same in both printers. Also I discard the possibility that the printers are broken because I can print other documents.
What can be wrong?
Try this:
using System;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class RawPrinterHelper
{
// Structure and API declarions:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class DOCINFOA
{
[MarshalAs(UnmanagedType.LPStr)] public string pDocName;
[MarshalAs(UnmanagedType.LPStr)] public string pOutputFile;
[MarshalAs(UnmanagedType.LPStr)] public string pDataType;
}
[DllImport("winspool.Drv", EntryPoint="OpenPrinterA", SetLastError=true, CharSet=CharSet.Ansi, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
[DllImport("winspool.Drv", EntryPoint="ClosePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint="StartDocPrinterA", SetLastError=true, CharSet=CharSet.Ansi, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool StartDocPrinter( IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
[DllImport("winspool.Drv", EntryPoint="EndDocPrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool EndDocPrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint="StartPagePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool StartPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint="EndPagePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool EndPagePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint="WritePrinter", SetLastError=true, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten );
// SendBytesToPrinter()
// When the function is given a printer name and an unmanaged array
// of bytes, the function sends those bytes to the print queue.
// Returns true on success, false on failure.
public static bool SendBytesToPrinter( string szPrinterName, IntPtr pBytes, Int32 dwCount)
{
Int32 dwError = 0, dwWritten = 0;
IntPtr hPrinter = new IntPtr(0);
DOCINFOA di = new DOCINFOA();
bool bSuccess = false; // Assume failure unless you specifically succeed.
di.pDocName = "My C#.NET RAW Document";
di.pDataType = "RAW";
// Open the printer.
if( OpenPrinter( szPrinterName.Normalize(), out hPrinter, IntPtr.Zero ) )
{
// Start a document.
if( StartDocPrinter(hPrinter, 1, di) )
{
// Start a page.
if( StartPagePrinter(hPrinter) )
{
// Write your bytes.
bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
// If you did not succeed, GetLastError may give more information
// about why not.
if( bSuccess == false )
{
dwError = Marshal.GetLastWin32Error();
}
return bSuccess;
}
public static bool SendFileToPrinter( string szPrinterName, string szFileName )
{
// Open the file.
FileStream fs = new FileStream(szFileName, FileMode.Open);
// Create a BinaryReader on the file.
BinaryReader br = new BinaryReader(fs);
// Dim an array of bytes big enough to hold the file's contents.
Byte []bytes = new Byte[fs.Length];
bool bSuccess = false;
// Your unmanaged pointer.
IntPtr pUnmanagedBytes = new IntPtr(0);
int nLength;
nLength = Convert.ToInt32(fs.Length);
// Read the contents of the file into the array.
bytes = br.ReadBytes( nLength );
// Allocate some unmanaged memory for those bytes.
pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
// Copy the managed byte array into the unmanaged array.
Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
// Send the unmanaged bytes to the printer.
bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
// Free the unmanaged memory that you allocated earlier.
Marshal.FreeCoTaskMem(pUnmanagedBytes);
return bSuccess;
}
public static bool SendStringToPrinter( string szPrinterName, string szString )
{
IntPtr pBytes;
Int32 dwCount;
// How many characters are in the string?
// Fix from Nicholas Piasecki:
// dwCount = szString.Length;
dwCount = (szString.Length + 1) * Marshal.SystemMaxDBCSCharSize;
// Assume that the printer is expecting ANSI text, and then convert
// the string to ANSI text.
pBytes = Marshal.StringToCoTaskMemAnsi(szString);
// Send the converted ANSI string to the printer.
SendBytesToPrinter(szPrinterName, pBytes, dwCount);
Marshal.FreeCoTaskMem(pBytes);
return true;
}
}
Fran_gg7, I had the same issue recently. Firstly, turn on the persistence of documents on the printer. This will allow you to see if the printer successfully received the print request.
You will see items in the printer queue and they will remain there.
In my scenario the print request was correctly being sent to the printer, however I was testing it on a laser printer that ultimately was unable to interpret the raw string data I was passing to it.
I tested the same output on a label printer that could understand the ZPL (zebra programming language) I was passing it and boom it worked fine.
Have a look at this for a detailed explanation
Hope this helps.
In cases where you are using the MSDN example from here https://support.microsoft.com/en-us/kb/322091#top but are trying to use an array of bytes instead of a string or file... This may help
public static void SendBytesToLocalPrinter(byte[] data, string printerName)
{
var size = Marshal.SizeOf(data[0]) * data.Length;
var pBytes = Marshal.AllocHGlobal(size);
try
{
SendBytesToPrinter(printerName, pBytes, size);
}
finally
{
Marshal.FreeCoTaskMem(pBytes);
}
}
This does not change with the byte array encoding. This is useful if you are trying to send some utf8 encoded byte sequences with some binary (ie. image) data mixed in as was the case for our team.
If printing plain text to Dot Matrix using "RawPrinterHelper" Method, it would only work properly for me when I manually added a printer, selected Generic / Text Only, and selected the USB001 port that was assigned to my USB connected printer (okidata in my test). Then RawPrinterHelper.SendStringToPrinter would behave very much like an 'lpd to lpt1:'
Had exactly the same issue with my ZEBRA ZD420 printer.
Sending ZPL string to printer only the data light flashing shortly without printing.
I changed only
Marshal.StringToCoTaskMemAnsi(szString);
to
Marshal.StringToCoTaskMemUTF8(szString);
and it works !

CKR_BUFFER_TOO_SMALL = 0x00000150

I want to PInvoke C_Encrypt() "pkcs#11" from a .dll :
[DllImport("cryptoki.dll", SetLastError = true)]
private static extern UInt32 C_Encrypt(CK_SESSION_HANDLE hSession,IntPtr pData,CK_ULONG ulDataLen,out IntPtr pEncryptedData,out CK_ULONG pulEncryptedData);
/*
.... Main
in which I initialize the encryption parametrs with C_EncyptInit
*/
CK_BYTE[] text = new CK_BYTE[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09 };
System.UInt32 t, tt = (System.UInt32)text.Length;
IntPtr pdata = Marshal.AllocHGlobal(text.Length);
Marshal.Copy(text, 0, pdata, text.Length);
IntPtr chif = IntPtr.Zero;
tt = (System.UInt32)Marshal.SizeOf(pdata);
rv = C_Encrypt(h, pdata, tt, out chif, out t);
help please
There's a variety of different problems here.
Your P/Invoke signature is wrong. The final two parameters are not out parameters. The C_Encrypt function will write the encrypted data to those parameters, but you need to allocate and pass them yourself.
You need to allocate data for chif, and then pass the size that you allocated for chif as the final param t. This is the root cause of the error that you're seeing.
Nit: Your variable names are confusing, and you seem to have mixed up tt and t somewhere, since you assign to tt twice.
I resolved the problem By my self:
[DllImport("D:/Program Files/Eracom/ProtectToolkit C SDK/bin/sw/cryptoki.dll", SetLastError = true)]
private static extern UInt32 C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE[] pData, CK_ULONG ulDataLen, CK_BYTE[] pEncryptedData,ref CK_ULONG pulEncryptedData);
enjoy

PInvoke and EntryPointNotFoundException

I can't understand what is wrong with a pinvoke below which results into an EntryPointNotFoundException:
A function in C with a structure declaration:
extern "C"__declspec (dllimport) __stdcall
LONG NET_DVR_Login_V30 (char *sDVRIP, WORD wDVRPort, char *sUserName,
char *sPassword, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo);
typedef struct
{
BYTE sSerialNumber[48];
BYTE byAlarmInPortNum;
BYTE byAlarmOutPortNum;
BYTE byDiskNum;
BYTE byDVRType;
BYTE byChanNum;
BYTE byStartChan;
BYTE byAudioChanNum;
BYTE byIPChanNum;
BYTE byZeroChanNum;
BYTE byMainProto;
BYTE bySubProto;
BYTE bySupport;
BYTE byRes1[20];
}NET_DVR_DEVICEINFO_V30, *LPNET_DVR_DEVICEINFO_V30;
The import in C#, the structure declaration and the pinvoke:
[DllImport("SDK.dll", SetLastError = true,
CallingConvention = CallingConvention.StdCall)]
public extern static int NET_DVR_Login_V30(
[MarshalAs(UnmanagedType.LPStr)] string sDVRIP,
ushort wDVRPort,
[MarshalAs(UnmanagedType.LPStr)] string sUserName,
[MarshalAs(UnmanagedType.LPStr)] string sPassword,
ref NET_DVR_DEVICEINFO_V30 lpDeviceInfo);
[StructLayout(LayoutKind.Sequential,
CharSet = CharSet.Ansi)]
public struct NET_DVR_DEVICEINFO_V30
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 48)]
public string sSerialNumber;
public byte byAlarmOutPortNum;
public byte byDiskNum;
public byte byDVRType;
public byte byChanNum;
public byte byStartChan;
public byte byAudioChanNum;
public byte byIPChanNum;
public byte byZeroChanNum;
public byte byMainProto;
public byte bySubProto;
public byte bySupport;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string byRes1;
}
NET_DVR_DEVICEINFO_V30 deviceInfo = new NET_DVR_DEVICEINFO_V30();
int result = Functions.NET_DVR_Login_V30(ip, port, user,
password, ref deviceInfo);
I inspected the function name via dumpbin and it is not mangled. So I wonder why an EntryPointNotFoundException occurs, if anything were wrong with the parameters for example, a PInvokeStackImbalance error would occur, let's say.
Any ideas what could be wrong with this pinvoke?
There is a tool called Dependency Walker (depends.exe) that will help debug this issue by displaying the import/export table of your SDK.DLL - I'd take a look at that. One other thing that might (this seems suspect to me) be happening is, that since you're using char*, .NET is adding an "A" on the end of your function name. That could be balderdash though.
Clearly there is a name mismatch. You therefore need to make sure that both sides of the interface use the same name:
When exporting the function from the DLL as stdcall it will be decorated. You can avoid this decoration by using a .def file.
When importing using P/Invoke you need to suppress the addition of a W or A suffix. Do so by setting the ExactSpelling field of the DllImportAttribute to true.

Categories