Pointer in Basic
#1
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
[Image: Zeiger-in-Basic2023-07-16.jpg]
Reply
#2
Check out the memory stuff, maybe start with Type.

https://qb64phoenix.com/qb64wiki/index.php/MEM
b = b + ...
Reply
#3
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
Reply
#4
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
Reply
#5
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://staging.qb64phoenix.com/showthread.php?tid=172
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#6
"As bplus already elucidated,"

OMG I am elucidating again!

Well I think SagaraS is germaining. ;-))
b = b + ...
Reply
#7
Spartan-style pointer-esque API for QB64 for those willing to step outside the safety of MEM.  Big Grin

https://github.com/a740g/Toolbox64/blob/...nterOps.bi
https://github.com/a740g/Toolbox64/blob/...interOps.h
Reply
#8
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


Attached Files
.txt   PeepingTom Example.txt (Size: 21.85 KB / Downloads: 45)
Ask me about Windows API and maybe some Linux stuff
Reply
#9
@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
[Image: MEM-Uebung2023-07-17.jpg]
Reply
#10
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
Reply




Users browsing this thread: 11 Guest(s)