Non-local App Memory Manipulation
BlitzMax Forums/BlitzMax Programming/Non-local App Memory Manipulation
| ||
I've starting this topic earlier without any success and have decided to respawn it with a clearer question, better stated question. I hate to bug you guys, but there seems to have been many topics addressing this very questions without really any answers. It seem that there have been may people interested, especially me:), and it would be great to get it answered. My questions is, is there a way to point to variables outside of your blitzmax application. If so, how would you go about doing that? Let’s say you wrote a program that created a spot in memory to place an integer, let's say the integer’s value was 1521. You ran that program and from another application you wanted to change that integer to 1522, how would you do that. You would have to loop through your memory until you found the value of 1521, right. Then you would have to place 1522 in that memory location. How would this program work? Thanks for all this help, Hopefully somebody knows how to do this:) |
| ||
This is not possible. On windows is a memory address violation. |
| ||
It is possible to specify a 'global' memory space and have it read and written to from separate applications using a dll. |
| ||
If you want to communicate data between programs in memory, you can set up a pipe, although that's said to be tricky, and I don't know how. Anyone? |
| ||
Using pipes is the best choice, take a look to the standardout and standardin streaming, and the TProcess class. But keep in mind that using pipes will force a sort of 'syncronization' as the data read and write is performed on separate threads, but the 'shared' buffer is ussually 4 Kbytes long. Each instance of a running application has its own private memory area, and when an application uses an external DLL, this DLL uses the same private memory area. If there's any way to 'break' this, it will be considered by the OS a memory access violation. So, even if it is possible, I would not recomend it. Not to talk about all the possible threading problems on uncontrolled 'shared' data access... |
| ||
That's not totally true Ziggy. Regarding DLLs, this is only the standard behaviour, but not the only one possible. GW was totally right, you can write a DLL that contains a special *shared* part. Every program loading this DLL, when accessing to this specific memory section, will indeed access the same shared memory. http://support.microsoft.com/kb/100634 It is also possible to use file mappings to implement a shared block of memory (CreateFileMapping with hFile = INVALID_HANDLE_VALUE): http://msdn2.microsoft.com/EN-US/library/aa366537.aspx http://msdn2.microsoft.com/en-us/library/ms686958.aspx These two solutions are very common, but obviously they are windows specific. |
| ||
@Koriolis: I knew that but i don't think (I can be wrong) it is compatible with managed code. And I think that shared blocks of memory on filemapping can only be shared by the creator process and child processes. But I'm not sure. |
| ||
It is possible to specify a 'global' memory space and have it read and written to from separate applications using a dll. Or without a DLL -- there's some blitzMax code here to deal with shared memory, written by Budman: ' Simple program to demonstrate sharing memory between process ' compile as console program and run one or more times the first run sets the ' shared memory ' additonal runs read it SuperStrict Extern "Win32" Function CloseHandle:Int(Handle:Int) Function MapViewOfFile:Byte Ptr(hFileMappingObject: Int,dwDesiredAccess: Int, dwFileOffsetHigh:Int, dwFileOffsetLow:Int, dwNumberOfBytesToMap:Int) Function UnmapViewOfFile:Int(lpBaseAddress: Byte Ptr) Function CreateFileMappingA:Int(hFile: Int, lpFileMappingAttributes: Byte Ptr,flProtect:Int, dwMaximumSizeHigh:Int, dwMaximumSizeLow:Int, lpName$z) Function GetLastError:Int() End Extern Const PAGE_READWRITE : Int=4 Const FILE_MAP_WRITE : Int=2 Type TSharedMemory Field _Handle : Int Field _Name : String Field _Size : Int Field _Owner : Int Field _Data : Byte Ptr Method Delete() Close End Method Method Open:Int(Name: String, Size: Int) Close() _Name = Name _Size = Size ' CreateFileMapping, when called with $FFFFFFFF For the hanlde value, creates a region of shared memory } _Handle = CreateFileMappingA($FFFFFFFF, Null, PAGE_READWRITE, 0,_Size,_Name) If _Handle = 0 Then Return False _Owner = GetLastError() = 0 ' We still need To map a pointer To the handle of the shared memory region _Data= MapViewOfFile(_Handle, FILE_MAP_WRITE, 0, 0, _Size) If Not _Data Close Return False End If Return True End Method Method Close() If _Data UnmapViewOfFile(_Data); _Data=Null End If If _Handle CloseHandle(_Handle) _Handle=0 End If End Method End Type Print "Test Share Mem" Local mem:TSharedMemory = New TSharedMemory mem.Open("TESTMEM",30) If mem._Owner Print "Setting Title" MemClear mem._Data,30 Local title:String="Budman Rocks" Local pTitle:Byte Ptr=title.toCString() MemCopy mem._Data,pTitle,title.length+1 MemFree pTitle Else Print "Getting Title" Local title : String = string.FromCString(mem._Data) Print "The Title is "+title End If Input mem.Close (See this thread for the full story: http://www.blitzbasic.com/Community/posts.php?topic=65705 ) |
| ||
An alternative is SKN[3]AC's code using OpenProcessMemory() <Windows only> that's in the code archives. It should be quite easy to write a simple game trainer with this (if that's what you are trying to do). Generally you search for a memory location by matching the value as you say, but you may well get more than one 'hit' so you modify the value in the target program (eg by losing a life) and seeing which of the original hits contains the new value. I'm starting to sound like a parrot now.. this question has come up a bunch of times... but he used the code to make a mod for Pro Evolution Soccer IV to allow people to play over the internet. |
| ||
You guys are excellent, thanks! |
| ||
Thanks for the code samples :D |