根据上一篇 使用Python读写游戏1 中,使用Python win32库,对一款游戏进行了读内存 操作。

今天来写一下对内存进行写的操作

正文

要进行32位的读写,首先了解一下要用到的几个函数,通过百度找到的,大多都是C/C++的资料。

更详细的分析看上一篇。

写入函数 是 WriteProcessMemory

此函数能写入某一进程的内存区域(直接写入会出Access Violation错误,故需此函数)。

VC++声明

BOOL WriteProcessMemory(
HANDLE hProcess,//要修改的进程内存的句柄。句柄必须具有对进程的进程_vm_写和进程_vm_操作的访问权限
LPVOID lpBaseAddress,//指向写入数据的指定进程中的基地址的指针。在进行数据传输之前,系统将验证指定大小的基址和内存中的所有数据都可用于写访问,如果无法访问,则函数将失败。
LPVOID lpBuffer,//指向缓冲区的指针,其中包含要在指定进程的地址空间中写入的数据
DWORD nSize,//要写入指定进程的字节数。
LPDWORD lpNumberOfBytesWritten//指向接收传输到指定进程的字节数的变量的指针。此参数是可选的。如果lpNumberOfBytesWritten是零,则忽略该参数。
);

返回值

如果函数成功,则返回值为非零

如果函数失败,则返回值为0(零)。若要获取扩展错误信息,请调用GetLastError,如果请求的写操作跨入进程中无法访问的区域,则函数将失败。

对单机植物大战僵尸进行读取与写入操作

对植物大战僵尸分析,请看

植物大战僵尸(1)

植物大战僵尸(2)

植物大战僵尸(3)

首先是对阳光数量的读取

阳光的基址偏移是:

阳光:PlantsVsZombies.exe+2A9EC0+768+5560   

不能直接读PlantsVsZombies.exe+2A9EC0,所以把该值添加到CE中,查看地址栏中的十六进制值 006A9EC0

读写操作,与上一篇文章写法相似

# -*- coding: utf-8 -*-
import win32process#进程模块
from win32con import PROCESS_ALL_ACCESS #Opencress 权限
import win32api#调用系统模块
import ctypes#C语言类型
from win32gui import FindWindow#界面 def GetProcssID(address,bufflength):
pid = ctypes.c_ulong()
kernel32 = ctypes.windll.LoadLibrary("kernel32.dll")
hwnd = FindWindow(None,u"植物大战僵尸中文版")
ReadProcessMemory = kernel32.ReadProcessMemory
hpid, pid = win32process.GetWindowThreadProcessId(hwnd)
hProcess = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
addr = ctypes.c_ulong()
ReadProcessMemory(int(hProcess), address, ctypes.byref(addr), bufflength, None)
win32api.CloseHandle(hProcess)
return addr.value def main():
sun = GetProcssID(GetProcssID(GetProcssID(0x006A9EC0, 4)+0x768, 4)+0x5560, 4) print ("阳光的数量:%d" % sun) if __name__ == '__main__':
main()

sun 分解写法:

def main():
ret = GetProcssID(0x006A9EC0,4)
ret2 = GetProcssID(ret+0x768,4)
sun = GetProcssID(ret2+0x5560,4)
print ("阳光的数量:%d" % sun)
#sun = GetProcssID(GetProcssID(GetProcssID(0x006A9EC0, 4)+0x768, 4)+0x5560, 4)

根据之前的分析,植物大战僵尸可以开启自动收集功能。具体的地址是

自动收集:PlantsVsZombies.exe+3158B   初始值:5274496  修改后:22051712
十六进制:0043158B

声明一个函数

def WriteMemeryInt(_address,Data):
hGameHandle = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
WriteProcessInt = kernel32.WriteProcessMemory // 从kernel32动态链接库中调用这个函数
WriteProcessInt(int(hGameHandle),_address,ctypes.byref(ctypes.c_ulong(Data)),4,None)
return Data

代码分析:

WriteProcessInt(int(hGameHandle),_address,ctypes.byref(ctypes.c_ulong(Data)),4,None)
BOOL WriteProcessInt(
int(hGameHandle), //传入的句柄
_address, //要写入的地址
ctypes.byref(ctypes.c_ulong(Data)), //要写入的数据
4, //要写入指定进程的字节数。
None //指向接收传输到指定进程的字节数的变量的指针。此参数是可选的。如果lpNumberOfBytesWritten是零,则忽略该参数。
);

修改植物大战僵尸阳光数量

def _modifySunshine():
sun = GetProcssID(GetProcssID(GetProcssID(0x006A9EC0, 4)+0x768, 4)+0x5560, 4)
sun_write = WriteMemeryInt(GetProcssID( GetProcssID( 0x006A9EC0, 4) + 0x768,4) + 0x5560, 100)
print("修改前阳光的数量:" , sun)
if sun_write:
print("###################修改阳光数量成功##############################")
sun = GetProcssID(GetProcssID(GetProcssID(0x006A9EC0, 4)+0x768, 4)+0x5560, 4)
print("修改后阳光的数量:" , sun)
else:
print("###################修改阳光数量失败,错误信息:##################",GetLastError)

sun_write 分解写法

def _modifySunshine():
ret = GetProcssID(0x006A9EC0, 4)
ret2 = GetProcssID(ret + 0x768, 4)
sun_write = WriteMemeryInt(ret2+0x5560,100)
#ret2+0x5560 要写入的地址,不能在GetProcessID读取,不然写入的地址就不正确
#100 为修改的数量。
if sun_write:
print("###################修改阳光数量成功##############################")
else:
print("###################修改阳光数量失败,错误信息:##################",GetLastError)

运行代码

# -*- coding: utf-8 -*-
import win32process#进程模块
from win32con import PROCESS_ALL_ACCESS #Opencress 权限
import win32api#调用系统模块
import ctypes#C语言类型
from win32gui import FindWindow#界面 def GetProcssID(address,bufflength):
pid = ctypes.c_ulong()
kernel32 = ctypes.windll.LoadLibrary("kernel32.dll")
hwnd = FindWindow(None,u"植物大战僵尸中文版")
ReadProcessMemory = kernel32.ReadProcessMemory
hpid, pid = win32process.GetWindowThreadProcessId(hwnd)
hProcess = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
addr = ctypes.c_ulong()
ReadProcessMemory(int(hProcess), address, ctypes.byref(addr), bufflength, None)
win32api.CloseHandle(hProcess)
return addr.value def WriteMemeryInt(_address,Data):
hGameHandle = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
WriteProcessInt = kernel32.WriteProcessMemory // 从kernel32动态链接库中调用这个函数
WriteProcessInt(int(hGameHandle),_address,ctypes.byref(ctypes.c_ulong(Data)),4,None)
return Data def _modifySunshine():
sun = GetProcssID(GetProcssID(GetProcssID(0x006A9EC0, 4)+0x768, 4)+0x5560, 4)
sun_write = WriteMemeryInt(GetProcssID(GetProcssID( 0x006A9EC0, 4) + 0x768,4) + 0x5560, 100)
print("修改前阳光的数量:" , sun)
if sun_write:
print("###################修改阳光数量成功##############################")
sun = GetProcssID(GetProcssID(GetProcssID(0x006A9EC0, 4)+0x768, 4)+0x5560, 4)
print("修改后阳光的数量:" , sun)
else:
print("###################修改阳光数量失败,错误信息:##################",GetLastError) def main():
_modifySunshine() if __name__ == '__main__':
main()

基本代码就这些了,接下来按照我写C的格式,把代码格式改一下,因为看起来真的挺乱的

先把FindWindow 等基础操作用函数给封装

# -*- coding: utf-8 -*-
import win32process#进程模块
from win32con import PROCESS_ALL_ACCESS #Opencress 权限
import win32api#调用系统模块
import ctypes#C语言类型
from win32gui import FindWindow#界面 kernel32 = ctypes.windll.LoadLibrary("kernel32.dll")
GetLastError = kernel32.GetLastError def _GetProcessId(className,windowName):
hGameWindow = FindWindow(className, windowName)
pid = win32process.GetWindowThreadProcessId(hGameWindow)[1]
return pid def _GetPorcessHandle(pid):
hGameHandle = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
return hGameHandle def _ReadMemeryInt(hGameHandle,_address,bufflength):
addr = ctypes.c_ulong()
ReadProcessInt = kernel32.ReadProcessMemory
ReadProcessInt(int(hGameHandle), _address, ctypes.byref(addr), bufflength, None)
return addr.value def WriteMemeryInt(hGameHandle,_address,Data):
WriteProcessInt = kernel32.WriteProcessMemory
WriteProcessInt(int(hGameHandle),_address,ctypes.byref(ctypes.c_ulong(Data)),4,None)
return Data def main():
ProcessId = _GetProcessId(None,u"植物大战僵尸中文版") _hGameHandle = _GetPorcessHandle(ProcessId) win32api.CloseHandle(_hGameHandle) if __name__ == '__main__':
main()

在开始写功能,先是读取阳光数量和修改阳光数量:

def _modifySunshine(hGameHandle):
sun = _ReadMemeryInt(hGameHandle,_ReadMemeryInt(hGameHandle,_ReadMemeryInt(hGameHandle,0x006A9EC0, 4) + 0x768, 4) + 0x5560, 4)
sun_write = WriteMemeryInt(hGameHandle,_ReadMemeryInt(hGameHandle, _ReadMemeryInt(hGameHandle, 0x006A9EC0, 4) + 0x768,4) + 0x5560, 100)
print("修改前阳光的数量:" , sun)
if sun_write:
print("###################修改阳光数量成功##############################")
sun = _ReadMemeryInt(hGameHandle,_ReadMemeryInt(hGameHandle, _ReadMemeryInt(hGameHandle, 0x006A9EC0, 4) + 0x768,4) + 0x5560, 4)
print("修改后的阳光数量:", sun)
else:
print("###################修改阳光数量失败,错误信息:##################",GetLastError)

接着,根据分析,有自动收集阳光功能,基址是:

自动收集:PlantsVsZombies.exe+3158B   初始值:5274496  修改后:22051712
十六进制:0043158B
def _collectSunshine(hGameHandle):
collect = WriteMemeryInt(hGameHandle,0x0043158B,22051712)
if collect:
print("###################启动自动收集功能成功#########################")
else:
print("###################修改自动收集功能失败,错误信息:##################",GetLastError)

接下来是秒杀功能,因为不一定每次都守得住

普通僵尸秒杀基址:

秒杀普通僵尸: PlantsVsZombies.exe+13178A   初始值:1284214911 修改后:1284214928
十六进制:0053178A
def _Seckill(hGameHandle):
seckill = WriteMemeryInt(hGameHandle,0x0053178A,1284214928)
if seckill:
print("###################启动秒杀普通僵尸功能成功#########################")
else:
print("###################修改秒杀功能失败,错误信息:#########################",GetLastError)

除了普通僵尸,还有头盔僵尸:

头盔僵尸基址:

秒杀带护甲:   PlantsVsZombies.exe+13186D   初始值:1347618942  修改后:1347653776
十六进制:0053186D
def _SecKillHelmet(hGameHandle):
seckillHelemet = WriteMemeryInt(hGameHandle,0x53186D ,1347653776)
if seckillHelemet:
print("###################启动秒杀头盔僵尸功能成功#########################")
else:
print("###################修改头盔僵尸秒杀功能失败,错误信息:#################",GetLastError)

完整代码:

# -*- coding: utf-8 -*-
import win32process#进程模块
from win32con import PROCESS_ALL_ACCESS #Opencress 权限
import win32api#调用系统模块
import ctypes#C语言类型
from win32gui import FindWindow#界面 kernel32 = ctypes.windll.LoadLibrary("kernel32.dll")
GetLastError = kernel32.GetLastError def _GetProcessId(className,windowName):
hGameWindow = FindWindow(className, windowName)
pid = win32process.GetWindowThreadProcessId(hGameWindow)[1]
return pid def _GetPorcessHandle(pid):
hGameHandle = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
return hGameHandle def _ReadMemeryInt(hGameHandle,_address,bufflength):
addr = ctypes.c_ulong()
ReadProcessInt = kernel32.ReadProcessMemory
ReadProcessInt(int(hGameHandle), _address, ctypes.byref(addr), bufflength, None)
return addr.value def WriteMemeryInt(hGameHandle,_address,Data):
WriteProcessInt = kernel32.WriteProcessMemory
WriteProcessInt(int(hGameHandle),_address,ctypes.byref(ctypes.c_ulong(Data)),4,None)
return Data def _modifySunshine(hGameHandle):
sun = _ReadMemeryInt(hGameHandle,_ReadMemeryInt(hGameHandle,_ReadMemeryInt(hGameHandle,0x006A9EC0, 4) + 0x768, 4) + 0x5560, 4)
sun_write = WriteMemeryInt(hGameHandle,_ReadMemeryInt(hGameHandle, _ReadMemeryInt(hGameHandle, 0x006A9EC0, 4) + 0x768,4) + 0x5560, 100)
print("修改前阳光的数量:" , sun)
if sun_write:
print("###################修改阳光数量成功##############################")
sun = _ReadMemeryInt(hGameHandle,_ReadMemeryInt(hGameHandle, _ReadMemeryInt(hGameHandle, 0x006A9EC0, 4) + 0x768,4) + 0x5560, 4)
print("修改后的阳光数量:", sun)
else:
print("###################修改阳光数量失败,错误信息:##################",GetLastError) def _collectSunshine(hGameHandle):
collect = WriteMemeryInt(hGameHandle,0x0043158B,22051712)
if collect:
print("###################启动自动收集功能成功#########################")
else:
print("###################修改自动收集功能失败,错误信息:##################",GetLastError) def _Seckill(hGameHandle):
seckill = WriteMemeryInt(hGameHandle,0x0053178A,1284214928)
if seckill:
print("###################启动秒杀普通僵尸功能成功#########################")
else:
print("###################修改秒杀功能失败,错误信息:#########################",GetLastError) def _SecKillHelmet(hGameHandle):
seckillHelemet = WriteMemeryInt(hGameHandle,0x53186D ,1347653776)
if seckillHelemet:
print("###################启动秒杀头盔僵尸功能成功#########################")
else:
print("###################修改头盔僵尸秒杀功能失败,错误信息:#################",GetLastError) def main():
ProcessId = _GetProcessId(None,u"植物大战僵尸中文版") _hGameHandle = _GetPorcessHandle(ProcessId) _modifySunshine(_hGameHandle) _collectSunshine(_hGameHandle) _Seckill(_hGameHandle) _SecKillHelmet(_hGameHandle) win32api.CloseHandle(_hGameHandle) if __name__ == '__main__':
main()

运行代码:

结尾

借用一句看到很不错的话:

技术不分对错.人性才分善恶.

学习逆向的人必须身心放正.

身心放正之人手握屠龙刀,也是保家卫民.

使用Python对植物大战僵尸学习研究的更多相关文章

  1. 用 Python 实现植物大战僵尸代码!

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: marble_xu GitHub地址:https://github ...

  2. Python 开发植物大战僵尸游戏

    作者:楷楷 链接:https://segmentfault.com/a/1190000019418065 开发思路 完整项目地址: https://github.com/371854496/pygam ...

  3. Python 植物大战僵尸代码实现: 图片加载和显示切换

    游戏介绍以前很火的植物大战僵尸游戏, 本想在网上找个python版本游戏学习下,无奈没有发现比较完整的,那就自己来写一个把.图片资源是从github上下载的,因为图片资源有限,只能实现几种植物和僵尸. ...

  4. 植物大战僵尸的代码如何使用python来实现

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:程序IT圈 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...

  5. 植物大战僵尸游戏的开发(python)

    装备东西: 搭建好python环境, 四张图片,(背景图片,炮弹图片,僵尸图片,豌豆图片),就ok了  没有安装pygame的需要进行安装  pip install pygame 参考视频 # 植物大 ...

  6. python修改内存,(修改植物大战僵尸)

    import win32process # 进程模块 import win32con # 系统定义 import win32api # 调用系统模块 import ctypes # c语言类型 imp ...

  7. 详解 Facebook 田渊栋 NIPS2017 论文:深度强化学习研究的 ELF 平台

    这周,机器学习顶级会议 NIPS 2017 的论文评审结果已经通知到各位论文作者了,许多作者都马上发 Facebook/Twitter/Blog/ 朋友圈分享了论文被收录的喜讯.大家的熟人 Faceb ...

  8. python从写定时器学习Thread

    目录 python从写定时器学习Thread Timer 对象 粗陋的循环定时器 更 pythonic 循环定时器 FAQ python从写定时器学习Thread python 如何写一个定时器,循环 ...

  9. 开始写下自己的python的cocos2d, pyglet学习

    开始写下自己的python的cocos2d, pyglet学习 2014年01月18日 13:52:36 我要做程序达人 阅读数 9051更多 分类专栏: python的cocos2d和pyglet ...

随机推荐

  1. PHP生成二维码 endroid/qr-code 扩展包

    目录 1. 引入 endroid/qr-code 扩展包 2. 使用示例 3. 二维码中放入logo,无法识别二维码的问题 1. 引入 endroid/qr-code 扩展包 https://pack ...

  2. java 多线程-1

    一.程序.进程.线程简介 程序(program)是为完成特定任务.用某种语言编写的一组指令的集合.即指一段静态的代码,静态对象 进程(process)是程序的一次执行过程,或是正在运行的一个程序.是一 ...

  3. NetCore微服务实战体系:日志管理

    一. 起始 进入NetCore时代,日志的使用有了很大的变化,因为跨平台以及虚拟化技术的使用,日志不能够再像Framework的方式直接记录在文本,文本其实也可以,但是日志的管理以及查看都不太方便.L ...

  4. oracle之分层查询

    ORACLE分层查询start with&connect by 分层查询是select 语句的扩展,目的是迅速找出表中列-列的隶属关系. 19.1 树的遍历 ORACLE是一个关系数据库管理系 ...

  5. grpc服务如何添加sentry监控(添加中间件)

    目录 需求 解决 需求 sentry是一款非常好用的工具,可以方便追踪线上的异常,在gin框架里边可以非常方便的使用Use添加中件间,grpc服务在网上搜索了一堆没一个能用的,只能硬着头皮看源码 终于 ...

  6. 使用App Metrics实现性能监控

    App Metrics监控需要安装InfluxDB时序数据库和Grafana可视化分析工具 1.安装InfluxDB 下载地址:https://portal.influxdata.com/downlo ...

  7. apche编译安装

    常见的网页类型:htm,html,shtml,stm.php,asp,aspx,shtm,jsp等等Apache本事只处理静态页面,处理动态页面需要使用libphp5.so这个模块去工作,编译php也 ...

  8. rocketmq-console修改logo,修改ip,修改port及完整编译安装图文版

    一.下载源码到本地 这里使用IDEA,作为编译工具 https://gitee.com/mrliuNumberOne/rocketmq-externals.git 导入成功后如图: 二.Maven编译 ...

  9. bootsrap 样式笔记

    颜色 --blue: #007bff; --indigo: #6610f2; --purple: #6f42c1; --pink: #e83e8c; --red: #dc3545; --orange: ...

  10. Excel—使用if(countif())表达式来筛选两个表格中相同的数据

    关注微信公众号:CodingTechWork,一起学习进步. 引言   在线上运维的过程中,遇到一个头疼的事情,有一些合作公司的数据直接从平台上down下来是一个excel,然后发到研发手里去数据库中 ...