[PureBasic] WinAPI (ReadProcessMemory) Problem

09/21/2012 22:48 Sentence'#1
Hey,

Da ich nicht weiß wo es sonst hinkommt versuch ich es mal hier^^

Also ich hab ein Problem mit ReadProcessMemory & WriteProcessMemory, es kommen IMMER die selben werte raus egal welche addresse ich nehme..

Code:
If OpenWindow(0, 0, 0, 100, 70, "Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  ButtonGadget(0, 10, 10, 80, 50, "Klick Mich")
  Repeat
    Event = WaitWindowEvent()
    If Event = #PB_Event_Gadget
      Select EventGadget()
        Case 0
          If OffOn = 0
            window = FindWindow_("Nksp","Last Chaos - RPG Version by Tarissuis (Window 1024x768)")    ;Finds the Window Title
            MessageRequester("",Str(window))
            GetWindowThreadProcessId_(window, @ProcessID)
            MessageRequester("",Str(ProcessID))
            hProcess = OpenProcess_(#PROCESS_ALL_ACCESS,0,ProcessID)
            *address = $1073A334
            reaad = ReadProcessMemory_(hProcess, *address, @buffer,4,@gelesen)  
            MessageRequester("",Str(@buffer)+#CRLF$+Str(@gelesen))
EndIf
      EndSelect
    EndIf
  Until Event = #PB_Event_CloseWindow
EndIf
Es geht um das Spiel LastChaos und ich möchte den wert für Auflösung : X auslesen

Hoffe hier kann jemand purebasic bzw kennt sich mit ReadProcessMemory aus :)
10/04/2012 19:00 WarmongerR4#2
Code:
Enumeration
  #Button_0
EndEnumeration

If OpenWindow(0, 0, 0, 100, 70, "Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  ButtonGadget(#Button_0, 10, 10, 80, 50, "Klick Mich")
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case EventGadget(
        Select #PB_Event_Gadget
          Case #Button_0
            window = FindWindow_("Nksp", 0)    ;Finds the Window Title
            MessageRequester("",Str(window))
            GetWindowThreadProcessId_(window, @ProcessID)
            MessageRequester("",Str(ProcessID))
            hProcess = OpenProcess_(#PROCESS_ALL_ACCESS,0,ProcessID)
            *address = $1073A334
            reaad = ReadProcessMemory_(hProcess, *address, @buffer,4,@gelesen)  
            MessageRequester("",Str(@buffer)+#CRLF$+Str(@gelesen))
        EndSelect
    EndSelect
  Until Event = #PB_Event_CloseWindow
EndIf
Plus ReadProcessMemory() is to be used like this.

Code:
ReadProcessMemory_(hProcess, Pointer + $FC4B0, @AttackDefault, SizeOf(AttackDefault), #Null)
10/04/2012 21:53 Sentence'#3
Quote:
Originally Posted by WarmongerR4 View Post
Code:
Enumeration
  #Button_0
EndEnumeration

If OpenWindow(0, 0, 0, 100, 70, "Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  ButtonGadget(#Button_0, 10, 10, 80, 50, "Klick Mich")
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case EventGadget(
        Select #PB_Event_Gadget
          Case #Button_0
            window = FindWindow_("Nksp", 0)    ;Finds the Window Title
            MessageRequester("",Str(window))
            GetWindowThreadProcessId_(window, @ProcessID)
            MessageRequester("",Str(ProcessID))
            hProcess = OpenProcess_(#PROCESS_ALL_ACCESS,0,ProcessID)
            *address = $1073A334
            reaad = ReadProcessMemory_(hProcess, *address, @buffer,4,@gelesen)  
            MessageRequester("",Str(@buffer)+#CRLF$+Str(@gelesen))
        EndSelect
    EndSelect
  Until Event = #PB_Event_CloseWindow
EndIf
Plus ReadProcessMemory() is to be used like this.

Code:
ReadProcessMemory_(hProcess, Pointer + $FC4B0, @AttackDefault, SizeOf(AttackDefault), #Null)
I got it worked few days ago :) but thanks
10/05/2012 02:31 WarmongerR4#4
Lost internet earlier, but here is the proper way to write it.

Code:
Enumeration
  #Window_0
EndEnumeration

Enumeration
  #Button_0
EndEnumeration

If OpenWindow(#Window_0, 0, 0, 150, 70, "Test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  ButtonGadget(#Button_0, 10, 10, 130, 50, "Click Me")
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #Button_0
            Window = FindWindow_("Nksp", 0) ;Get Window Handle
            If Window <> #Null
              GetWindowThreadProcessId_(Window, @ProcessID)
              hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, 0, ProcessID)
              ReadProcessMemory_(hProcess, $1073A334, @Buffer, SizeOf(Buffer), #Null)
              MessageRequester("Memory", Str(@Buffer))
            Else
              MessageRequester("Error", "Window Not Found")
            EndIf
        EndSelect
    EndSelect
  Until Event = #PB_Event_CloseWindow
EndIf
01/10/2020 03:20 Syr1#5
Für alle die einen Purebasic Code zur Orientierung brauchen: Modul und Offsets werden mit Cheatengine erstellt. Beispielprogramm hier ist Fishing Planet.

Code:
;Es braucht die Funktion CreateToolhelp32Snapshot() aus der kernler32.dll
Global kernel32=OpenLibrary(#PB_Any, "kernel32.dll")

;Prozdur liefert den Basepointer (Trampolin) des Moduls. 
;Die ProcessID muss via GetWindowThreadProcessId_ vorher gefunden werden.
;Modulname ist einfach die dll (z.b. "mono.dll")
;Module sind nur nötig wenn die pointer aus der exe rausgehen
Procedure.i GetModule(ProcessId.l, ModuleName.s)
  ;Handle für externen Prozess 
  Protected snapShot.i
  ;Struktur für die Eigenschaften eines Moduls
  Protected Me32.MODULEENTRY32
   ;Wenn die Library "kernel32.dll" geladen wurden
   If kernel32
     ;Rufe die Funktion ToolHelp mit der ProcessID auf. Gibt den Handle auf die Module der ProcessID
     snapShot=CallFunction(kernel32, "CreateToolhelp32Snapshot", #TH32CS_SNAPMODULE, ProcessId)
     ;falls erfolgreich
     If snapShot
       ;Bereite eine Struktur des Typs Moduleentry32 vor um die einzelnen Module nacheinander da reinzuschreiben
       ;Die Größe der Struktur wird in der Struktur festgehalten (Windows-eigen)
       Me32\dwSize=SizeOf(MODULEENTRY32)
       ;Belade die Struktur mit dem ersten Modul des Prozesses
       If CallFunction(kernel32, "Module32First", snapShot,  [MENTION=321286]me3[/MENTION]2)
         ;Werte den Modulnamen aus
         Repeat
           ;Lese String aus dem Speicherbereich Me32\szModule bis zur Nullterminierung (-1) aks ASCCI
           Protected moduleName$=PeekS  [MENTION=321286]me3[/MENTION]2\szModule, -1, #PB_Ascii)
           ;Ist der String der gesuchten Modulnamen?
           If moduleName$=ModuleName
             ;Falls ja, abbruch und Baseaddresse aus der Struktur auslesen und returnen
             ProcedureReturn Me32\modBaseAddr
           EndIf
            ;Sonst: Nächstes Modul bis es kein Nächstes mehr gibt.
         Until Not CallFunction(kernel32, "Module32Next", snapShot,  [MENTION=321286]me3[/MENTION]2)
       EndIf
       ;Alle Module wurden durchsucht / es wurde das richtige gefunden. Jetzt den Funktionshandle freigaben (max 4048 pro Programm)
       CloseHandle_(snapShot)
     EndIf
   EndIf
   ;Wenn oben keine Baseadresse ermittelt werden konnte, gebe Null zurück
   ProcedureReturn 0
EndProcedure

Procedure.l GefangeneFische(hProcess,ProcessId) ;geht nimmer
  ;Wenn nötig gehe die Module dieser ProcessID nach einen speziellen Modul durch und ermittle die Startadresse dafür
  *moduleAddress=GetModule(ProcessId, "mono.dll")
  ;Erstelle eine 8-Byte-Variable für Pointer. Die Pointer liegen im Speicher als little-endian vor (Intel).
  ergebnis.q
  ;Lese mit dem Lese/Schreib-Handle von der Moduladresse + Offset und schreibe in die Adresse von Ergebnis alle 8 Byte.
  ;Die Erfolgsmeldung wird nicht verarbeitet. Die Anzahl der gelesenen Bytes wird ignoriert.
  ReadProcessMemory_(hProcess, *moduleAddress+$00500AC8 ,  [MENTION=2472835]Erge[/MENTION]bnis, 8, #IGNORE)
  ;Der Ermittelte Pointer wird nun um ein neuen Offsete erhöht und selbst wieder als Zieladresse verwendet.
  ReadProcessMemory_(hProcess, ergebnis+$20   ,  [MENTION=2472835]Erge[/MENTION]bnis, 8, #IGNORE)
  ReadProcessMemory_(hProcess, ergebnis+$640  ,  [MENTION=2472835]Erge[/MENTION]bnis, 8, #IGNORE)
  ReadProcessMemory_(hProcess, ergebnis+$0   ,  [MENTION=2472835]Erge[/MENTION]bnis, 8, #IGNORE)
  ReadProcessMemory_(hProcess, ergebnis+$48   ,  [MENTION=2472835]Erge[/MENTION]bnis, 8, #IGNORE)
  ReadProcessMemory_(hProcess, ergebnis+$E0   ,  [MENTION=2472835]Erge[/MENTION]bnis, 8, #IGNORE)
  ReadProcessMemory_(hProcess, ergebnis+$10   ,  [MENTION=2472835]Erge[/MENTION]bnis, 8, #IGNORE)
  ReadProcessMemory_(hProcess, ergebnis+$18   ,  [MENTION=2472835]Erge[/MENTION]bnis, 8, #IGNORE)
  ;Solange bis laut CheatEngine das Ergebnis erreicht wurde
  ;Je nach Ergebnis müssen mehrere Bytes(vorsicht: little endian) aus dem Speicher gelesen werden
  ;Laut CheatEngine ist das Ergebnis ein 4-Byte Wert. Bei Purebasicx64 sind Integer aber 8 Bytes lang.
  ;Daher wird das ergebnis als long, also mit 4 byte gelesen
  Schnur.l = PeekL  [MENTION=2472835]Erge[/MENTION]bnis)
  ProcedureReturn Schnur
EndProcedure


;Besorge den Handle der Execuatable aus dem Speicher
Window = FindWindow_(0,"Fishing Planet")
;Wenn der Handle gefunden wurde
If Window <> #Null
  ;Besorge die dazugehörige ProcessID
  GetWindowThreadProcessId_(Window,  [MENTION=2699288]Process[/MENTION]ID)
  ;Besorge einen Handle(hProcess) mit Lese/Schreibzugriff auf diese ProcessID
  hProcess = OpenProcess_(#PROCESS_ALL_ACCESS, 0, ProcessID)
  
  Debug GefangeneFische(hProcess,ProcessId)
EndIf
;Unnötig aber sauber: zum Schluss wird auch der Handle auf die kernel32.dll wieder freigegeben
CloseLibrary(kernel32)
Der Code wurde leider irgendwie anstelle der @ Zeichen ersetzt. Im Anhang ist die Orginalfassung.