Pointer in Basic - Kernelpanic - 07-16-2023
Has anyone ever dealt with pointers in Basic?
Actually there are no pointers in Basic like in C, but maybe they can be imitated. I've tried this now with VarPtr, Peek and Poke, and I didn't find any error in my exercise to achieve this. I don't see any at the moment either. Access to the memory address is basically like in C, and I can also change the content.
Pointers are a powerful, but also dangerous, tool in C! One could definitely good use them in Basic too. I think so.
I would be grateful to anyone who is interested and takes a look at the program if they could point out whether and if so, where I made a mistake in my thinking.
The explanations/comments are of course in German, so I can understand what's going on.
Code: (Select All) 'Zeigerbeispiel in Basic - 16. Juli 2023
'Mit VarPtr und Peek und Poke ist es moeglich Zeiger in
'Basic nachzuahmen.
$Console:Only
Option _Explicit
Dim As Long zahl1, zahl2, wert, wert2
Dim As Long speicherAdresse, speicherAdresse2
Locate 2, 3
Input "Zahl 1: ", zahl1
Locate 3, 3
Input "Zahl 2: ", zahl2
Locate 5, 3
Print Using "Zeige Zahl 1: ### -- Zahl 2: ### "; zahl1, zahl2
'Adresse der Zahl im Speicher ermitteln
speicherAdresse = VarPtr(zahl1)
'Speicheradresse anzeigen
Locate 6, 3
Print "Speicheradress Zahl 1: ", speicherAdresse
'wert wird der Inhalt der Speicheradresse zugewiesen
wert = Peek(speicherAdresse)
Locate 8, 3
Print "Inhalt der Speicheradresse: ", wert
'wert erhoehen
wert = wert * 2
'Neuen Wert in die Speicheradresse einfuegen
Poke (speicherAdresse), wert
'Neuen Inhalt anzeigen
Locate 9, 3
Print "Neuer Inhalt in der Speicheradresse (Inhalt * 2): ", wert
'Speicheradresse der 2ten Variablen ermitteln
speicherAdresse2 = VarPtr(zahl2)
wert2 = Peek(speicherAdresse2)
'Inhalt der Speicheradresse
Locate 11, 3
Print "Inhalt der 2ten Speicheradresse: ", wert2
Locate 12, 3
Print "Jetzt auf die Adresse von Zahl 2 zugreifen, um den Inhalt zu aendern."
'Der 2ten Variablen den Wert von wert2 von der
'ersten Speicheradresse zuweisen
Locate 14, 3
wert2 = Peek(speicherAdresse)
Print "2te Variable hat jetzt den selben Wert wie Zahl 1: ", wert2
End
RE: Pointer in Basic - bplus - 07-16-2023
Check out the memory stuff, maybe start with Type.
https://qb64phoenix.com/qb64wiki/index.php/MEM
RE: Pointer in Basic - mnrvovrfc - 07-17-2023
As bplus already elucidated, what I call the _MEM gang. But it's somewhat clunky to some people used to how code looks in C. They prefer Freebasic because those developers desired as close association to C/C++ as possible. It explains the "ZString" type and the folly with using fixed-length strings in UDT's and working with files.
QB64 allows the programmer to do pointer-heavy stuff in C if he/she wanted to. Just include stuff in "dot-H" files and have a matching "DECLARE LIBRARY... END DECLARE" to have subprogram and function prototypes. This is actually done extensively in QB64 itself to expand the language.
Show Content
SpoilerDo not look at a lot of Purebasic code, especially that targeted for Win32 API because it's confusing. They talk sometimes about using an integer type (declared as "something.i") to sometimes substitute for pointer. This was because the language used to be not sophisticated enough to handle pointer variables per se and there needed to be a way to give an address to point to a variable or function or something. The thing wrong with that is that most "pointers" in Win32 API were 32-bit for a 32-bit operating system, and therefore it was easy to assume the "dot-i" which is for 32-bit integer. Pointers should never have types in any language, it depends always on the CPU architecture.
Another thing to get confused about is the _OFFSET type in QB64. But that is actually a go-between so the programmer could call stuff from Win API and other places. _OFFSET is actually the "void" pointer type in C.
https://qb64phoenix.com/qb64wiki/index.php/PEEK_and_POKE_Library
Here is very close to what is called "PEEK" and "POKE" in Purebasic: just simple memory buffers to store stuff into. But this could be done about as easily with the _MEM statements.
RE: Pointer in Basic - SagaraS - 07-17-2023
New Method
Code: (Select All)
' 32Bit / 64Bit Speicher (Der von Windows)
' Reine 32/64 Bit Adressierung
' 32/64 Bit Pointer
' Funktioniert fuer Werte mit bis zu 64Bit (Integer64)
DIM SEGBlock AS _MEM
DIM wert AS _UNSIGNED LONG
DIM wert2 AS _UNSIGNED LONG
wert = 4294967295
' Speicherblock der Variable ermitteln
SEGBlock = _MEM(wert)
' Aendern des Wertes im Speicher um -5
_MEMPUT SEGBlock, SEGBlock.OFFSET, _MEMGET(SEGBlock, SEGBlock.OFFSET, LONG) - 5 AS LONG
' Wert aus dem Speicher holen
wert2 = _MEMGET(SEGBlock, SEGBlock.OFFSET, LONG)
PRINT "Speicher Start Adresse :"; SEGBlock.OFFSET
PRINT "Groesse des Blocks :"; SEGBlock.SIZE
PRINT "Typ des Blocks :"; SEGBlock.TYPE
PRINT "Datentyp des Blocks :"; SEGBlock.ELEMENTSIZE
PRINT "Wert der Speicher Adresse:"; wert2
' Speicherblock freigeben
_MEMFREE SEGBlock
Old Method:
Code: (Select All)
' 16 Bit Speicher (Wird emuliert von QB64)
' Es handelt sich hierbei um DOS Adressierungen
' 16 Bit Pointer (Segment Adressierung im Speicher)
' Funktioniert nur fuer 1 Byte Werte 0 - 255
DIM SpeicherAdresse AS LONG
DIM wert AS LONG
wert = 65535
DEF SEG = VARSEG(SpeicherAdresse)
' Bei groesseren Variablen muss die Zahl zerlegt werden.
' Zerlegung der Variable in Bytes, die dann in den Speicher geschrieben werden
POKE SpeicherAdresse + 0, (wert AND &HFF00&) / &H100&
POKE SpeicherAdresse + 1, (wert AND &HFF&)
' Aendern des Wertes im Speicher um -5
POKE SpeicherAdresse + 1, PEEK(SpeicherAdresse + 1) - 5
' Zusammensetzung des Integer Wertes aus dem Speicher
wert2 = PEEK(SpeicherAdresse + 0) * &H100& + PEEK(SpeicherAdresse + 1)
PRINT "Verwendeter Segment Block: &H" + HEX$(VARSEG(SpeicherAdresse))
PRINT "Speicher Start Adresse : &H" + HEX$(VARPTR(SpeicherAdresse))
PRINT "Wert der SpeicherAdresse :"; wert2
RE: Pointer in Basic - OldMoses - 07-17-2023
I concur with what everyone else has stated here. Use the _MEM set of commands. They operate very similar to binary files and are a better protected (i.e. less dangerous) way of doing PEEKs & POKEs. There's essentially no chance of "going off the reservation". They can be a bit fussy to use, but worth the effort. Check out Steve's video tutorials on the subject, if you haven't already, that's where I learned them.
https://qb64phoenix.com/forum/showthread.php?tid=172
RE: Pointer in Basic - bplus - 07-17-2023
"As bplus already elucidated,"
OMG I am elucidating again!
Well I think SagaraS is germaining. ;-))
RE: Pointer in Basic - a740g - 07-17-2023
Spartan-style pointer-esque API for QB64 for those willing to step outside the safety of MEM.
https://github.com/a740g/Toolbox64/blob/main/PointerOps.bi
https://github.com/a740g/Toolbox64/blob/main/PointerOps.h
RE: Pointer in Basic - SpriggsySpriggs - 07-17-2023
That reminds me a lot of my PeepingTom code
Code: (Select All)
'Begin $INCLUDE
Type PROCESSENTRY32
As Long dwSize, cntUsage, th32ProcessID
$If 64BIT Then
As String * 4 padding
$End If
As _Unsigned _Offset th32DefaultHeapID
As Long th32ModuleID, cntThreads, th32ParentProcessID, pcPriClassBase, dwFlags
As String * 260 szExeFile
End Type
Const PROCESS_VM_READ = &H0010
Const PROCESS_QUERY_INFORMATION = &H0400
Const PROCESS_VM_WRITE = &H0020
Const PROCESS_VM_OPERATION = &H0008
Const TH32CS_SNAPPROCESS = &H00000002
Const TOM_FALSE = 0
Declare Dynamic Library "Kernel32"
Function CreateToolhelp32Snapshot%& (ByVal dwFlags As Long, Byval th32ProcessID As Long)
Function Process32First%% (ByVal hSnapshot As _Offset, Byval lppe As _Offset)
Function Process32Next%% (ByVal hSnapshot As _Offset, Byval lppe As _Offset)
End Declare
Declare CustomType Library
Function OpenProcess%& (ByVal dwDesiredAccess As Long, Byval bInheritHandle As Long, Byval dwProcessId As _Unsigned Long)
Function ReadProcessMemory%% (ByVal hProcess As _Offset, Byval lpBaseAddress As _Offset, Byval lpBuffer As _Offset, Byval nSize As _Offset, Byval lpNumberOfBytesRead As _Offset)
Function WriteProcessMemory%% (ByVal hProcess As _Offset, Byval lpBaseAddress As _Offset, Byval lpBuffer As _Offset, Byval nSize As _Offset, Byval lpNumberOfBytesWritten As _Offset)
Sub TomCloseHandle Alias "CloseHandle" (ByVal hObject As _Offset)
Function strlen& (ByVal ptr As _Unsigned _Offset)
End Declare
Function PeekByte%% (process As String, address As _Unsigned _Offset)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
Dim As _Byte result
memo = ReadProcessMemory(hProcess, address, _Offset(result), 1, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PeekByte = result
End Function
Function PokeByte% (process As String, address As _Unsigned _Offset, value As _Byte)
Dim As _Offset hProcessSnap
Dim As _Offset hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim memo As _Byte
memo = WriteProcessMemory(hProcess, address, _Offset(value), 1, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PokeByte = memo
End Function
Function PeekUnsignedByte~%% (process As String, address As _Unsigned _Offset)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
Dim As _Unsigned _Byte result
memo = ReadProcessMemory(hProcess, address, _Offset(result), 1, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PeekUnsignedByte = result
End Function
Function PokeUnsignedByte% (process As String, address As _Unsigned _Offset, value As _Unsigned _Byte)
Dim As _Offset hProcessSnap
Dim As _Offset hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim memo As Integer
memo = WriteProcessMemory(hProcess, address, _Offset(value), 1, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PokeUnsignedByte = memo
End Function
Function PeekInt% (process As String, address As _Unsigned _Offset)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
Dim As Integer result
memo = ReadProcessMemory(hProcess, address, _Offset(result), 2, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PeekInt = result
End Function
Function PokeInt% (process As String, address As _Unsigned _Offset, value As Integer)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
memo = WriteProcessMemory(hProcess, address, _Offset(value), 2, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PokeInt = memo
End Function
Function PeekUnsignedInt~% (process As String, address As _Unsigned _Offset)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
Dim As _Unsigned Integer result
memo = ReadProcessMemory(hProcess, address, _Offset(result), 2, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PeekUnsignedInt = result
End Function
Function PokeUnsignedInt% (process As String, address As _Unsigned _Offset, value As _Unsigned Integer)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
memo = WriteProcessMemory(hProcess, address, _Offset(value), 2, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PokeUnsignedInt = memo
End Function
Function PeekLong& (process As String, address As _Unsigned _Offset)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
Dim As Long result
memo = ReadProcessMemory(hProcess, address, _Offset(result), 4, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PeekLong = result
End Function
Function PokeLong% (process As String, address As _Unsigned _Offset, value As Long)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
memo = WriteProcessMemory(hProcess, address, _Offset(value), 4, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PokeLong = memo
End Function
Function PeekUnsignedLong~& (process As String, address As _Unsigned _Offset)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
Dim As _Unsigned Long result
memo = ReadProcessMemory(hProcess, address, _Offset(result), 4, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PeekUnsignedLong = result
End Function
Function PokeUnsignedLong% (process As String, address As _Unsigned _Offset, value As _Unsigned Long)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
memo = WriteProcessMemory(hProcess, address, _Offset(value), 4, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PokeUnsignedLong = memo
End Function
Function PeekInt64&& (process As String, address As _Unsigned _Offset)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
Dim As _Integer64 result
memo = ReadProcessMemory(hProcess, address, _Offset(result), 8, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PeekInt64 = result
End Function
Function PokeInt64% (process As String, address As _Unsigned _Offset, value As _Integer64)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
memo = WriteProcessMemory(hProcess, address, _Offset(value), 8, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PokeInt64 = memo
End Function
Function PeekUnsignedInt64~&& (process As String, address As _Unsigned _Offset)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
Dim As _Unsigned _Integer64 result
memo = ReadProcessMemory(hProcess, address, _Offset(result), 8, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PeekUnsignedInt64 = result
End Function
Function PokeUnsignedInt64% (process As String, address As _Unsigned _Offset, value As _Unsigned _Integer64)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
memo = WriteProcessMemory(hProcess, address, _Offset(value), 8, 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PokeUnsignedInt64 = memo
End Function
Function PeekString$ (process As String, address As _Unsigned _Offset)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
Dim As String result
result = Space$(strlen(address))
memo = ReadProcessMemory(hProcess, address, _Offset(result), Len(result), 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PeekString = result
End Function
Function PokeString% (process As String, address As _Unsigned _Offset, value As String)
Dim As _Offset hProcessSnap, hProcess
Dim As PROCESSENTRY32 pe32
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
pe32.dwSize = Len(pe32)
If Process32First(hProcessSnap, _Offset(pe32)) Then
While Process32Next(hProcessSnap, _Offset(pe32))
If _StrCmp(Left$(pe32.szExeFile, InStr(pe32.szExeFile, ".exe" + Chr$(0)) + 3), process) = 0 Then
hProcess = OpenProcess(PROCESS_VM_READ Or PROCESS_QUERY_INFORMATION Or PROCESS_VM_WRITE Or PROCESS_VM_OPERATION, TOM_FALSE, pe32.th32ProcessID)
Dim As _Byte memo
Dim As Long lenaddress
lenaddress = strlen(address)
If Right$(value, 1) <> Chr$(0) Then
value = value + Chr$(0)
End If
If lenaddress > Len(value) Then
Dim As Long i
For i = 1 To lenaddress
value = value + Chr$(0)
Next
End If
memo = WriteProcessMemory(hProcess, address, _Offset(value), Len(value), 0)
Exit While
End If
Wend
End If
TomCloseHandle hProcessSnap
TomCloseHandle hProcess
PokeString = memo
End Function
Sub RelaunchAsAdmin
If _ShellHide(">nul 2>&1 " + Chr$(34) + "%SYSTEMROOT%\system32\cacls.exe" + Chr$(34) + " " + Chr$(34) + "%SYSTEMROOT%\system32\config\system" + Chr$(34)) = 5 Then 'not admin
Shell _Hide _DontWait "PowerShell Start-Process " + "'" + Chr$(34) + Command$(0) + Chr$(34) + "'" + " -Verb runAs"
System
End If
End Sub
'End $INCLUDE
RE: Pointer in Basic - Kernelpanic - 07-17-2023
@SagraS - Thanks for the example and the description in German.
I tried a few things with the example to understand the whole thing. Well, it comes so slowly, understanding. The thing about _MEM is new for me in Basic.
The number in SEGBlock.TYPE obviously depends on the variable declaration, because it changes depending on the variable type. Is there a table showing what each number means?
What still surprises me is that with a 2nd number, the memory address increases by 8 bytes, but SEGBlock.SIZE and SEGBlock.ELEMENTSIZE only show 4 bytes (4 + 4?).
Code: (Select All) 'SagraS, Beispiel fuer die Nutzung von _MEM - 16. Juli 2023
' 32Bit / 64Bit Speicher (Der von Windows)
' Reine 32/64 Bit Adressierung
' 32/64 Bit Pointer
' Funktioniert fuer Werte mit bis zu 64Bit (Integer64)
Option _Explicit
Dim SEGBlock As _MEM
Dim As _Unsigned Long wert, wert1, wert2
Dim As _Offset position, position1
Print
Input "Zahl eingeben : ", wert
Print
Input "Noch eine Zahl: ", wert1
' Speicherblock der Variable ermitteln
SEGBlock = _Mem(wert)
'Entspricht der Startadresse
position = _Offset(wert)
position1 = _Offset(wert1)
' Aendern des Wertes im Speicher um -5 / +5
_MemPut SEGBlock, SEGBlock.OFFSET, _MemGet(SEGBlock, SEGBlock.OFFSET, Long) + 5 As LONG
' Wert aus dem Speicher holen
wert2 = _MemGet(SEGBlock, SEGBlock.OFFSET, Long)
Print
Print "Position erste Zahlim Speicher : "; position
Print
Print "Position zweite Zahlim Speicher : "; position1
Print
Print "Speicher Startadresse : "; SEGBlock.OFFSET
Print "Groesse des Blocks(Byte) : "; SEGBlock.SIZE
Print "Type des Blocks(Nummer) : "; SEGBlock.TYPE
Print "Datentyp des Blocks(Nach Dim) : "; SEGBlock.ELEMENTSIZE
Print "Neuer Inhalt der Speicheradresse: "; wert2
Print
'Startadresse bleibt gleich, es wird ja nur der Inhalt geaendert
Print "Startadresse neuer Inhalt : "; SEGBlock.OFFSET
' Speicherblock freigeben
_MemFree SEGBlock
End
RE: Pointer in Basic - SagaraS - 07-17-2023
Here a new Code Example:
variable wert2_I on line 62 is a test value for a example in the text (line 8 - 46)
Code: (Select All)
'SagraS, Beispiel fuer die Nutzung von _MEM - 16. Juli 2023
' 32Bit / 64Bit Speicher (Der von Windows)
' Reine 32/64 Bit Adressierung
' 32/64 Bit Pointer
' Funktioniert fuer Werte mit bis zu 64Bit (Integer64)
'*****************************************
' Das hier ist der Datentyp den _MEM erzeugt
' IMAGE und SOUND wird erst mit dem jeweiligen _MEMIMAGE oder _MEMSOUND Befehl
' aufgerufen. So wuerde sich der Datentyp sogar vergroessern
' Also hast du die ersten 4 Datentypen des Typs memory_type fuer _MEM
'
' TYPE memory_type
' OFFSET AS _OFFSET 'start location of block(changes with byte position)
' SIZE AS _OFFSET 'size of block remaining at offset(changes with position)
' TYPE AS _OFFSET 'type description of variable used(never changes)
' ELEMENTSIZE AS _OFFSET 'byte size of values inside the block(never changes)
' -----------------------
' IMAGE AS LONG 'the image handle used when _MEMIMAGE(handle) is used
' SOUND AS LONG 'the sound handle used when _MEMSOUND(handle) is used
' END TYPE
'
' Jede Position im Speicher egal um welchen Datentyp es sich handelt betraegt
' 8 Bytes, da die Funktion von _MEM fuer 64Bit ausgelegt ist.
' Du kannst dich auch nur innerhalb des jeweiligen Speicher Segmentes bewegen
' In diesem Falle die 8 Bytes
' Bedeutet:
' Um Fehler vorzubeugen, weil du einen Wert mit Integer reingeschrieben hast,
' kannst du diesen Wert an selber Adresse mit einem Integer64 Datentyp auslesen
' lassen, ohne den Wert darin zu gefaehrden.
'
' Darum ist _MEM auch sehr sicher und man kann nix ausserhalb seines Programmes
' kaputt machen. z.B. Windows eigene Speicher Adressen, so das dein Rechner z.B.
' einfach runter faehrt.
'
' Gibst du eine INTEGER64 Variable in den Speicher mit _MEM, so kannst
' du die ersten 4, 2 oder 1 Byte mit long, integer oder einem Byte Datentyp
' von dieser Zahl auslesen
' z.B. &FEDC BA98 7654 3210 <- Integer64
' Jetzt kannst du mit _MEMGET einen LONG Wert daraus auslesen
' und die Offset Position darin verschieben.
' z.B. willst du BA98 7654 auslesen
' Dann geht das so:
' wert2_O = _MEMGET(SEGBlock2, SEGBlock2.OFFSET + 2, LONG)
OPTION _EXPLICIT
DIM SEGBlock1 AS _MEM
DIM SEGBlock2 AS _MEM
DIM AS _UNSIGNED _INTEGER64 wert1_I, wert2_I
DIM AS _UNSIGNED LONG wert1_O, wert2_O
DIM AS _OFFSET position1, position2
PRINT
INPUT "Zahl eingeben : ", wert1_I
PRINT
INPUT "Noch eine Zahl: ", wert2_I
' Test Wert fuer wert2
wert2_I = &HFEDCBA9876543210
' Speicherblock der Variable ermitteln
SEGBlock1 = _MEM(wert1_I)
SEGBlock2 = _MEM(wert2_I)
'Entspricht der Startadresse
' *** Dies ist unnoetig fuer _MEM ***
position1 = _OFFSET(wert1_I)
position2 = _OFFSET(wert2_I)
' Aendern des Wertes im Speicher um +5
' *** Mit _MEMPUT kannst du an einer Offsetadresse ein Wert eintragen ***
' Um den Wert zu aendern der bereits drin steht, holt man ihn mit _MEMGET raus und manupuliert ihn
'_MEMPUT SEGBlock1, SEGBlock1.OFFSET, _MEMGET(SEGBlock1, SEGBlock1.OFFSET, _OFFSET) + 5 AS _OFFSET
' Wert aus dem Speicher holen
wert1_O = _MEMGET(SEGBlock1, SEGBlock1.OFFSET, LONG)
wert2_O = _MEMGET(SEGBlock2, SEGBlock2.OFFSET + 2, LONG) ' <- 3-6 Byte auslesen
PRINT LEN(SEGBlock1)
PRINT
PRINT "Position 1te Zahl im Speicher : &H" + HEX$(position1)
PRINT "Position 2te Zahl im Speicher : &H" + HEX$(position2)
PRINT
PRINT "Position 1te Zahl im Speicher : &H" + HEX$(SEGBlock1.OFFSET)
PRINT "Groesse des Blocks(Byte) : &H" + HEX$(SEGBlock1.SIZE)
PRINT "Type des Blocks(Nummer) : &H" + HEX$(SEGBlock1.TYPE)
PRINT "Datentyp des Blocks(Nach Dim) : &H" + HEX$(SEGBlock1.ELEMENTSIZE)
PRINT "Inhalt der Speicheradresse : " + STR$(wert1_O) + " HEX( " + HEX$(wert1_O) + " )"
PRINT
PRINT "Position 2te Zahl im Speicher : &H" + HEX$(SEGBlock2.OFFSET)
PRINT "Groesse des Blocks(Byte) : &H" + HEX$(SEGBlock2.SIZE)
PRINT "Type des Blocks(Nummer) : &H" + HEX$(SEGBlock2.TYPE)
PRINT "Datentyp des Blocks(Nach Dim) : &H" + HEX$(SEGBlock2.ELEMENTSIZE)
PRINT "Inhalt der Speicheradresse : " + STR$(wert2_O) + " HEX( " + HEX$(wert2_O) + " )"
PRINT
'Startadresse bleibt gleich, es wird ja nur der Inhalt geaendert
PRINT "Startadresse neuer Inhalt : "; SEGBlock1.OFFSET
' Speicherblock freigeben
_MEMFREE SEGBlock1
_MEMFREE SEGBlock2
END
|