python脚本扫描win系统中运行程序内存值并修改

 用于修改运行中程序的内存值

#!encoding=utf8import os
import json
import psutil
import shutil
import threading
import ctypes
import win32api 
import win32process
from win32con import PROCESS_ALL_ACCESS class MemScan:'''注:一定要以系统管理员身份运行脚本(管理员身份运行cmd) windows系统 根据 进程号 pid 进行扫描内存中的数据, 最终定位到需要修改的内存地址并设置新值, 已知内存地址可以跳过扫描步骤定位内存地址的方法:一、精确查找1、在目标程序页面找到需要修改的值 对该值进行首次扫描2、在目标程序中改变这个值, 用新值进行二次扫描(扫描内存地址范围为上一次扫描结果)3、如果还是没办法确定准确的内存地址, 则重复第 2 步 逐步缩小范围4、根据内存地址设置新值'''def __init__(self, pid):self.scan_data = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'scan_data.json')self.tmp_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'tmp')self.hProcess = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)  # 获取进程句柄# 根据进程号来获取进程的内存大小process = psutil.Process(pid)mem_info = process.memory_info()print("内存总量:", mem_info.rss)  #  resident set size, 常驻内存集大小print("内存占用的峰值:", mem_info.vms)  # virtual memory size, 虚拟内存大小self.base_addr = win32process.EnumProcessModules(self.hProcess)[0]self.end_addr =  mem_info.vms + self.base_addrprint(f'pid:{pid} 的进程基址:{self.base_addr}  内存结束地址:{self.end_addr}')def read(self, mem_address, data_len=4, data_type=''):'''读取内存中的值'''if data_type == 'int':addr = ctypes.c_int32()elif data_type == 'float':addr = ctypes.c_float()elif data_type == 'double':addr = ctypes.c_double()data_len = 8else:addr = ctypes.c_ulong()# 句柄,地址,返回值,长度ctypes.windll.kernel32.ReadProcessMemory(int(self.hProcess), ctypes.c_void_p(int(mem_address)), ctypes.byref(addr), data_len, None)# print(addr)return addr.valuedef write(self, mem_address, num, data_len=4, data_type=''):'''根据内存地址写入值'''if data_type == 'int':addr = ctypes.c_int32()elif data_type == 'float':addr = ctypes.c_float()elif data_type == 'double':addr = ctypes.c_double()data_len = 8else:addr = ctypes.c_ulong()addr.value = num# 句柄,地址,写入值,长度return ctypes.windll.kernel32.WriteProcessMemory(int(self.hProcess), ctypes.c_void_p(int(mem_address)), ctypes.byref(addr), data_len, None)def _scan(self, target_value, scan_addrs, data_len=4, data_type=''):'''target_value: 目标值scan_addrs: 待扫描的地址列表data_len: 数据长度data_type: 数据类型'''current_thread = threading.current_thread()thread_id = current_thread.ident# print(f'当前线程ID:{thread_id}')current_save_path = os.path.join(self.tmp_dir, f'scan_data_{thread_id}.json')if data_type == 'int':addr = ctypes.c_int32()elif data_type == 'float':addr = ctypes.c_float()elif data_type == 'double':addr = ctypes.c_double()data_len = 8else:addr = ctypes.c_ulong()new_scan_data = {}for mem_addr in scan_addrs:value = self.read(mem_addr, data_len, data_type)if value == target_value:print(f'内存地址:{mem_addr}, 值为:{value}')mem_data = {'first_value': value, 'last_value': None ,'current_value': value}new_scan_data[mem_addr] = mem_dataif new_scan_data:# print(f'扫描结果保存路径:{current_save_path}')json.dump(new_scan_data, open(current_save_path, 'w', encoding='utf8'))def scan(self, target_value, data_len=4, data_type='', is_first_scan=False, thread_num=10):'''target_value: 目标值data_len: 数据长度data_type: 数据类型is_first_scan: 是否是第一次扫描thread_num: 线程数量'''if os.path.exists(self.tmp_dir):shutil.rmtree(self.tmp_dir)os.makedirs(self.tmp_dir)old_scan_data = {}mem_addrs = []if is_first_scan:mem_addrs = list(range(self.base_addr, self.end_addr, data_len))else:try:old_scan_data = json.load(open(self.scan_data, 'r', encoding='utf8'))mem_addrs = list(old_scan_data.keys())except:print(f'获取上一次扫描结果失败,请确认是否存在上一次扫描结果,或开启首次扫描')step = int(len(mem_addrs)/thread_num)step = step if step > 0 else 1sub_mem_addrs = [mem_addrs[i:i+step] for i in range(0, len(mem_addrs), step)]threads = []for sub_mem_addrs in sub_mem_addrs:t = threading.Thread(target=self._scan, args=(target_value, sub_mem_addrs, data_len, data_type))threads.append(t)t.start()for t in threads:t.join()new_scan_data = {}for filename in os.listdir(self.tmp_dir):filepath = os.path.join(self.tmp_dir, filename)new_scan_data.update(json.load(open(filepath, 'r', encoding='utf8')))for k, v in new_scan_data.items():old_v = old_scan_data.get(k, None)if old_v is not None:v['last_value'] = old_v['current_value']v['first_value'] = old_v['first_value']print(f'扫描结果保存路径:{self.scan_data}')json.dump(new_scan_data, open(self.scan_data, 'w', encoding='utf8'))def set_value_by_mem_addr(self, mem_addr, value, data_len=4, data_type=''):'''根据内存地址写入值mem_addr: 内存地址  10进制内存地址value: 写入的值data_len: 数据长度data_type: 数据类型'''if data_type == 'double':data_len = 8src = self.read(mem_addr, data_len, data_type)self.write(mem_addr, value, data_len, data_type)dst = self.read(mem_addr, data_len, data_type)print(f'目标地址:{mem_addr}, 原始值:{src}, 新值:{value}, 写入后值:{dst}')if __name__ == '__main__':# 替换为目标进程的PID , 可通过 任务管理器-详细信息 查看pid = 3960  # 扫描的数据长度     int, float 是4字节,double 是8字节data_len = 4# 扫描的数据类型    int, float 是4字节,double 是8字节data_type = 'int'# 扫描并发数量thread_num = 100ms = MemScan(pid)# 第一次扫描target_value = 1092ms.scan(target_value, data_len, data_type, thread_num=thread_num, is_first_scan=True)# 第N次扫描# target_value = 1090# ms.scan(target_value, data_len, data_type, thread_num=thread_num)# 内存地址设置值# target_value = 1090# mem_addr = 27366160# ms.set_value_by_mem_addr(mem_addr, target_value, data_len, data_type)

寻找PID

第一次扫描结果,值为1090的有很多

第二次扫描结果,通过程序修改1090的值为1085后,扫描结果只有1个

设置新值,根据内存地址设置值,设置完成后可以通过程序页面查看是否同步修改了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/661754.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kotlin 协程:用源码来理解 ‘viewModelScope‘

Kotlin 协程:用源码来理解 ‘viewModelScope’ Kotlin 协程是 Kotlin 语言的一大特色,它让异步编程变得更简单。在 Android 开发中,我们经常需要在后台线程执行耗时操作,例如网络请求或数据库查询,然后在主线程更新 UI…

微服务—RabbitMQ

目录 初识MQ 同步和异步通讯 同步通讯的优缺点 异步调用方案 异步通信优缺点 常见MQ技术对比 RabbitMQ快速入门 安装RabbitMQ RabbitMQ整体架构与相关概念 常见消息模型​编辑 入门案例 SpringAMQP 基本介绍 SpringAMQP案例——模拟HelloWorld消息模型 Sprin…

SpringCloud-搭建Eureka服务模块

在构建分布式微服务体系中,搭建Eureka服务模块是实现服务注册与发现的关键一步。Spring Cloud作为领先的微服务框架,通过Eureka为我们提供了高效的服务治理能力。本文将深入探讨如何使用Spring Cloud,逐步引导读者完成Eureka服务模块的搭建。…

【HarmonyOS】鸿蒙开发之ArkTs初步认识——第2.1章

ArkTs简介 ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。 以下图可以展示Js,TS,ArkTs的关系 ArkTs基础语…

C++(17)——list的模拟实现

前面的文章中,介绍了,的模拟实现,本篇文章将介绍对于的模拟实现。 目录 1. list的基本结构: 2. list功能实现:尾部插入元素: 3. list迭代器的实现: 4. list功能实现:在任意位置前…

酒店管理小程序|基于微信小程序的酒店管理系统设计与实现(源码+数据库+文档)

酒店管理小程序目录 目录 基于微信小程序的酒店管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员模块的实现 (1)用户信息管理 (2)酒店管理员管理 (3) 房间信息管理 2、小程序…

语义分割:从早期探索到深度学习的突破

语义分割:从早期探索到深度学习的突破 语义分割的端倪:从早期探索到深度学习的突破引言早期技术:图像处理与模式识别边缘检测区域生长图割(Graph Cut)聚类方法 深度学习的兴起:CNN革命2012年 AlexNet的突破全卷积网络(…

计算机网络实验一

目录 实验一 使用PacketTracer组建简单局域网 1、实验目的 2、实验设备 (1)内容一(组建简单局域网): (2)内容二(使用交叉线直连两台机器): &#xff08…

mfc140.dll丢失的几种修复方式,有效的解决文件丢失问题

mfc140.dll是Microsoft Foundation Class (MFC)库中的一个非常重要的DLL文件。它承载了许多被执行程序使用的函数和资源。这个库主要被广泛应用于开发Windows操作系统上的应用程序。然而,有时候我们可能会遭遇到mfc140.dll缺失或损坏的情况,这会导致依赖…

Linux管道、网络管理和远程连接

这次来说一下Linux管道、网络管理与远程连接相关的一些内容,如下。 一、管道(重点) 1、管道符 用 “|”(竖线)表示。 作用:管道是一种通信机制,通常用于进程间的通信。它表现出来的形式将前…

DRV8313和L298N都是电机驱动,一个是驱动三相FOC无刷直流电机的,一个是驱动有刷电机,使stm32控制无刷电机简单入门知识

DRV8313和L298N都是电机驱动器,但它们之间存在一些关键的区别: DRV83131: 由德州仪器(TI)制造。 具有集成的场效应晶体管(FET)。 最大电压为65V。 峰值电流为3A。 适用于三相电机驱动。 L298N…

维纳过程简介

在资产价格模型中,我们得出了结论:价格对数的标准差与时间的平方根 成一定比例。因此在离散时间模型下,我们可以设定以下过程,其中𝑡是相互 独立的标准正态分布变量序列 过渡到连续时间模型下,我们可以定义…

Java打印图形 九九乘法表

目录 双重循环九九乘法表打印长方形打印平行四边形打印三角形打印菱形打印空心菱形 三重循坏百钱买百鸡 双重循环 九九乘法表 在Java中,你可以使用嵌套的for循环来打印九九乘法表。以下是一个简单的示例: public class Main {public static void main…

从0搭建react+ts+redux+axios+antd项目

文章目录 一、安装及初始化二、TypeScript配置三、Webpack配置四、Prettier统一编码风格五、使用less六、Antd 安装及使用七、添加Router及配置八、安装axios九、添加redux及使用 本文介绍了如何用creat-react-app脚手架搭建一个react项目的基本结构,同时配置webpac…

printf死翘翘

本来想把我的单片机玩一下,寄给在大学搞研究的一个朋友,但竟然挂在printf里面,大概知道是什么位置出问题,但是还想不清楚什么原因。 我先是在stc51单片机里面搞了串口,然后我想用串口重定向到printf做调试,…

ApacheNginx配置ssl证书

一、Apache配置ssl Linux版本:CentOS Linux release 7.9.2009 (Core) Apache版本:Apache/2.4.6 (CentOS) 1、安装Apache(使用默认yum源) [root10-35-1-25 ~]# yum -y install httpd2、查Apache版本&启动Apache [root10-35-…

面试经典 150 题 -- 滑动窗口 (总结)

面试经典150题链接 面试经典 150 题 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台 209 . 长度最小的子数组 思路 : 滑动窗口的思想,取ij0,向后遍历j,记录前缀和[l,r]为s,如果s>target,那么左端点向右移动,直到s…

[网络安全 渗透实验 01]基于MSF框架渗透攻击Win7主机系统的设计与实现

基于MSF框架渗透攻击Win7主机系统的设计与实现 文章目录 基于MSF框架渗透攻击Win7主机系统的设计与实现[Warning] 写在前面1. 实验要求2. 实验环境搭建2.1 攻击机(Linux kali)的下载与安装2.2 靶机(Windows 7 Enterprise with Service Pack 1…

分布式事务(二)—— CAP和Base理论

系列目录: 《分布式事务(一)—— 事务的基本概念》 一、CAP理论 cap理论是分布式系统的理论基石 1、Consistency[一致性] 即操作成功并返回客户端后,所有节点在同一时间的数据完全一致,这就是分布式的一致性。一致…

Linux------进程优先级与进程切换

目录 一、进程优先级 二、优先级与权限的区别 三、优先级的查看 四、进程优先级修改 五、进程切换 六、linux2.6内核调度队列与调度原理 一、进程优先级 首先我们得知道一个进程总是需要排队的,他一会在运行队列中排队等待运行,一会在设备的等待队…