It is currently Tue Sep 29, 2020 9:49 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 26 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Need help converting 'trainer' to PureBasic
PostPosted: Mon Oct 27, 2003 3:54 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Fri Apr 25, 2003 5:24 pm
Posts: 7581
This is a small app that opens Calc.exe and then replaces the 'Backspace'
button text with 'VB-O-Matic' (like a trainer). I've tried converting this to
PureBasic without success. Is anyone able to please help? (The VB code
works fine on Win 2000, so I know the routine definitely works).

Code:
Private Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long
    szCSDVersion As String * 128
End Type

Private Type MEMORY_BASIC_INFORMATION ' 28 bytes
    BaseAddress As Long
    AllocationBase As Long
    AllocationProtect As Long
    RegionSize As Long
    State As Long
    Protect As Long
    lType As Long
End Type

Private Type SYSTEM_INFO ' 36 Bytes
    dwOemID As Long
    dwPageSize As Long
    lpMinimumApplicationAddress As Long
    lpMaximumApplicationAddress As Long
    dwActiveProcessorMask As Long
    dwNumberOrfProcessors As Long
    dwProcessorType As Long
    dwAllocationGranularity As Long
    wProcessorLevel As Integer
    wProcessorRevision As Integer
End Type

Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (LpVersionInformation As OSVERSIONINFO) As Long
Private Declare Function VirtualQueryEx& Lib "kernel32" (ByVal hProcess As Long, lpAddress As Any, lpBuffer As MEMORY_BASIC_INFORMATION, ByVal dwLength As Long)
Private Declare Sub GetSystemInfo Lib "kernel32" (lpSystemInfo As SYSTEM_INFO)
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal blnheritHandle As Long, ByVal dwAppProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long

Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As Long, ByVal lpWindowName As Long) As Long
Private Declare Function GetParent Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
Const GW_HWNDNEXT = 2

Private Declare Function InvalidateRect Lib "user32" (ByVal hWnd As Long, ByVal lpRect As Long, ByVal bErase As Long) As Long
Const PROCESS_VM_READ = (&H10)
Const PROCESS_VM_WRITE = (&H20)
Const PROCESS_VM_OPERATION = (&H8)
Const PROCESS_QUERY_INFORMATION = (&H400)
Const PROCESS_READ_WRITE_QUERY = PROCESS_VM_READ + PROCESS_VM_WRITE + PROCESS_VM_OPERATION + PROCESS_QUERY_INFORMATION

Const MEM_PRIVATE& = &H20000
Const MEM_COMMIT& = &H1000

'Add 3 labels, 3 textboxes and 1 commandbutton on form

Private Sub Command1_Click()
    Dim pid As Long, hProcess As Long, hWin As Long
    Dim lpMem As Long, ret As Long, lLenMBI As Long
    Dim lWritten As Long, CalcAddress As Long, lPos As Long
    Dim sBuffer As String
    Dim sSearchString As String, sReplaceString As String
    Dim si As SYSTEM_INFO
    Dim mbi As MEMORY_BASIC_INFORMATION
    sSearchString = Text2
    sReplaceString = Text3 & Chr(0)
    If IsWindowsNT Then 'NT store strings in RAM in UNICODE
       sSearchString = StrConv(sSearchString, vbUnicode)
       sReplaceString = StrConv(sReplaceString, vbUnicode)
    End If
    pid = Shell(Text1) 'launch application (calc.exe in this sample)
    hWin = InstanceToWnd(pid) 'get handle of launched window - only to repaint it after changes
'Open process with required access
    hProcess = OpenProcess(PROCESS_READ_WRITE_QUERY, False, pid)
    lLenMBI = Len(mbi)
'Determine applications memory addresses range
    Call GetSystemInfo(si)
    lpMem = si.lpMinimumApplicationAddress
'Scan memory
    Do While lpMem < si.lpMaximumApplicationAddress
        mbi.RegionSize = 0
        ret = VirtualQueryEx(hProcess, ByVal lpMem, mbi, lLenMBI)
        If ret = lLenMBI Then
            If ((mbi.lType = MEM_PRIVATE) And (mbi.State = MEM_COMMIT)) Then ' this block is In use by this process
                If mbi.RegionSize > 0 Then
                   sBuffer = String(mbi.RegionSize, 0)
'Read region into string
                   ReadProcessMemory hProcess, ByVal mbi.BaseAddress, ByVal sBuffer, mbi.RegionSize, lWritten
'Check if region contain search string
                   lPos = InStr(1, sBuffer, sSearchString, vbTextCompare)
                   If lPos Then
                      CalcAddress = mbi.BaseAddress + lPos
                      Me.Show
                      ret = MsgBox("Search string was found at address " & CalcAddress & "." & vbCrLf & "Do you want to replace it?", vbInformation + vbYesNo, "VB-O-Matic")
                      If ret = vbYes Then
'Replace string in virtual memory
                         Call WriteProcessMemory(hProcess, ByVal CalcAddress - 1, ByVal sReplaceString, Len(sReplaceString), lWritten)
'Redraw window
                         InvalidateRect hWin, 0, 1
                      End If
                      Exit Do
                   End If
                End If
            End If
'Increase base address for next searching cicle. Last address may overhead max Long value (Windows use 2GB memory, which is near max long value), so add Error checking
            On Error GoTo Finished
            lpMem = mbi.BaseAddress + mbi.RegionSize
            On Error GoTo 0
        Else
            Exit Do
        End If
    Loop
Finished:
   CloseHandle hProcess
End Sub

Private Sub Form_Load()
   Caption = "VB-O-Matic"
   Label1 = "Start application:"
   Label2 = "String to find:"
   Label3 = "Replace with:"
   Text1 = "Calc.exe"
   Text2 = "Backspace"
   Text3 = "VB-O-Matic"
   Command1.Caption = "&Launch It!"
End Sub

Private Function InstanceToWnd(ByVal target_pid As Long) As Long
  Dim test_hwnd As Long
  Dim test_pid As Long
  Dim test_thread_id As Long
  test_hwnd = FindWindow(ByVal 0&, ByVal 0&)
  Do While test_hwnd <> 0
   If GetParent(test_hwnd) = 0 Then
      test_thread_id = GetWindowThreadProcessId(test_hwnd, test_pid)
      If test_pid = target_pid Then
         InstanceToWnd = test_hwnd
         Exit Do
      End If
   End If
   test_hwnd = GetWindow(test_hwnd, GW_HWNDNEXT)
  Loop
End Function

Private Function IsWindowsNT() As Boolean
   Dim verinfo As OSVERSIONINFO
   verinfo.dwOSVersionInfoSize = Len(verinfo)
   If (GetVersionEx(verinfo)) = 0 Then Exit Function
   If verinfo.dwPlatformId = 2 Then IsWindowsNT = True
End Function


Top
 Profile  
Reply with quote  
 Post subject: Re: Need help converting 'trainer' to PureBasic
PostPosted: Mon Nov 24, 2003 4:26 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Fri Apr 25, 2003 5:24 pm
Posts: 7581
Okay, I've converted the code pretty much to PureBasic, but it doesn't work.
Anyone got any ideas why? I'm testing it on Windows 2000 and the Visual
Basic version does work on there, so it's not like the code can't access the
Calc's process memory or anything. In particular, see the line that I've
marked with *** that seems to be causing the failure.

Again, this code is for Windows 2000 only. Once we get it working, we can
start adapting it for all other versions of Windows.

Code:
#PROCESS_VM_READ = $10
#PROCESS_VM_WRITE = $20
#PROCESS_VM_OPERATION = $8
#PROCESS_QUERY_INFORMATION = $400
#PROCESS_READ_WRITE_QUERY = #PROCESS_VM_READ|#PROCESS_VM_WRITE|#PROCESS_VM_OPERATION|#PROCESS_QUERY_INFORMATION

#MEM_PRIVATE = $20000
#MEM_COMMIT = $1000

Global ProcessID.l

Procedure.l RunProgramEx(Filename.s,Parameter.s,Directory.s,ShowFlag.l)
  Info.STARTUPINFO : Info\cb=SizeOf(STARTUPINFO) : Info\dwFlags=1
  Info\wShowWindow=ShowFlag : ProcessInfo.PROCESS_INFORMATION
  ProcessPriority=#NORMAL_PRIORITY_CLASS
  If CreateProcess_(@Filename,@Parameter,0,0,0,ProcessPriority,0,@Directory,@Info,@ProcessInfo)
    ProcessID.l=ProcessInfo\dwProcessId
    Repeat
      win=FindWindow_(0,0)
      While win<>0
        GetWindowThreadProcessId_(win,@pid.l)
        If pid=ProcessID : WinHandle=win : Break : EndIf
        win=GetWindow_(win,#GW_HWNDNEXT)
      Wend
    Until WinHandle
  EndIf
  ProcedureReturn WinHandle
EndProcedure

sSearchString.s = "Backspace"
sReplaceString.s = "PB-O-Matic"

;If IsWindowsNT ;NT store strings in RAM in UNICODE
;   sSearchString = StrConv(sSearchString, vbUnicode)
;   sReplaceString = StrConv(sReplaceString, vbUnicode)
;EndIf

si.SYSTEM_INFO
mbi.MEMORY_BASIC_INFORMATION

hWin=RunProgramEx("c:\winnt\system32\calc.exe","","c:\winnt\system32\",#SW_SHOW)
hProcess = OpenProcess_(#PROCESS_READ_WRITE_QUERY,#FALSE,ProcessID)
lLenMBI = SizeOf(mbi)
GetSystemInfo_(si)
lpMem = si\lpMinimumApplicationAddress
While lpMem < si\lpMaximumApplicationAddress
    mbi\RegionSize = 0
    ; VB version of next line: ret = VirtualQueryEx(hProcess, ByVal lpMem, mbi, lLenMBI)
    ; In the VB version, if you remove "ByVal" then it doesn't work in VB either...
    ret = VirtualQueryEx_(hProcess, lpMem, mbi, lLenMBI) ; *** ALWAYS RETURNS 0 ***
    If ret = lLenMBI
        If ((mbi\lType = #MEM_PRIVATE) And (mbi\State = #MEM_COMMIT))
            If mbi\RegionSize > 0
               sBuffer.s = Space(mbi\RegionSize)
               ReadProcessMemory_(hProcess, mbi\BaseAddress, sBuffer, mbi\RegionSize, lWritten)
               lPos = FindString(sBuffer, sSearchString, 1)
               If lPos
                  CalcAddress = mbi\BaseAddress + lPos
                  WriteProcessMemory_(hProcess, CalcAddress - 1, sReplaceString, Len(sReplaceString), lWritten)
                  InvalidateRect_(hWin, 0, 1)
                  Break
               EndIf
            EndIf
        EndIf
        OnErrorGoto(?Finished)
        lpMem = mbi\BaseAddress + mbi\RegionSize
        OnErrorResume()
    Else
        Break
    EndIf
Wend
Finished:
CloseHandle_(hProcess)


Top
 Profile  
Reply with quote  
 Post subject: virtualqueryex second parameter
PostPosted: Mon Nov 24, 2003 12:12 pm 
Offline
User
User
User avatar

Joined: Fri Oct 31, 2003 2:57 pm
Posts: 40
Location: Italy
Quote:
; VB version of next line: ret = VirtualQueryEx(hProcess, ByVal lpMem, mbi, lLenMBI)
; In the VB version, if you remove "ByVal" then it doesn't work in VB either...


Yes, in VB without ByVal won't work, because the second parameter of VirtualQueryEx is LPCVOID, a const pointer to void, i.e. you tell that this pointer can't be changed by the routine, and in VB can be done forcing it to be passed by value, instead of by reference (as normally is without any modifier).

What I don't know is how to do it in PB, because if you pass a pointer just like you do, it certainly will fail....
have you tried
Code:
#lpMemConst = lpMem
ret = VirtualQueryEx_(hProcess, #lpMemConst, mbi, lLenMBI)


Let me know

_________________
--:: Gkaizer ::--
Using PB 3.92 on WinXP SP2 and 3.91 on Mandrake Linux 10.0


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Nov 24, 2003 11:07 pm 
Offline
User
User

Joined: Sun Nov 02, 2003 7:33 am
Posts: 33
Location: Pullman, WA
What is a "trainer?"

Bryan


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Nov 24, 2003 11:11 pm 
Offline
User
User
User avatar

Joined: Mon Oct 13, 2003 10:33 pm
Posts: 25
Location: England, Derbyshire.
bcgreen wrote:
What is a "trainer?"

Bryan


It's a running shoe j/k :lol:

_________________
Mr Tickle.
Athlon xp 2500+, Gigabyte KT400-FSB333, Gf3 Ti200, SB Live 5.1


Top
 Profile  
Reply with quote  
 Post subject: Re: virtualqueryex second parameter
PostPosted: Tue Nov 25, 2003 4:10 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Fri Apr 25, 2003 5:24 pm
Posts: 7581
> #lpMemConst = lpMem
> ret = VirtualQueryEx_(hProcess, #lpMemConst, mbi, lLenMBI)

That doesn't work, because you get an error about trying to create a
constant from a variable. I tried replacing lpMem with its actual value
(65536) but that didn't work either.

> what is a "trainer"?

It's an app that lets you change the process memory of another app.
For example: if a game gives you 3 lives, the value 3 is stored in the
game's memory somewhere. A trainer lets you change this 3 to another
value, like 255, to give you 255 lives. They're called "trainers" because
you get to play the game with a cheating edge, to "train" yourself in how
the game plays.

In the Visual Basic example here, the Windows Calculator is launched
and then its "Backspace" key is changed to "VB-O-Matic", much like
the 3 lives / 255 lives concept. That's what I'm trying to convert to
PureBasic.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Nov 25, 2003 4:48 am 
Offline
User
User

Joined: Wed Nov 05, 2003 4:34 am
Posts: 44
Location: Tokyo, Japan
:?:

How do you pass ByVal in PB????

Is there a workaround? That will break a lot of code converted from other basics

_________________
Paul Dwyer
Network Engineer
Aussie in Tokyo


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Nov 25, 2003 5:23 pm 
Offline
Administrator
Administrator

Joined: Fri May 17, 2002 4:39 pm
Posts: 14090
Location: France
Just use '@' to pass by val

Code:
Procedure Hello(*ReturnAddress)
  PokeL(*ReturnAddress, 10)
EndProcedure

Hello(@Result)

Debug Result


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Nov 25, 2003 6:01 pm 
Offline
User
User
User avatar

Joined: Fri Oct 31, 2003 2:57 pm
Posts: 40
Location: Italy
nope :lol: , what you're doing is -- hello receives a pointer and correctly you pass a pointer to variable Result...
where is the byval passing here?

what I think Paul wanted to ask is connected to my post, where I explained why you cannot cancel "ByVal" in VB in a call to VirtualQueryEx.

It seems that PB can't handle API whose parameters are declared constant pointer to void (and who knows to other types).

another example could be using memcpy in PB, the second argument is const void * or else MoveMemory, if someone has time to do a little test and post it back here would make clear if it's a limitation of PB or ours :o
that's my 2 cent's :

_________________
--:: Gkaizer ::--
Using PB 3.92 on WinXP SP2 and 3.91 on Mandrake Linux 10.0


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Nov 26, 2003 1:03 am 
Offline
User
User

Joined: Wed Nov 05, 2003 4:34 am
Posts: 44
Location: Tokyo, Japan
Now I'm confused... 8O

Some Windows API functions (or Dlls) require you to send constants by value and not a pointer to that value. If you don't have the constants declared then you can just pass the value "ByVal 5" or something.

How would you handle this in PB?

Thanks

_________________
Paul Dwyer
Network Engineer
Aussie in Tokyo


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Nov 26, 2003 10:07 am 
Offline
Administrator
Administrator

Joined: Fri May 17, 2002 4:39 pm
Posts: 14090
Location: France
Any example ? I don't understand really this 'By Val' stuff. PB can handle the API call exactly like C/C++ does, so I don't see any case where you will be stuck in PB... ;)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Nov 26, 2003 10:26 am 
Offline
User
User
User avatar

Joined: Fri Oct 31, 2003 2:57 pm
Posts: 40
Location: Italy
ok then, I'll try and see with some other API's that have that kind of argument and let you know what I find.

byz :lol:

_________________
--:: Gkaizer ::--
Using PB 3.92 on WinXP SP2 and 3.91 on Mandrake Linux 10.0


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Nov 26, 2003 10:27 am 
Offline
User
User

Joined: Wed Nov 05, 2003 4:34 am
Posts: 44
Location: Tokyo, Japan
Fred,

My understanding is that C passes parameters by value and not by reference which is why you pass a pointer. You pass the value of the 32bit address. You can pass actual values on the stack too. One very common one is a constant. The windows API is full of thousands of such constants to be passed as parameters as I'm sure you are aware.

In PB, when you pass a constant abviously you can't pass a pointer because a constant is not a variable it's a compiler equate. So can I just pass a constant as is and the compiler will know to pass the value and not attempt to send a pointer to... ?

Or in PB is everything passed by value rather than by reference so you have to pass you're own pointers?

_________________
Paul Dwyer
Network Engineer
Aussie in Tokyo


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Nov 26, 2003 11:50 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Oct 29, 2003 10:35 am
Posts: 537
Paul Dwyer wrote:
Now I'm confused... 8O

Some Windows API functions (or Dlls) require you to send constants by value and not a pointer to that value. If you don't have the constants declared then you can just pass the value "ByVal 5" or something.

How would you handle this in PB?

Thanks


You think you're confused 8O 8O 8O 8O !#$%& !!!

It's hard enough trying to use the API's, this thread is harder to understand than Algebra 8O

_________________
Paid up PB User !


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Nov 26, 2003 12:06 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 5:21 pm
Posts: 5813
Location: Germany
In PB, everything is passed by value, with these exceptions:

Structures are passed by reference
Strings are passed by reference
If you add the '@' before anything, it is also passed by reference.

I never had any trouble with API calls, i really don't understand the problem.

Timo

_________________
quidquid Latine dictum sit altum videtur


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 26 posts ]  Go to page 1, 2  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 69 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye