新增植物大战僵尸杂交版的修改器
This commit is contained in:
parent
b1a154cd45
commit
7dab4539e3
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
46
PVZZZB_C1.py
Normal file
46
PVZZZB_C1.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# 植物大战僵尸v2.2 杂交版辅助
|
||||||
|
import win32gui #pip install pywin32
|
||||||
|
import psutil
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import win32gui
|
||||||
|
import win32process
|
||||||
|
import psutil
|
||||||
|
|
||||||
|
def get_visible_windows():
|
||||||
|
"""获取所有可见窗口的标题和PID"""
|
||||||
|
results = []
|
||||||
|
|
||||||
|
def foreach_window(hwnd, _):
|
||||||
|
if win32gui.IsWindowVisible(hwnd):
|
||||||
|
title = win32gui.GetWindowText(hwnd)
|
||||||
|
if title:
|
||||||
|
_, pid = win32process.GetWindowThreadProcessId(hwnd)
|
||||||
|
results.append((title, pid))
|
||||||
|
return True
|
||||||
|
|
||||||
|
win32gui.EnumWindows(foreach_window, None)
|
||||||
|
return results
|
||||||
|
|
||||||
|
def get_window_handle(title):
|
||||||
|
"""根据窗口标题获取窗口句柄"""
|
||||||
|
hwnd = win32gui.FindWindow(None, title)
|
||||||
|
if hwnd == 0:
|
||||||
|
print("窗口未找到")
|
||||||
|
else:
|
||||||
|
print(f"窗口句柄: {hwnd}")
|
||||||
|
return hwnd
|
||||||
|
|
||||||
|
# 调用函数获取所有可见窗口的应用信息
|
||||||
|
visible_windows = get_visible_windows()
|
||||||
|
for title, pid in visible_windows:
|
||||||
|
print(f"窗口标题: {title}, 进程ID: {pid}")
|
||||||
|
|
||||||
|
# 假设我们要找的窗口标题是"My Application"
|
||||||
|
window_title = "植物大战僵尸v2.2 "
|
||||||
|
get_window_handle(window_title)
|
||||||
|
|
||||||
|
|
||||||
|
|
88
PVZZZB_C2.py
Normal file
88
PVZZZB_C2.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import win32gui
|
||||||
|
import win32process
|
||||||
|
import win32api
|
||||||
|
import ctypes
|
||||||
|
import time
|
||||||
|
# 参考资料 https://www.52pojie.cn/thread-1132032-1-1.html
|
||||||
|
|
||||||
|
def change_sun(Phand, sun_num):
|
||||||
|
sun_date = ctypes.c_long()
|
||||||
|
# kernel32.ReadProcessMemory(int(Phand), 0x03F8A9C0, ctypes.byref(sun_date), 4, None)
|
||||||
|
kernel32.ReadProcessMemory(int(Phand), 0x6A9EC0, ctypes.byref(sun_date), 4, None)
|
||||||
|
"""
|
||||||
|
0x03F8A9C0 是基础地址,假设这里存储了一个指向阳光数值的指针。
|
||||||
|
ctypes.byref(sun_date) 是一个指向sun_date变量的引用,用于接收从内存中读取的数据。
|
||||||
|
4 表示读取数据的大小,这里是4字节,即一个整数。
|
||||||
|
None 是一个可选参数,用来接收实际读取的字节数,但在这里我们不关心这个值。
|
||||||
|
"""
|
||||||
|
kernel32.ReadProcessMemory(int(Phand), sun_date.value + 0x768, ctypes.byref(sun_date), 4, None)
|
||||||
|
# 写入新的数值
|
||||||
|
new_sun_date = ctypes.c_long(sun_num)
|
||||||
|
print(sun_date)
|
||||||
|
print(new_sun_date)
|
||||||
|
return kernel32.WriteProcessMemory(int(Phand), sun_date.value + 0x5560, ctypes.byref(new_sun_date), 4, None)
|
||||||
|
|
||||||
|
|
||||||
|
def change_cooling(Phand, cooling):
|
||||||
|
"""
|
||||||
|
修改冷却
|
||||||
|
:param Phand:
|
||||||
|
:param cooling: 0 冷却 1 无冷却
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
cooling_data = ctypes.c_long()
|
||||||
|
kernel32.ReadProcessMemory(int(Phand), 0x6A9EC0, ctypes.byref(cooling_data), 4, None)
|
||||||
|
kernel32.ReadProcessMemory(int(Phand), cooling_data.value + 0x768, ctypes.byref(cooling_data), 4, None)
|
||||||
|
kernel32.ReadProcessMemory(int(Phand), cooling_data.value + 0x144, ctypes.byref(cooling_data), 4, None)
|
||||||
|
# kernel32.ReadProcessMemory(int(Phand),cooling_data.value,ctypes.byref(cooling_data),4,None)
|
||||||
|
new_cooling_date = ctypes.c_long(cooling)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x70, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0xC0, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x110, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x160, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x1B0, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x200, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x250, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x2A0, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x2F0, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x340, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
# 可以看出,从第二个地址开始,每个地址与其前一个地址之间的差值是固定的,为0x50(80)。这种模式表明,每个卡槽的冷却时间数据在内存中是以固定间隔排列的。
|
||||||
|
#
|
||||||
|
# 推测剩余卡槽的冷却时间地址
|
||||||
|
# 既然已知前十个卡槽的冷却时间地址遵循0x50的增量规律,那么我们可以轻易地推测出后五个卡槽的冷却时间地址:
|
||||||
|
#
|
||||||
|
# 第11个卡槽:0x340 + 0x50 = 0x390 (944)
|
||||||
|
# 第12个卡槽:0x390 + 0x50 = 0x3E0 (992)
|
||||||
|
# 第13个卡槽:0x3E0 + 0x50 = 0x430 (1072)
|
||||||
|
# 第14个卡槽:0x430 + 0x50 = 0x480 (1168)
|
||||||
|
# 第15个卡槽:0x480 + 0x50 = 0x4D0 (1232)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x390, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x3E0, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x430, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x480, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
|
||||||
|
|
||||||
|
def change(Phand, param):
|
||||||
|
while(1000):
|
||||||
|
change_sun(Phand,param)
|
||||||
|
change_cooling(Phand,1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# 调用动态链接库
|
||||||
|
kernel32 = ctypes.windll.LoadLibrary('kernel32.dll')
|
||||||
|
# 调用最高权限执行
|
||||||
|
PROCESS_ALL_ACCESS = (0x000F0000 | 0x00100000 | 0xFFF)
|
||||||
|
# 获取窗口句柄
|
||||||
|
windos_handle = win32gui.FindWindow(None, "植物大战僵尸v2.2 ")
|
||||||
|
# 获取进程PID
|
||||||
|
read, pid = win32process.GetWindowThreadProcessId(windos_handle)
|
||||||
|
# 获取进程句柄
|
||||||
|
Phand = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
|
||||||
|
# 调用修改函数
|
||||||
|
print("PID:",pid)
|
||||||
|
print("进程句柄:",Phand)
|
||||||
|
print(change(Phand,9999))
|
||||||
|
print("end")
|
71
PVZZZB_C2_ai.py
Normal file
71
PVZZZB_C2_ai.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import win32api
|
||||||
|
import win32con
|
||||||
|
import win32process
|
||||||
|
import win32gui
|
||||||
|
from ctypes import c_int, byref, c_void_p, windll
|
||||||
|
from ctypes.wintypes import HANDLE
|
||||||
|
import time
|
||||||
|
|
||||||
|
def get_pid_by_window_title(title):
|
||||||
|
def callback(hwnd, hwnds):
|
||||||
|
if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowText(hwnd) == title:
|
||||||
|
hwnds.append(hwnd)
|
||||||
|
return True
|
||||||
|
|
||||||
|
hwnds = []
|
||||||
|
win32gui.EnumWindows(callback, hwnds)
|
||||||
|
|
||||||
|
pids = []
|
||||||
|
for hwnd in hwnds:
|
||||||
|
_, pid = win32process.GetWindowThreadProcessId(hwnd)
|
||||||
|
pids.append(pid)
|
||||||
|
|
||||||
|
return pids
|
||||||
|
|
||||||
|
def read_process_memory(pid, address):
|
||||||
|
hProcess = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, pid)
|
||||||
|
buffer = (c_int * 1)()
|
||||||
|
bytes_read = c_int(0)
|
||||||
|
success = windll.kernel32.ReadProcessMemory(HANDLE(hProcess), c_void_p(address), byref(buffer), 4, byref(bytes_read))
|
||||||
|
win32api.CloseHandle(hProcess)
|
||||||
|
if not success:
|
||||||
|
raise Exception("Failed to read process memory")
|
||||||
|
return buffer[0]
|
||||||
|
|
||||||
|
def write_process_memory(pid, address, value):
|
||||||
|
hProcess = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, pid)
|
||||||
|
value_c = c_int(value)
|
||||||
|
if not windll.kernel32.WriteProcessMemory(HANDLE(hProcess), c_void_p(address), byref(value_c), 4, None):
|
||||||
|
raise Exception("Failed to write process memory")
|
||||||
|
win32api.CloseHandle(hProcess)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
window_title = "植物大战僵尸v2.2 "
|
||||||
|
pids = get_pid_by_window_title(window_title)
|
||||||
|
|
||||||
|
if len(pids) == 0:
|
||||||
|
print("No matching windows found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
pid = pids[0] # 取第一个匹配的PID,如果有多个窗口,你可能需要调整逻辑
|
||||||
|
base_address = 0x2A9EC0
|
||||||
|
offset1 = 768
|
||||||
|
offset2 = 5560
|
||||||
|
final_address = base_address + offset1 + offset2
|
||||||
|
|
||||||
|
try:
|
||||||
|
original_value = read_process_memory(pid, final_address)
|
||||||
|
print(f"Original value: {original_value}")
|
||||||
|
|
||||||
|
new_value = 9420
|
||||||
|
write_process_memory(pid, final_address, new_value)
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
modified_value = read_process_memory(pid, final_address)
|
||||||
|
print(f"Modified value: {modified_value}")
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
154
PVZZZB_C3_gui.py
Normal file
154
PVZZZB_C3_gui.py
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import threading
|
||||||
|
import time
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import messagebox
|
||||||
|
import win32gui
|
||||||
|
import win32process
|
||||||
|
import win32api
|
||||||
|
import ctypes
|
||||||
|
|
||||||
|
kernel32 = ctypes.windll.kernel32
|
||||||
|
|
||||||
|
PROCESS_ALL_ACCESS = (0x000F0000 | 0x00100000 | 0xFFF)
|
||||||
|
|
||||||
|
# 定义修改阳光和冷却的函数
|
||||||
|
|
||||||
|
def change_sun(Phand, sun_num):
|
||||||
|
sun_date = ctypes.c_long()
|
||||||
|
# kernel32.ReadProcessMemory(int(Phand), 0x03F8A9C0, ctypes.byref(sun_date), 4, None)
|
||||||
|
kernel32.ReadProcessMemory(int(Phand), 0x6A9EC0, ctypes.byref(sun_date), 4, None)
|
||||||
|
"""
|
||||||
|
0x03F8A9C0 是基础地址,假设这里存储了一个指向阳光数值的指针。
|
||||||
|
ctypes.byref(sun_date) 是一个指向sun_date变量的引用,用于接收从内存中读取的数据。
|
||||||
|
4 表示读取数据的大小,这里是4字节,即一个整数。
|
||||||
|
None 是一个可选参数,用来接收实际读取的字节数,但在这里我们不关心这个值。
|
||||||
|
"""
|
||||||
|
kernel32.ReadProcessMemory(int(Phand), sun_date.value + 0x768, ctypes.byref(sun_date), 4, None)
|
||||||
|
# 写入新的数值
|
||||||
|
new_sun_date = ctypes.c_long(sun_num)
|
||||||
|
print(sun_date)
|
||||||
|
print(new_sun_date)
|
||||||
|
return kernel32.WriteProcessMemory(int(Phand), sun_date.value + 0x5560, ctypes.byref(new_sun_date), 4, None)
|
||||||
|
|
||||||
|
|
||||||
|
def change_cooling(Phand, cooling):
|
||||||
|
"""
|
||||||
|
修改冷却
|
||||||
|
:param Phand:
|
||||||
|
:param cooling: 0 冷却 1 无冷却
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
cooling_data = ctypes.c_long()
|
||||||
|
kernel32.ReadProcessMemory(int(Phand), 0x6A9EC0, ctypes.byref(cooling_data), 4, None)
|
||||||
|
kernel32.ReadProcessMemory(int(Phand), cooling_data.value + 0x768, ctypes.byref(cooling_data), 4, None)
|
||||||
|
kernel32.ReadProcessMemory(int(Phand), cooling_data.value + 0x144, ctypes.byref(cooling_data), 4, None)
|
||||||
|
# kernel32.ReadProcessMemory(int(Phand),cooling_data.value,ctypes.byref(cooling_data),4,None)
|
||||||
|
new_cooling_date = ctypes.c_long(cooling)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x70, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0xC0, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x110, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x160, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x1B0, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x200, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x250, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x2A0, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x2F0, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x340, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
# 可以看出,从第二个地址开始,每个地址与其前一个地址之间的差值是固定的,为0x50(80)。这种模式表明,每个卡槽的冷却时间数据在内存中是以固定间隔排列的。
|
||||||
|
#
|
||||||
|
# 推测剩余卡槽的冷却时间地址
|
||||||
|
# 既然已知前十个卡槽的冷却时间地址遵循0x50的增量规律,那么我们可以轻易地推测出后五个卡槽的冷却时间地址:
|
||||||
|
#
|
||||||
|
# 第11个卡槽:0x340 + 0x50 = 0x390 (944)
|
||||||
|
# 第12个卡槽:0x390 + 0x50 = 0x3E0 (992)
|
||||||
|
# 第13个卡槽:0x3E0 + 0x50 = 0x430 (1072)
|
||||||
|
# 第14个卡槽:0x430 + 0x50 = 0x480 (1168)
|
||||||
|
# 第15个卡槽:0x480 + 0x50 = 0x4D0 (1232)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x390, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x3E0, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x430, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
kernel32.WriteProcessMemory(int(Phand), cooling_data.value + 0x480, ctypes.byref(new_cooling_date), 4, None)
|
||||||
|
|
||||||
|
|
||||||
|
# 定义检测游戏是否运行的函数
|
||||||
|
|
||||||
|
def find_game_window():
|
||||||
|
global running # 声明running为全局变量
|
||||||
|
hwnd = win32gui.FindWindow(None, "植物大战僵尸v2.2 ")
|
||||||
|
if hwnd == 0:
|
||||||
|
messagebox.showinfo("提示", "植物大战僵尸没有运行,请先启动游戏!")
|
||||||
|
# 将启动按钮设置为禁用状态
|
||||||
|
# start_button.config(state=tk.DISABLED)
|
||||||
|
# 如果正在进行修改,则停止
|
||||||
|
if running:
|
||||||
|
running = False
|
||||||
|
start_button.config(text="启动")
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
_, pid = win32process.GetWindowThreadProcessId(hwnd)
|
||||||
|
Phand = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
|
||||||
|
# 如果游戏开始运行,重新激活启动按钮
|
||||||
|
start_button.config(state=tk.NORMAL)
|
||||||
|
return Phand
|
||||||
|
|
||||||
|
# 定义修改阳光值的函数
|
||||||
|
def modify_sunlight():
|
||||||
|
sunlight_value = int(sunlight_entry.get())
|
||||||
|
Phand = find_game_window()
|
||||||
|
if Phand:
|
||||||
|
change_sun(Phand, sunlight_value)
|
||||||
|
|
||||||
|
# 定义修改冷却时间的函数
|
||||||
|
def modify_cooling():
|
||||||
|
cooling_enabled = cooling_var.get()
|
||||||
|
Phand = find_game_window()
|
||||||
|
if Phand:
|
||||||
|
change_cooling(Phand, cooling_enabled)
|
||||||
|
|
||||||
|
# 定义开始/停止修改的函数
|
||||||
|
def start_stop_modification():
|
||||||
|
global running
|
||||||
|
if running:
|
||||||
|
running = False
|
||||||
|
start_button.config(text="启动")
|
||||||
|
else:
|
||||||
|
running = True
|
||||||
|
start_button.config(text="启动中")
|
||||||
|
modification_thread = threading.Thread(target=modification_loop)
|
||||||
|
modification_thread.start()
|
||||||
|
|
||||||
|
def modification_loop():
|
||||||
|
while running:
|
||||||
|
modify_sunlight()
|
||||||
|
if cooling_var.get():
|
||||||
|
modify_cooling()
|
||||||
|
time.sleep(0.1) # 防止CPU占用过高
|
||||||
|
if __name__ == '__main__':
|
||||||
|
running = False
|
||||||
|
|
||||||
|
# 创建主窗口
|
||||||
|
root = tk.Tk()
|
||||||
|
root.title("植物大战僵尸修改器")
|
||||||
|
root.resizable(False, False) # 禁止窗口被调整大小
|
||||||
|
|
||||||
|
# 创建阳光值输入框
|
||||||
|
sunlight_label = tk.Label(root, text="阳光值:")
|
||||||
|
sunlight_label.grid(row=0, column=0, padx=(10, 5), pady=10)
|
||||||
|
sunlight_entry = tk.Entry(root)
|
||||||
|
sunlight_entry.insert(0, "9000")
|
||||||
|
sunlight_entry.grid(row=0, column=1, padx=(5, 10), pady=10)
|
||||||
|
|
||||||
|
# 创建冷却时间复选框
|
||||||
|
cooling_label = tk.Label(root, text="无冷却:")
|
||||||
|
cooling_label.grid(row=1, column=0, padx=(10, 5), pady=10)
|
||||||
|
cooling_var = tk.IntVar()
|
||||||
|
cooling_checkbutton = tk.Checkbutton(root, variable=cooling_var)
|
||||||
|
cooling_checkbutton.grid(row=1, column=1, padx=(5, 10), pady=10)
|
||||||
|
|
||||||
|
# 创建开始/停止按钮
|
||||||
|
start_button = tk.Button(root, text="启动", command=start_stop_modification)
|
||||||
|
start_button.grid(row=2, columnspan=2, padx=10, pady=10)
|
||||||
|
|
||||||
|
root.mainloop()
|
Loading…
Reference in New Issue
Block a user