c++ vs c# do zabawy pamiecia

4

Witam serdecznie ;)

Jako mlody pythonowiec i automatyk chce isc o krok dalej i zaczac wyciagac dane / manipulowac pamiecia niskopoziomowo w apkach .exe (trainery do gier i inne bajery 4fun). Python niestety na tym polu to juz troche za malo i najlepsze bedzie cos z rodziny C. Mam maly dylemat miedzy c++ a c#. Ten drugi jest na pewno nowszy i zdrowy rozsadek podpowiada ze to wlasnie to bedzie lepszym wyborem. Tak czy owak, nie zajmie mi to dlugo zeby ogarnac ktorys z tych jezykow. Temacik luzny, moze ktos poda argumenty stojaca za kazdym z nich ;) Pozdro and stay strong !

1

Jeśli Python się nie nada, to C# też.

4
ledi12 napisał(a):

Mam maly dylemat miedzy c++ a c#. Ten drugi jest na pewno nowszy i zdrowy rozsadek podpowiada ze to wlasnie to bedzie lepszym wyborem

Nie do końca rozumiem co chcesz zrobić, ale twój zdrowy rozsądek leży i kwiczy. C# nie jest nowszą wersją C++. C# jest tak samo daleko od rzeczy niskopoziomowych jak Java
Może opisz lepiej co chcesz robić z tą pamięcią to łatwiej będzie coś doradzić

BTW jak szukasz nowoczesnego, niskopoziomowego języka programowania to polecam Rust

1

Jak niskopoziomowo to assembler :P jak troszeczkę wyżej to C.

4
KamilAdam napisał(a):

Nie do końca rozumiem co chcesz zrobić, ale twój zdrowy rozsądek leży i kwiczy. C# nie jest nowszą wersją C++. C# jest tak samo daleko od rzeczy niskopoziomowych jak Java

Są w Javie pointery? Nie ma.
Są w C# pointery? Są.
Czyli nie tak samo :)

A tak serio, to w C# da się robić niskopoziomowe grzebanie w pamięci. Ale... nie bardzo jest po co. Nie do tego ten język został stworzony.

1
Azarien napisał(a):

Są w Javie pointery? Nie ma.
Są w C# pointery? Są.
Czyli nie tak samo :)

Są w Javie pointery tylko totalnie nieotypowane: https://www.baeldung.com/java-unsafe#off-heap-memory
Zwykły long jest wskaźnikiem i można go zdobyć metodą np Unsafe.allocateMemory i użyć w metodach Unsafe.putByte, Unsafe.getByte, Unsafe.freeMemory, itd
Z drugiej strony sun.misc.Unsafe jest czymś nieoficjalnym i nie jest dostępne we wszystkich implementacjach Javy. Na dodatek w planach jest usunięcie tego całkowie (a może już tego nie ma?).

1
Wibowit napisał(a):

Z drugiej strony sun.misc.Unsafe jest czymś nieoficjalnym i nie jest dostępne we wszystkich implementacjach Javy. Na dodatek w planach jest usunięcie tego całkowie (a może już tego nie ma?).

Ale w zamian ma być dostarczone oficjalne api do jeżdżenia po pamięci. Bez sun.misc.Unsafe lub api zastępczego projekty Cassandra i Kafka już mogą się zwijać

1

@KamilAdam: i nie tylko Kafke. Generalnie pierdyliard bibliotek Javovych ma Unsafe, nie wiem jak cache offheap ;]

1

Jeżeli chcesz wyciągać jakieś dane z klienta gry za pomocą C# to da się to zrobić bo się tym bawiłem, ale problem raczej nie jest na poziomie jakiego języka użyć, a jak wyciągać te adresy/dane.

Kod którego używałem do pewnej gierki do wyciągania z niej danych przy wywołaniu RefreshData() na Windowsie:

Na Lunixa nie znalazłem jak to zrobić

public class MemoryContext
{
	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, int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);

	private int xor;

	private int baseAddress;
	private int AddrXOR = 0x511458;
	private int AddrLevel = 0x545470;


	private Process process;
	private IntPtr handle;

	public MemoryContext(string processName)
	{
		process = Process.GetProcessesByName(processName).FirstOrDefault();

		if (process == null)
		{
			throw new Exception($"Process with name: '{processName}' is not running");
		}

		baseAddress = process.MainModule.BaseAddress.ToInt32();
		handle = OpenProcess(PROCESS_WM_READ, false, process.Id);

		int bytesRead = 0;
		byte[] buffer = new byte[4];

		ReadProcessMemory((int)handle, AddrXOR + baseAddress, buffer, buffer.Length, ref bytesRead);
		xor = BitConverter.ToInt32(buffer, 0);
	}

	public GameInfo RefreshData()
	{
		var gameInfo = new GameInfo();

		int bytesRead = 0;
		byte[] buffer = new byte[4];

		ReadProcessMemory((int)handle, AddrLevel + baseAddress, buffer, buffer.Length, ref bytesRead);
		gameInfo.Level = BitConverter.ToInt32(buffer, 0);

		return gameInfo;
	}
}
3
WeiXiao napisał(a):

Kod którego używałem do pewnej gierki do wyciągania z niej danych przy wywołaniu RefreshData() na Windowsie:

	[DllImport("kernel32.dll")]
	public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);

Tu jest źle. hProcess jest w C typu HANDLE, które jest zdefiniowane jako void*, nietypowany pointer. Rozmiar HANDLE jest zależny od platformy.
To samo się tyczy lpBaseAddress, które jest LPCVOID czyli "long pointer to constant void", czyli w praktyce const void*.

Powinno być IntPtr w obu przypadkach.

 	[DllImport("kernel32.dll")]
 	public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);

Wtedy nie trzeba tego rzutowania na int:

ReadProcessMemory((int)handle, AddrXOR + baseAddress, buffer, buffer.Length, ref bytesRead);

Poprawienie baseAddress pozostawiamy czytelnikowi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1