好友
阅读权限10
听众
最后登录1970-1-1
|
本帖最后由 xueshanshi2 于 2025-12-18 08:22 编辑
在红警2尤里的复仇如果你按照这样加载电脑
在没有任何帮助的情况下,大概率赢不了
但只要我们稍稍懂一点python:lol
那情况就不一样了
要知道这个游戏几乎没有反作弊,网上的修改器一大堆,但我想要的功能却没有,于是决定亲自下手,做一款在鼠标位置释放无限核弹的修改器,开局即可使用,1分钟内消灭7家对手!
本代码借鉴了KaQqi大佬在https://www.52pojie.cn/thread-935581-1-1.html发帖中的代码:
核弹代码
pushad
mov ecx,0x14
call 006ceeb0
mov ebx,eax
mov eax,[ebx+98]
mov edx,[00a83d4c]
mov ecx,[edx+258]
push 0
push 0
mov ecx,[ecx+eax*4]
push 1
call 006CB560
mov eax,[ebx+98]
mov ecx,0087f7e8
push eax
push 1f
call 006a6300
popad
ret
代码中的地址和游戏版本有关,并且都是VA地址,需要转换为Python中能用的地址,需要先确定自己的游戏版本,找到相关位置:
可以看到我的游戏地址和大佬帖子中的一样,这样就省了一个步骤,不用改代码call的地址了。
现在就剩把以上代码转换为Python能用的代码了,如果你具备相关知识,万能的deepseek可以帮助你。这时候,你需要告诉deepseek:
上面的代码是用于游戏修改的远程注入代码,代码中的地址都是VA地址,请转换为基址加偏移地址的形式,并最终转换为机器码,要注意call调用函数时的长度问题。
经过数次的测试,你会得到如下函数:
远程注入关键函数:
def _write_asm_code(self):
"""将汇编代码写入分配的内存"""
try:
# 计算实际函数地址
func_2ceeb0 = self.base_address + 0x2CEEB0
func_2cb560 = self.base_address + 0x2CB560
func_2a6300 = self.base_address + 0x2A6300
offset_683d4c = self.base_address + 0x683D4C
offset_47f7e8 = self.base_address + 0x47F7E8
# 构建机器码(x88汇编)
asm_bytes = bytearray()
# pushad (保存所有寄存器)
asm_bytes.extend(b'\x60')
# mov ecx, 0x14
asm_bytes.extend(b'\xB9\x14\x00\x00\x00')
# call gamemd.exe+2CEEB0
asm_bytes.extend(b'\xE8')
rel_call_1 = func_2ceeb0 - (self.alloc_addr + len(asm_bytes) + 4)
asm_bytes.extend(struct.pack('<I', rel_call_1 & 0xFFFFFFFF))
# mov ebx, eax
asm_bytes.extend(b'\x89\xC3')
# mov eax, [ebx+98]
asm_bytes.extend(b'\x8B\x83\x98\x00\x00\x00')
# mov edx, [gamemd.exe+683D4C]
asm_bytes.extend(b'\x8B\x15')
asm_bytes.extend(struct.pack('<I', offset_683d4c))
# mov ecx, [edx+258]
asm_bytes.extend(b'\x8B\x8A\x58\x02\x00\x00')
# push 0
asm_bytes.extend(b'\x6A\x00')
# push 0
asm_bytes.extend(b'\x6A\x00')
# mov ecx, [ecx+eax*4]
asm_bytes.extend(b'\x8B\x0C\x81')
# push 1
asm_bytes.extend(b'\x6A\x01')
# call gamemd.exe+2CB560
asm_bytes.extend(b'\xE8')
rel_call_2 = func_2cb560 - (self.alloc_addr + len(asm_bytes) + 4)
asm_bytes.extend(struct.pack('<I', rel_call_2 & 0xFFFFFFFF))
# mov eax, [ebx+0x98]
asm_bytes.extend(b'\x8B\x83\x98\x00\x00\x00')
# mov ecx, gamemd.exe+47F7E8
asm_bytes.extend(b'\xB9')
asm_bytes.extend(struct.pack('<I', offset_47f7e8))
# push eax
asm_bytes.extend(b'\x50')
# push 0x1F
asm_bytes.extend(b'\x6A\x1F')
# call gamemd.exe+2A6300
asm_bytes.extend(b'\xE8')
rel_call_3 = func_2a6300 - (self.alloc_addr + len(asm_bytes) + 4)
asm_bytes.extend(struct.pack('<I', rel_call_3 & 0xFFFFFFFF))
# popad (恢复寄存器)
asm_bytes.extend(b'\x61')
# ret
asm_bytes.extend(b'\xC3')
# 写入内存
if self.pm and self.alloc_addr:
pymem.memory.write_bytes(self.pm.process_handle, self.alloc_addr, bytes(asm_bytes), len(asm_bytes))
return True
return False
except Exception as e:
print(f"写入汇编代码失败: {e}")
return False
以上是最关键的代码,只要在目标进程分配一个1k的内存,注入后运行即可实现一次加载好的核弹,不管你创建游戏时是否开了超级武器,这段代码都会让你拥有一颗核弹。
但我们总不能用一次注入一次吧,那样太麻烦了,这时候我们有两种思路,一种是修改上边的汇编代码,让代码运行后再次回到开头重新执行,这样有有了无限核弹,但这样注入的进程一直运行,很容易让游戏崩溃,于是有了下边的方法:
无限核弹主循环
def nuke_loop(self):
"""无限核弹主循环"""
first_run = True
while self.running and not self.stop_event.is_set():
# 检查无限核弹功能是否启用
try:
# 检查是否可以读取游戏值
if self.nuke_flag:
if self.can_read_game_values:
if not self.alloc_addr:
self.alloc_addr = self._allocate_memory(1024)
if not self.alloc_addr:
print("核弹内存分配失败")
time.sleep(5) # 增加延迟从2秒到5秒
continue
# 写入汇编代码
success = self._write_asm_code()
if not success:
print("写入汇编代码失败")
if self.stop_event.wait(1):
break
continue
if first_run:
first_run = False
print("开始无限核弹模式...")
# 创建远程线程执行代码
self._create_remote_thread()
time.sleep(0.1)
else:
self._cleanup_nuke()
time.sleep(1)
else:
if not first_run:
print("无限核弹模式已关闭")
if self.alloc_addr:
self._cleanup_nuke()
first_run = True
time.sleep(0.2) # 增加延迟
except Exception as e:
print(f"核弹执行出错: {e}")
# 发生错误时重置状态
first_run = True
self._cleanup_nuke()
if self.stop_event.wait(2): # 增加延迟
break
这时候你就拥有了永远用不完的核弹了,但核弹还不能主动释放,还需要鼠标点击才行,但这还不是小问题?我们的Python有个pyautogui模块,专门干这个事情,于是有了下面的代码:
技能释放到当前鼠标位置
def cast_skill_to_cursor(self):
"""
将技能释放到当前鼠标位置
支持多种图像格式,但推荐使用PNG
"""
# 获取当前鼠标位置
keyboard.press('w')
keyboard.release('w')
time.sleep(0.05)
target_x, target_y = pyautogui.position()
skill_location1 = None
skill_location2 = None
try:
# 尝试定位技能图标1
skill_location1 = pyautogui.locateCenterOnScreen("hdpic.png", confidence=0.8)
except :
pass
try:
skill_location2 = pyautogui.locateCenterOnScreen("hdpic2.png", confidence=0.8)
except :
pass
skill_location = skill_location1 if skill_location1 else skill_location2
if skill_location:
if skill_location == skill_location1:
pyautogui.click(skill_location.x*1.2, skill_location.y*1.2)
else:
pyautogui.click(skill_location)
pyautogui.click(target_x, target_y)
return True
else:
return False
代码中用到两张图片,分别是不同游戏版本的核弹加载完整的图片,没有这个图片无法实现自动释放,本来以为核弹加载完成后都一样,但是实际上差距很大,所以游戏会每次都加载,但这个图片很小,不影响程序运行速度,所以就懒得修改函数了,所以这两张图片会多次加载,大家有空闲了可以修改在程序运行时加载,减少内存浪费。以下是两张图片,请务必下载放到程序目录:
另外你会发现pyautogui.click(skill_location.x*1.2, skill_location.y*1.2)中有个系数1.2,这是跟电脑分辨率有关,电脑分辨率设置以后大多数会放大125%或者放大150%,然而红警2之尤里的复仇分辨率设置会跟不上现在的电脑硬件,在全屏时会强制放大,所以这个1.2可能仅适配我的电脑,如果您的电脑不能正确自动释放,请修改此处系数
至此核心代码已经展示完毕,把cast_skill_to_cursor()函数加入到核弹主循环,就可以了。
后来还增加了无限金钱功能、雷达全开功能、鼠标连击功能、快速建造功能,还增加了GUI界面,最终的代码就到了829行,其中GUI界面就占了342行,但实际代码没多少,很适合新手学习,希望大家多提宝贵意见!
软件截图如下:
由于某个模块目前还不适配Python3.14,所以本代码最高支持Python3.13.8,希望某模块尽快适配吧
原代码打包:
GameMonitor.zip
(7.55 KB, 下载次数: 40)
成品链接:
https://xueshanshi.lanzouq.com/iLpX23dwjg6f
使用方法:
1.解压exe文件和两张图片到任意目录
2.以管理员身份运行软件
3.打开游戏选择电脑对手(本软件不适用于网络对战,仅限单机)
4.在对战中按Ctrl+D开始核弹轰炸,再次按Ctrl+D取消轰炸
5.游戏初期建议不要使用建造加速,因为电脑也加速,手速很难超过电脑
6.轰炸时画面会有抖动,几乎看不清鼠标位置,可以轰炸完一家后按Ctrl+D取消,把鼠标移动到另一家再次按Ctrl+D继续轰炸
|
免费评分
-
查看全部评分
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|
|