EDIT: I think I have an idea of a possible solution for the actual searching of values. By making sure the user input ends in 0 the issue should be resolved. This would involve subtracting the last digit from the uint (which I do not know how to get, unless I go the convert to string, trim end back to uint method which is ugly but I guess it could work) and then subtracting it. If anyone has any tips on how to do this please help me out!
I've been working on a program to search memory on the Xbox 360 for specific values, if you are familiar, it is similar to "Cheat Engine". I've gotten the basics down, but I just ran into an issue. My method to search memory is dependent on starting your search at an address that will line up with your value. If that doesn't make sense to you here is the code:
private void searchInt32(int Value, uint Address, uint BytesToSearch)
{
for (uint i = 0; i <= BytesToSearch; i+=4)
{
int recoveredMem = XboxSupport.littleEndtoInt(XboxSupport.GetMem(Address + i, 4), 0);
//Recover Memory (As Bytes) and convert to integer from address (incremented based on for loop)
if (recoveredMem == Value) //Check if recovered mem = search value
{
writeToFile(Address + i, Convert.ToString(Value)); //If recovered mem = search value, write to a text file
}
siStatus.Caption = String.Format("Searching Bytes {0} out of {1}...", i, BytesToSearch); //Update status caption
}
}
As you can see, the code is kept to a minimum and it's also about as fast as possible when it comes to recovering memory from a console. But, if the 4 bytes it recovers don't line up with the value, it will never return what you want. That's obviously a serious issue because the user won't know where their value is or what address to start at to return the correct value. I then attempted to use the following code to fix the issue:
private void searchUInt32(uint Value, uint Address, uint BytesToSearch)
{
siStatus.Caption = String.Format("Recovering Memory...");
byte[] data = XboxSupport.GetMem(Address, BytesToSearch); //Dump Console Memory
FileStream output = new FileStream("SearchData.dat", FileMode.Create);
BinaryWriter writer = new BinaryWriter(output);
writer.Write(data); //Write dump to file
writer.Close();
output = new FileStream("SearchData.dat", FileMode.Open);
BinaryReader reader = new BinaryReader(output); //Open dumped file
for (uint i = 0; i *4 < reader.BaseStream.Length; i++)
{
byte[] bytes = reader.ReadBytes(4); //Read the 4 bytes
Array.Reverse(bytes);
uint currentValue = BitConverter.ToUInt32(bytes, 0); //Convert to UInt
if(currentValue == Value) //Compare
writeToFile(Address + i * 4, Convert.ToString(Value));
siStatus.Caption = String.Format("Searching Bytes {0} out of {1}...", i * 4, BytesToSearch);
}
reader.Close();
File.Delete("SearchData.dat");
}
There is a lot more code, but essentially it does the same thing, just using a file. My original goal was to have users be able to input their own memory blocks to be searched, but right now it seems that just won't work. I do not really want to have the program search all of the memory because that might end up being a slow process (depending on the size of the process being dumped) and often times the values being looked for can be narrowed down to areas of writeable code, removing junk addresses from the executable portion of the process. I am just looking to see if anyone has any suggestions, I was thinking I could possibly get the entry address from the process (I have a function for it) and using a little math correct user input addresses to work properly but I wasn't entirely sure how to do it. If anyone has any suggestions or solutions I'd appreciate any help I can get. If any of my post needs to be clarified/cleaned up please let me know, I'll be glad to do anything that might help me to an answer.
Thanks!
Edit: Temporary (hopefully) Solution:
When I load addresses into the tool they are loaded as strings from a text file, then a conversion to uint is attempted. I solved the not even issue using the following code:
sA[0] = sA[0].Remove(sA[0].Length - 1) + "0"; //Remove last character and replace w/ 0
//Add 16 to the search length
Instead of dumping memory to disk and reading every iteration, scan the target process' memory in chunks, and then marshal the data to leverage the efficiency of pointer arithmetic.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace MemoryScan {
internal class Program {
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [Out] byte[] lpBuffer, int dwSize, out int lpNumberOfBytesRead);
private static unsafe void Main(string[] args) {
Process process = Process.GetProcessesByName("notepad")[0]; //example target process
int search = 100; //search value
int segment = 0x10000; //avoid the large object heap (> 84k)
int range = 0x7FFFFFFF - segment; ; //32-bit example
int bytesRead;
List<int> addresses = new List<int>();
DateTime start = DateTime.Now;
for (int i = 0; i < range; i += segment) {
byte[] buffer = new byte[segment];
if (!ReadProcessMemory(process.Handle, new IntPtr(i), buffer, segment, out bytesRead)) {
continue;
}
IntPtr data = Marshal.AllocHGlobal(bytesRead);
Marshal.Copy(buffer, 0, data, bytesRead);
for (int j = 0; j < bytesRead; j++) {
int current = *(int*)(data + j);
if (current == search) {
addresses.Add(i + j);
}
}
Marshal.FreeHGlobal(data);
}
Console.WriteLine("Duration: {0} seconds", (DateTime.Now - start).TotalSeconds);
Console.WriteLine("Found: {0}", addresses.Count);
Console.ReadLine();
}
}
}
Test Results
Duration: 1.142 seconds
Found: 3204
Create a generic class to make type marshaling easier, like so:
public static class MarshalHelper
{
public unsafe static T Read<T>(IntPtr address)
{
object value;
switch (Type.GetTypeCode(typeof(T)))
{
case TypeCode.Int16:
value = *(short*)address;
break;
case TypeCode.Int32:
value = *(int*)address;
break;
case TypeCode.Int64:
value = *(long*)address;
break;
default:
throw new ArgumentOutOfRangeException();
}
return (T)value;
}
}
Related
I need to check in realtime if a specific process try to read a wav of flac file.
I hare created a routine with 2 parameters: the process name, and the file that try to open:
public static bool Scan(string ProcessName,string TextToFind)
{
// getting minimum & maximum address
SYSTEM_INFO sys_info = new SYSTEM_INFO();
GetSystemInfo(out sys_info);
int MatchCount=0;
IntPtr proc_min_address = sys_info.minimumApplicationAddress;
IntPtr proc_max_address = sys_info.maximumApplicationAddress;
// saving the values as long ints so I won't have to do a lot of casts later
long proc_min_address_l = (long)proc_min_address;
long proc_max_address_l = (long)proc_max_address;
Process[] Arrprocess = Process.GetProcessesByName(ProcessName);
if (Arrprocess.Length == 0) return false;
// notepad better be runnin'
Process process = Arrprocess[0];
// opening the process with desired access level
IntPtr processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_WM_READ, false, process.Id);
// this will store any information we get from VirtualQueryEx()
MEMORY_BASIC_INFORMATION mem_basic_info = new MEMORY_BASIC_INFORMATION();
int bytesRead = 0; // number of bytes read with ReadProcessMemory
// long milliseconds_start = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
while (proc_min_address_l < proc_max_address_l)
{
// 28 = sizeof(MEMORY_BASIC_INFORMATION)
VirtualQueryEx(processHandle, proc_min_address, out mem_basic_info, 28);
// if this memory chunk is accessible
if (mem_basic_info.Protect == PAGE_READWRITE && mem_basic_info.State == MEM_COMMIT && (mem_basic_info.lType == MEM_MAPPED || mem_basic_info.lType == MEM_PRIVATE))
{
byte[] buffer = new byte[mem_basic_info.RegionSize];
// read everything in the buffer above
ReadProcessMemory((int)processHandle, mem_basic_info.BaseAddress, buffer, mem_basic_info.RegionSize, ref bytesRead);
string result = System.Text.Encoding.ASCII.GetString(buffer);
if (result.Contains(TextToFind))
return true;
}
// move to the next memory chunk
proc_min_address_l += mem_basic_info.RegionSize;
proc_min_address = new IntPtr(proc_min_address_l);
}
return false;
}
this code work only the first time, because when the process close the flac file, the string keep in memory until the process will close.
I need to check every time (with precision of milliseconds) the process try to load the file that I pass as parameter.
I don't known if i'am in the right way ...
Can someone suggest me a code (in c# or c++) that detect in realtime if a process x try to read a file name y ?
Thank you !
Windows provides methods to let you know when files are opened/edited/renamed/etc.
https://learn.microsoft.com/en-us/windows/win32/projfs/file-system-operation-notifications
I am currently trying to read from a memory address, then open its contents in a web browser (its contents is always a url.)
I am currently attempting to do it like this:
public static void Main(string[] args)
{
Process[] pname = Process.GetProcessesByName("t6mp");
if (pname.Length == 0)
{
Console.WriteLine("Game not found. Please run your game then restart this program.");
Console.ReadLine();
}
else
{
void ReadProcessMemory(object t6mp, int v1, byte[] url, int v2, ref int read)
{
}
Console.WriteLine("Game found. Please go to the page where you can start a demo, then press enter to continue.");
Console.ReadLine();
Console.WriteLine("Please press enter to export");
Console.ReadLine();
var buffer = new byte[1];
var sb = new StringBuilder();
var handle = Process.GetProcessesByName("t6mp")[0];
int _bytesused = 200;
for (var i = 0; i < _bytesused; i++)
{
ReadProcessMemory(handle, 0x2BDA932 + i, buffer, buffer.Length, ref _bytesused);
if (buffer[0] != 0)
{
sb.Append(Encoding.ASCII.GetString(buffer));
Process.Start(sb.ToString());
}
else
{
Console.WriteLine("Error has occured, please try again. Press enter to close program");
Console.ReadLine();
break;
}
}
}
}
It is correctly recognizing when the process is open, and I am sure that the address exists (I have tried both 0x2BDA932 and 0x02BDA932) However, It always displays the error message, for some reason if (buffer[0] != 0) is always false. When I remove the if / else and just have it go straight to sb.Append(Encoding.ASCII.GetString(buffer));
Process.Start(sb.ToString());
It just crashes. Ideally, it would open the contents of the address in my browser, as it is a url. Any ideas?
var buffer = new byte[1];
Your buffer is only 1 byte in length, your while loop is overflowing your buffer potentially leading to undefined behavior.
buffer.Length in your call to ReadProcessMemory
Length is 1, you're only reading 1 byte, this is why it's never 0.
You should define the array length using a fixed size like 2000 which should cover all possible scenarios, concerning URLS.
Here is my function for reading null terminated strings:
public static string ReadNullTerminatedString(IntPtr handle, IntPtr addr, int maxlength)
{
var bytearray = new byte[maxlength];
IntPtr bytesread = IntPtr.Zero;
ReadProcessMemory(handle, addr, bytearray, maxlength, out bytesread);
int nullterm = 0;
while (nullterm < bytesread.ToInt64() && bytearray[nullterm] != 0)
{
nullterm++;
}
string s = Encoding.ASCII.GetString(bytearray, 0, nullterm);
return s;
}
I'm trying to detect when a card has been inserted into a reader.
If I do a nasty polling loop like this:
public struct SCARD_READERSTATE
{
[MarshalAs(UnmanagedType.LPWStr)]
public string szReader;
public byte[] pvUserData;
public byte[] rgbAtr;
public uint dwCurrentState;
public uint dwEventState;
public uint cbAtr;
}
byte[] atr = null;
SCARD_READERSTATE[] rs = new SCARD_READERSTATE[1];
rs[0].szReader = readersList[0];
rs[0].dwCurrentState = SCARD_STATE_UNAWARE;
rs[0].dwEventState = SCARD_STATE_PRESENT;
int hctx = hContext.ToInt32();
var cardResult = SCardGetStatusChange(hctx, 100, rs, 1);
if (cardResult == 0 && rs[0].cbAtr > 0 && rs[0].rgbAtr != null)
{
atr = new byte[rs[0].cbAtr];
Array.Copy(rs[0].rgbAtr, atr, rs[0].cbAtr);
}
while ( (rs[0].dwCurrentState & SCARD_STATE_PRESENT) == 0)
{
rs = new SCARD_READERSTATE[1];
rs[0].szReader = readersList[0];
//rs[0].dwCurrentState = SCARD_STATE_PRESENT;
//rs[0].dwEventState = SCARD_STATE_PRESENT;
SCardGetStatusChange(hctx, 100000000, rs, 1);
System.Threading.Thread.Sleep(1000);
}
it works, but it has a nasty thread sleep in it. Ideally I'd like to make a blocking call to SCardGetStatusChange on a background thread and then surface up the events.
Apparently by setting the szReader to the value "\\?PnP?\Notification" it should block, as long as everything else in the struct is 0.
I've changed the code to
rs[0].szReader = "\\\\?PnP?\\Notification";
rs[0].cbAtr = 0;
rs[0].dwCurrentState = 0;
rs[0].dwEventState = 0;
rs[0].pvUserData = new byte[0];
rs[0].rgbAtr = new byte0];
SCardGetStatusChange(hctx, 100000000, rs, 1);
but it just returns a success result immediately. Can any pInvoke masters out there see what's wrong?
In your sample the second call to SCardGetStatusChange should block if you copy dwEventState into dwCurrentState and then reset dwEventState, so there's no need for the sleep.
The "\\?PnP?\Notification" struct is to tell you when a new smart card reader has been attached, not when a card has been inserted. From the MSDN page on SCardGetStatusChange:
To be notified of the arrival of a new smart card reader, set the szReader member of a SCARD_READERSTATE structure to "\\?PnP?\Notification", and set all of the other members of that structure to zero.
When using the "\\?PnP?\Notification" struct:
the pvUserData and rgbAttr fields should be set to null
a new byte[0] is a valid pointer to a zero length array, but what the API needs here is null pointers or zero values)
the high 16 bits of dwCurrentState should contain the current reader count
i.e. rs[0].dwCurrentState = (readerCount << 16);
the MSDN page is currently inaccurate on this point.
Is there a method (in c#/.net) that would left-shift (bitwise) each short in a short[] that would be faster then doing it in a loop?
I am talking about data coming from a digital camera (16bit gray), the camera only uses the lower 12 bits. So to see something when rendering the data it needs to be shifted left by 4.
This is what I am doing so far:
byte[] RawData; // from camera along with the other info
if (pf == PixelFormats.Gray16)
{
fixed (byte* ptr = RawData)
{
short* wptr = (short*)ptr;
short temp;
for (int line = 0; line < ImageHeight; line++)
{
for (int pix = 0; pix < ImageWidth; pix++)
{
temp = *(wptr + (pix + line * ImageWidth));
*(wptr + (pix + line * ImageWidth)) = (short)(temp << 4);
}
}
}
}
Any ideas?
I don't know of a library method that will do it, but I have some suggestions that might help. This will only work if you know that the upper four bits of the pixel are definitely zero (rather than garbage). (If they are garbage, you'd have to add bitmasks to the below). Basically I would propose:
Using a shift operator on a larger data type (int or long) so that you are shifting more data at once
Getting rid of the multiply operations inside your loop
Doing a little loop unrolling
Here is my code:
using System.Diagnostics;
namespace ConsoleApplication9 {
class Program {
public static void Main() {
Crazy();
}
private static unsafe void Crazy() {
short[] RawData={
0x000, 0x111, 0x222, 0x333, 0x444, 0x555, 0x666, 0x777, 0x888,
0x999, 0xaaa, 0xbbb, 0xccc, 0xddd, 0xeee, 0xfff, 0x123, 0x456,
//extra sentinel value which is just here to demonstrate that the algorithm
//doesn't go too far
0xbad
};
const int ImageHeight=2;
const int ImageWidth=9;
var numShorts=ImageHeight*ImageWidth;
fixed(short* rawDataAsShortPtr=RawData) {
var nextLong=(long*)rawDataAsShortPtr;
//1 chunk of 4 longs
// ==8 ints
// ==16 shorts
while(numShorts>=16) {
*nextLong=*nextLong<<4;
nextLong++;
*nextLong=*nextLong<<4;
nextLong++;
*nextLong=*nextLong<<4;
nextLong++;
*nextLong=*nextLong<<4;
nextLong++;
numShorts-=16;
}
var nextShort=(short*)nextLong;
while(numShorts>0) {
*nextShort=(short)(*nextShort<<4);
nextShort++;
numShorts--;
}
}
foreach(var item in RawData) {
Debug.Print("{0:X4}", item);
}
}
}
}
I have this method that I need to call and use in my application, but I don't know really know how to do it exactly.
This is the function that I need to call.
[DllImport(dll_Path)]
public static extern int DTS_GetDataToBuffer(int Position, int Length, char* Buffer, int* DataRead);
In my code, I have this function and I'm missing its implementation.
internal static void GetDataToBuffer(int position, int length, out byte[] data, out int dataRead)
{
unsafe
{
// the code I need
}
}
I think most of this is very selfexplanatory. I need to implement the latter function so I can be able to read the data into the buffer and the amount of data read (which should actually be the same as data.Length, but the manufacturer has this as separate option, so I need it).
Can anyone help? Is this clear enough?
Thank you
Edit: Here is the unmanaged declaration from the .h file. Hope it helps.
extern NAG_DLL_EXPIMP int DTS_GetDataToBuffer(int Position,
int Length,
unsigned char *Buffer,
int *DataRead );
Edit #2:
Positon - the position from which to star reading the data.
Length - The amount of data to read (this would be the buffer size).
DataRead - the actual data size that was read.
I don't think you really need to use unsafe pointers here.
Declare function as
[DllImport(dll_Path)]
public static extern int DTS_GetDataToBuffer(
int position,
int length,
byte[] buffer,
ref int dataRead);
Reasonable C# wrapper for this function:
internal static byte[] GetDataToBuffer()
{
// set BufferSize to your most common data length
const int BufferSize = 1024 * 8;
// list of data blocks
var chunks = new List<byte[]>();
int dataRead = 1;
int position = 0;
int totalBytes = 0;
while(true)
{
var chunk = new byte[BufferSize];
// get new block of data
DTS_GetDataToBuffer(position, BufferSize, chunk, ref dataRead);
position += BufferSize;
if(dataRead != 0)
{
totalBytes += dataRead;
// append data block
chunks.Add(chunk);
if(dataRead < BufferSize)
{
break;
}
}
else
{
break;
}
}
switch(chunks.Count)
{
case 0: // no data blocks read - return empty array
return new byte[0];
case 1: // single data block
if(totalBytes < BufferSize)
{
// truncate data block to actual data size
var data = new byte[totalBytes];
Array.Copy(chunks[0], data, totalBytes);
return data;
}
else // single data block with size of Exactly BufferSize
{
return chunks[0];
}
default: // multiple data blocks
{
// construct new array and copy all data blocks to it
var data = new byte[totalBytes];
position = 0;
for(int i = 0; i < chunks.Count; ++i)
{
// copy data block
Array.Copy(chunks[i], 0, data, position, Math.Min(totalBytes, BufferSize));
position += BufferSize;
// we need to handle last data block correctly,
// it might be shorted than BufferSize
totalBytes -= BufferSize;
}
return data;
}
}
}
I can't test this but I think you should let the Marshaler do you conversion(s):
[DllImport(dll_Path)]
public static extern int DTS_GetDataToBuffer(out byte[] data, out int dataRead);
i agree you don't need to use unsafe block. you are using pinvoke, i hope below links might be useful :
http://msdn.microsoft.com/en-us/magazine/cc164123.aspx
http://www.pinvoke.net/
and there are post on stackoverflow too