赞
踩
python: 3.12.1
Pymen: 1.13.1
python-pptx: 0.6.23
WPS演示: 12.1.0.16250
pip install pymem
pip install python-pptx
这个功能实现比较简单,直接通过python-pptx库即可实现
# 获取 ppt 总页数
def get_ppt_total_page_count(ppt_file:str):
ppt = Presentation(ppt_file)
total_page_count = len(ppt.slides)
return total_page_count
这个功能相对比较复杂,网上也没有找到相关的博客,基本都是如何提供python去修改ppt的
后来想了想,ppt播放时软件里肯定得记录这个页索引数吧,就想着试试用Cheat Engine这种内存地址数值查找工具找找看,结果还真给我找到了
首先播放PPT,然后打开CE找到 WPS演示 幻灯片放映 这个进程
比如现在播放的是PPT的第一页,那就在输入框中输入0
然后随便切到PPT的任意页,输入该页的索引后点击next scan
这样多重复几次这个操作,直到左侧结果栏中只剩下一个结果
右键它点击Find out what accesses this address
弹出窗口后,随便切下PPT的播放进度,注意别把PPT播放完了关掉了
这样弹窗的结果栏中就会出现一些结果,随便找到一个mov命令的结果点击查看结果内容
记住ebx+20的+20,表示内存地址+0x20得到该用于表示PPT当前播放进度的临时变量
这个EBX的地址可以不用记住,复制即可
关闭该弹窗,勾上Hex,然后粘贴上EBX的地址,进行新一轮的查找
会发现有很多值是EBX地址值的地址,随便找一个右键Find out what accesses this address
然后还是重复上述步骤,随便切几下PPT,找到mov命令的结果
(可能有些地址不会弹出来这些命令,那么多地址再换一个找就行,不出意外应该都能找到)
还是像上述那样,记住+0x1C,然后复制ESI地址重复步骤,不出意外找个两三轮应该就能找到绿色的结果了,这个表示是静态地址,也就是说下次打开软件播放时还是这个地址,不会变
OK,这样就找到了固定地址,接下来就是基于这个固定地址找到我们一开始找的用于记录当前PPT播放进度的临时变量
player.dll+BA6EC记录了下一个变量的地址,下一个变量的地址记录了下下个变量的地址,就这样一直推得到那个临时变量
因此,临时变量地址 = [[[player.dll + BA6EC] + 28] + 1C] + 20
注意:这里[]表示获取的是地址的值而不是地址
每个人可能不一样,根据实际得到的偏址变化来
通过pymem库,首先获取player.dll模块的基址,然后就是根据上述得到的反推临时变量的公式得到临时变量的地址了
# 获取指定dll的基址
def get_module_address(dll_name:str, process):
modules = list(process.list_modules())
for module in modules:
if module.name == dll_name:
return module.lpBaseOfDll
根据 临时变量地址 = [[[player.dll + BA6EC] + 28] + 1C] + 20,得到临时变量的值
player_dll_name = "player.dll"
process_name = "wpp.exe"
process = pymem.Pymem(process_name)
player_dll_base_address = get_module_address(player_dll_name, process)
value_address = process.read_int(static_address_value + 0x00000028)
value_address = process.read_int(value_address + 0x0000001C)
value = process.read_int(value_address + 0x00000020)
得到的value就是当前的播放进度索引啦
注意:我测试下来发现wps的ppt有2个临时变量的地址去存储这个当前播放索引,并且其中一个地址作为播放索引的临时变量时,另一个地址的值始终为0
另一个临时变量的地址推导公式为
临时变量 = [[[[[[player.dll + BA6EC] + 28] + 18] + 4] + 4] + 8] + 20
同样的方法去获取这个临时变量的值
因为其中一个地址作为播放索引的临时变量时,另一个地址的值始终为0
那我们就可以封装下,返回两个地址的最大值即可表示当前的播放索引了
# 获取当前 ppt 页数 def get_current_ppt_index(process_name:str="wpp.exe", player_dll_name:str="player.dll"): # 获取进程 process = pymem.Pymem(process_name) # 获取 player.dll 的基址 player_dll_base_address = get_module_address(player_dll_name, process) # 找到静态地址 player.dll + 0xBA6EC 的值 static_address_value = process.read_int(player_dll_base_address + 0x000BA6EC) # 测试发现有 2 个临时变量记录着当前页数 # value_1 value_1_address = process.read_int(static_address_value + 0x00000028) value_1_address = process.read_int(value_1_address + 0x00000018) value_1_address = process.read_int(value_1_address + 0x00000004) value_1_address = process.read_int(value_1_address + 0x00000004) value_1_address = process.read_int(value_1_address + 0x00000008) value_1 = process.read_int(value_1_address + 0x00000020) # value_2 value_2_address = process.read_int(static_address_value + 0x00000028) value_2_address = process.read_int(value_2_address + 0x0000001C) value_2 = process.read_int(value_2_address + 0x00000020) # 当其中一个变量记录当前页数时,另一个变量的值为 0, 则两个变量的最大值为当前页数 return max(value_1, value_2)
这样我们就得到了当前的播放进度及总页数
log_utils是我自己封装的日志打印方法,删了改成print就行
from pptx import Presentation import pymem import time from log_utils import * # 获取模块的内存地址 def get_module_address(dll_name:str, process): modules = list(process.list_modules()) for module in modules: if module.name == dll_name: return module.lpBaseOfDll # 获取 ppt 总页数 def get_ppt_total_page_count(ppt_file:str): ppt = Presentation(ppt_file) total_page_count = len(ppt.slides) return total_page_count # 获取当前 ppt 页数 def get_current_ppt_index(process_name:str="wpp.exe", player_dll_name:str="player.dll"): # 获取进程 process = pymem.Pymem(process_name) # 获取 player.dll 的基址 player_dll_base_address = get_module_address(player_dll_name, process) # 找到静态地址 player.dll + 0xBA6EC 的值 static_address_value = process.read_int(player_dll_base_address + 0x000BA6EC) # 测试发现有 2 个临时变量记录着当前页数 # value_1 value_1_address = process.read_int(static_address_value + 0x00000028) value_1_address = process.read_int(value_1_address + 0x00000018) value_1_address = process.read_int(value_1_address + 0x00000004) value_1_address = process.read_int(value_1_address + 0x00000004) value_1_address = process.read_int(value_1_address + 0x00000008) value_1 = process.read_int(value_1_address + 0x00000020) # value_2 value_2_address = process.read_int(static_address_value + 0x00000028) value_2_address = process.read_int(value_2_address + 0x0000001C) value_2 = process.read_int(value_2_address + 0x00000020) # 当其中一个变量记录当前页数时,另一个变量的值为 0, 则两个变量的最大值为当前页数 return max(value_1, value_2) if __name__ == "__main__": ppt_file = "test.pptx" player_dll_name = "player.dll" process_name = "wpp.exe" total_page_count = get_ppt_total_page_count(ppt_file=ppt_file) while True: try: current_ppt_index = get_current_ppt_index(process_name=process_name, player_dll_name=player_dll_name) progress = (current_ppt_index + 1) / total_page_count log_progress(progress, logger=f"第{current_ppt_index+1}/{total_page_count}页") except Exception as e: log_warning("未找到进程") time.sleep(1)
基地址寻址和偏移地址应用案例_chest engine如何看地址偏移-CSDN博客
以上就是“【Python】基于内存地址获取WPS中ppt的当前播放进度”的全部内容,希望对你有所帮助。
关于Python技术储备
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
一、Python所有方向的学习路线
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、Python必备开发工具
三、Python视频合集
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
四、实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
五、Python练习题
检查学习结果。
六、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
最后祝大家天天进步!!
上面这份完整版的Python全套学习资料已经上传至CSDN官方,朋友如果需要可以直接微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。