diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/PVZZZB_C1.py b/PVZZZB_C1.py new file mode 100644 index 0000000..d7a6390 --- /dev/null +++ b/PVZZZB_C1.py @@ -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) + + + diff --git a/PVZZZB_C2.py b/PVZZZB_C2.py new file mode 100644 index 0000000..a363f8f --- /dev/null +++ b/PVZZZB_C2.py @@ -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") \ No newline at end of file diff --git a/PVZZZB_C2_ai.py b/PVZZZB_C2_ai.py new file mode 100644 index 0000000..c2c5136 --- /dev/null +++ b/PVZZZB_C2_ai.py @@ -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() \ No newline at end of file diff --git a/PVZZZB_C3_gui.py b/PVZZZB_C3_gui.py new file mode 100644 index 0000000..162604f --- /dev/null +++ b/PVZZZB_C3_gui.py @@ -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() \ No newline at end of file