Results 1 to 10 of 10

Thread: Python Healer

  1. #1
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725

    Python Healer

    So I got a bit tired of the confusion brought on by C++, and with the requirement to use a specific IDE for C#. Further to that, I got sick of sitting here typing code which I'm unlikely to use in my career in the near future. Result? Bring on the Python healer.

    I got to this stage this morning (but now have to leave for work). Thought it might prove useful for someone should anyone here be interested in developing using Python.



    Heres the code behind it:

    memory.py:
    Code:
    import ctypes, win32ui, win32process ,win32api
    
    class Memory:
    	def __init__(self):
    		# Read and write process memory methods from kernel32
    		self.rPM = ctypes.windll.kernel32.ReadProcessMemory
    		self.wPM = ctypes.windll.kernel32.WriteProcessMemory
    		# PROCESS_ALL_ACCESS is a flag typically set in kernel32, for simplicity we shall define it here
    		PROCESS_ALL_ACCESS = 0x1F0FFF
    
    
    		# Acquire a HWND for Tibia
    		self.HWND = win32ui.FindWindow("TibiaClient",None).GetSafeHwnd()
    		print("HWND        : " + str(self.HWND))
    
    		# Acquire the ProcessID using our HWND
    		self.PID = win32process.GetWindowThreadProcessId(self.HWND)[1]
    		print("PID         : " + str(self.PID))
    
    		# Acquire a Process object to work with
    		self.PROCESS = win32api.OpenProcess(PROCESS_ALL_ACCESS,0,self.PID)
    		print("HANDLE      : " + str(self.PROCESS.handle))
    
    		# Enumerate Process MOdules to find the base address of Tibia
    		self.BASEADDRESSLIST = win32process.EnumProcessModules(self.PROCESS.handle)
    
    		# Take the first (C# "Default") base address from the list
    		self.BASEADDRESS = self.BASEADDRESSLIST[0]
    		print("BASEADDRESS : " + str(self.BASEADDRESS))
    
    
    
    #ALL GLOBALS DEFINED
    
    	def ReadInt(self, Address):
    		data = 4294967295
    		self.rPM(self.PROCESS.handle,Address+self.BASEADDRESS,data,32,0)
    		return data
    
    
    	def ReadString(self, Address):
    		data = b"wah"
    		buff = ctypes.create_string_buffer(data, 32)
    		self.rPM(self.PROCESS.handle,Address+self.BASEADDRESS,buff,32,0)
    		val = ctypes.string_at(buff).decode("utf-8")
    		return val
    main.py:
    Code:
    import memory
    
    mem = memory.Memory()
    
    print("Name from BattleList: " + mem.ReadString(5943964))
    print("CID from BattleList: " + str(mem.ReadInt(5943960)))
    Hope someone finds it useful

  2. #2
    How is this going?

  3. #3
    Junior Member
    Join Date
    Nov 2013
    Posts
    5
    When I try to use this with a custom client i get this error:
    Code:
    HWND        : 198814
    PID         : 13932
    Traceback (most recent call last):
      File "tst.py", line 3, in <module>
        mem = test.Memory()
      File "C:\Users\asd\Python\test.py", line 23, in __init__
        self.PROCESS = win32api.OpenProcess(PROCESS_ALL_ACCESS, 0, self.PID)
    pywintypes.error: (5, 'OpenProcess', 'Access is denied.')
    Any ideas why?

  4. #4
    Senior Member
    Join Date
    Jan 2012
    Posts
    417
    Code:
        self.PROCESS = win32api.OpenProcess(PROCESS_ALL_ACCESS, 0, self.PID)
    pywintypes.error: (5, 'OpenProcess', 'Access is denied.')
    I am not a python programmer, but judging by these lines seems like you are not running the program as Administrator... so test "Run as Administrator".

  5. #5
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Quote Originally Posted by szulak View Post
    How is this going?
    Currently it's almost done. I just haven't gotten round to doing the final steps. Here's what I have so far:

    Control.py:
    Code:
    import ctypes
    import win32ui
    import win32process
    import win32api
    import win32con
    
    class Control:
    	def __init__(self, hwnd, handle):
    		self.hwnd = hwnd
    		self.handle = handle
    
    	def SendKey(self, key):
    		for k in key:
    			print(str(k))
    			if k == "\n":
    				win32api.SendMessage(self.hwnd, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
    				win32api.SendMessage(self.hwnd, win32con.WM_KEYUP, win32con.VK_RETURN, 0)
    			else:
    				win32api.SendMessage(self.hwnd, win32con.WM_CHAR, ord(k), 0)
    Healer.py
    Code:
    from threading import Thread
    import time, random
    import control
    
    class Healer:
    	def __init__(self, rules, ctrl, mem):
    		Thread.__init__(self)
    		self.rules = rules
    		self.ctrl = ctrl
    		self.isStopped = False
    		self.mem = mem
    
    	def run(self):
    		self.isStopped = False
    		for i in self.rules:
    			print("HealRule")
    
    		while (~self.isStopped):
    			delay = random.uniform(0.7, 1.3)
    			print("tick " + str(delay))
    			self.ctrl.SendKey("Hello, world!")
    			time.sleep(delay)
    main.py
    Code:
    import memory, healer, time, control
    
    # Heal Rules:
    # Format: minhp, maxhp, minmp, maxmp, spell
    HealRules = [
    	{ 2000, 3000, 40, 0, "Exura Ico" }#,
    	#{ 1000, 2000, 100, 0, "Exura Gran Ico" }
    ]
    
    mem = memory.Memory()
    ctrl = control.Control(mem.HWND, mem.PROCESS.handle)
    heal = healer.Healer(HealRules, ctrl, mem)
    
    print("Name from BattleList: " + mem.ReadString(5943964))
    print("CID from BattleList: " + str(mem.ReadInt(5943960)))
    
    heal.run()
    memory.py
    Code:
    import ctypes, win32ui, win32process ,win32api
    
    class Memory:
    	def __init__(self):
    		# Read and write process memory methods from kernel32
    		self.rPM = ctypes.windll.kernel32.ReadProcessMemory
    		self.wPM = ctypes.windll.kernel32.WriteProcessMemory
    		# PROCESS_ALL_ACCESS is a flag typically set in kernel32, for simplicity we shall define it here
    		PROCESS_ALL_ACCESS = 0x1F0FFF
    
    
    		# Acquire a HWND for Tibia
    		self.HWND = win32ui.FindWindow("TibiaClient",None).GetSafeHwnd()
    		print("HWND        : " + str(self.HWND))
    
    		# Acquire the ProcessID using our HWND
    		self.PID = win32process.GetWindowThreadProcessId(self.HWND)[1]
    		print("PID         : " + str(self.PID))
    
    		# Acquire a Process object to work with
    		self.PROCESS = win32api.OpenProcess(PROCESS_ALL_ACCESS,0,self.PID)
    		print("HANDLE      : " + str(self.PROCESS.handle))
    
    		# Enumerate Process MOdules to find the base address of Tibia
    		self.BASEADDRESSLIST = win32process.EnumProcessModules(self.PROCESS.handle)
    
    		# Take the first (C# "Default") base address from the list
    		self.BASEADDRESS = self.BASEADDRESSLIST[0]
    		print("BASEADDRESS : " + str(self.BASEADDRESS))
    
    
    
    #ALL GLOBALS DEFINED
    
    	def ReadInt(self, Address):
    		data = 4294967295
    		self.rPM(self.PROCESS.handle,Address+self.BASEADDRESS,data,32,0)
    		return data
    
    
    	def ReadString(self, Address):
    		data = b"wah"
    		buff = ctypes.create_string_buffer(data, 32)
    		self.rPM(self.PROCESS.handle,Address+self.BASEADDRESS,buff,32,0)
    		val = ctypes.string_at(buff).decode("utf-8")
    		return val

  6. #6
    Junior Member
    Join Date
    Nov 2013
    Posts
    5
    Quote Originally Posted by Blequi View Post
    Code:
        self.PROCESS = win32api.OpenProcess(PROCESS_ALL_ACCESS, 0, self.PID)
    pywintypes.error: (5, 'OpenProcess', 'Access is denied.')
    I am not a python programmer, but judging by these lines seems like you are not running the program as Administrator... so test "Run as Administrator".
    I am running the program as Administrator, and it works with the regular Tibia Client.

  7. #7
    Senior Member
    Join Date
    Apr 2008
    Posts
    689
    From what I've seen so far:
    1. try minimal privileges instead of PROCESS_ALL_ACCESS
    2. try sedebugprivilege & friends http://blogs.msdn.com/b/oldnewthing/...4/8080140.aspx

  8. #8
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Quote Originally Posted by Arnie View Post
    I am running the program as Administrator, and it works with the regular Tibia Client.
    Try change that line of code to this:

    self.PROCESS = win32api.OpenProcess(MAXIMUM_ALLOWED, 0, self.PID)

    Then check if rPM still works. This will give you the maximum allowed privileges within the target process, so if you can't rPM after it then there is something a bit iffy going on.

  9. #9
    Junior Member
    Join Date
    Nov 2013
    Posts
    5
    That didn't work, I'm still getting the same error. The custom client is the Tibianic client if that helps.

  10. #10
    Junior Member
    Join Date
    Jun 2019
    Posts
    1
    Quote Originally Posted by XtrmJash View Post
    Currently it's almost done. I just haven't gotten round to doing the final steps. Here's what I have so far:

    Control.py:
    Code:
    import ctypes
    import win32ui
    import win32process
    import win32api
    import win32con
    
    class Control:
    	def __init__(self, hwnd, handle):
    		self.hwnd = hwnd
    		self.handle = handle
    
    	def SendKey(self, key):
    		for k in key:
    			print(str(k))
    			if k == "\n":
    				win32api.SendMessage(self.hwnd, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
    				win32api.SendMessage(self.hwnd, win32con.WM_KEYUP, win32con.VK_RETURN, 0)
    			else:
    				win32api.SendMessage(self.hwnd, win32con.WM_CHAR, ord(k), 0)
    Healer.py
    Code:
    from threading import Thread
    import time, random
    import control
    
    class Healer:
    	def __init__(self, rules, ctrl, mem):
    		Thread.__init__(self)
    		self.rules = rules
    		self.ctrl = ctrl
    		self.isStopped = False
    		self.mem = mem
    
    	def run(self):
    		self.isStopped = False
    		for i in self.rules:
    			print("HealRule")
    
    		while (~self.isStopped):
    			delay = random.uniform(0.7, 1.3)
    			print("tick " + str(delay))
    			self.ctrl.SendKey("Hello, world!")
    			time.sleep(delay)
    main.py
    Code:
    import memory, healer, time, control
    
    # Heal Rules:
    # Format: minhp, maxhp, minmp, maxmp, spell
    HealRules = [
    	{ 2000, 3000, 40, 0, "Exura Ico" }#,
    	#{ 1000, 2000, 100, 0, "Exura Gran Ico" }
    ]
    
    mem = memory.Memory()
    ctrl = control.Control(mem.HWND, mem.PROCESS.handle)
    heal = healer.Healer(HealRules, ctrl, mem)
    
    print("Name from BattleList: " + mem.ReadString(5943964))
    print("CID from BattleList: " + str(mem.ReadInt(5943960)))
    
    heal.run()
    memory.py
    Code:
    import ctypes, win32ui, win32process ,win32api
    
    class Memory:
    	def __init__(self):
    		# Read and write process memory methods from kernel32
    		self.rPM = ctypes.windll.kernel32.ReadProcessMemory
    		self.wPM = ctypes.windll.kernel32.WriteProcessMemory
    		# PROCESS_ALL_ACCESS is a flag typically set in kernel32, for simplicity we shall define it here
    		PROCESS_ALL_ACCESS = 0x1F0FFF
    
    
    		# Acquire a HWND for Tibia
    		self.HWND = win32ui.FindWindow("TibiaClient",None).GetSafeHwnd()
    		print("HWND        : " + str(self.HWND))
    
    		# Acquire the ProcessID using our HWND
    		self.PID = win32process.GetWindowThreadProcessId(self.HWND)[1]
    		print("PID         : " + str(self.PID))
    
    		# Acquire a Process object to work with
    		self.PROCESS = win32api.OpenProcess(PROCESS_ALL_ACCESS,0,self.PID)
    		print("HANDLE      : " + str(self.PROCESS.handle))
    
    		# Enumerate Process MOdules to find the base address of Tibia
    		self.BASEADDRESSLIST = win32process.EnumProcessModules(self.PROCESS.handle)
    
    		# Take the first (C# "Default") base address from the list
    		self.BASEADDRESS = self.BASEADDRESSLIST[0]
    		print("BASEADDRESS : " + str(self.BASEADDRESS))
    
    
    
    #ALL GLOBALS DEFINED
    
    	def ReadInt(self, Address):
    		data = 4294967295
    		self.rPM(self.PROCESS.handle,Address+self.BASEADDRESS,data,32,0)
    		return data
    
    
    	def ReadString(self, Address):
    		data = b"wah"
    		buff = ctypes.create_string_buffer(data, 32)
    		self.rPM(self.PROCESS.handle,Address+self.BASEADDRESS,buff,32,0)
    		val = ctypes.string_at(buff).decode("utf-8")
    		return val
    Hey, you still have this project? I really wanted it for educational purposes ... TY

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •