今年招新赛,出了几个水题,出题的过程中也学到了不少东西,虽然自己出的是一坨shit(
出题的主要目的是提高题目的趣味性(避免上来一坨逆天算法导致劝退)
让选手有更多的兴趣做逆向
听说你是pvz高手1/2?
Pvz1直接用ce修改即可,也可以修改userdata.json配置文件直接通关
python | 内存模型-腾讯云开发者社区-腾讯云 (tencent.com)
【python】内存管理结构初探——我要的内存从哪儿来的?_哔哩哔哩_bilibili
https://blog.csdn.net/u012219371/article/details/98449700
通过cheatengine对pvz进行简单调试,观察函数调用栈,我们可以大致猜出真实的阳光是用python变量存的,而能扫到的阳光是用ctypes变量存的,扫到的阳光仅仅是一个中间变量
真实的sun_valuie实际是一个对内存的引用,因此我们无法通过变化扫到对应sun_value的真实地址的
在Python中,变量的引用机制是基于对象的引用计数来管理的。这意味着变量名实际上是对存储在内存中的对象的引用。以下是Python变量引用机制的几个关键点:
- 对象和引用:
- Python中的数据类型(如整数、浮点数、字符串、列表等)都是对象。
- 变量名指向这些对象,而不是直接存储数据。
- 引用计数:
- Python使用引用计数来跟踪一个对象被多少个变量引用。
- 当一个对象的引用计数变为0时,意味着没有任何变量引用该对象,Python的垃圾回收机制会回收该对象,释放内存。
- 变量赋值:
- 当你将一个值赋给一个变量时,Python会创建一个对象,并将变量指向这个对象。
- 如果你将一个变量赋值给另一个变量,新的变量会指向同一个对象,引用计数会增加。
- 可变与不可变对象:
- 不可变对象(如整数、浮点数、字符串和元组)一旦创建,其值不能改变。
- 可变对象(如列表、字典、集合等)可以在不改变其身份(即内存地址)的情况下改变其内容。
- 垃圾回收:
- Python使用引用计数来管理内存,但当出现循环引用(两个或多个对象互相引用,形成闭环)时,引用计数无法正确减少到0,这时Python的垃圾回收器会介入,使用更复杂的算法来识别和回收这些循环引用。
- 深拷贝与浅拷贝:
- 浅拷贝(shallow copy)创建一个新的对象,但是它包含对原始对象中包含的可变对象的引用。
- 深拷贝(deep copy)创建一个新的对象,并且递归地复制所有对象,使得新对象与原始对象完全独立。
对于[-5,256]区间的数值,python解释器会提前在内存区域加载,提高程序的运行效率,超出这个区间python就会在堆中malloc一个数然后再引用,引用数为0就free掉
可以看到这个变量表实际上是连续的
我们要修改真实sun_ value,就必须要找到上图的变量表,将引用的结构体的值修改为想要的值即可
下面是实操部分
- 第一种方式
先找到虚假的sun_value,看看是什么改变了这篇内存
下断点看看调用栈
以这个函数为例
单步调着调着就发现了有趣的地方
显然这就是那块内存区域,在此时我的阳光值是75 直接找到75即0x4B 改成 FFFF即可
(这里要在游戏暂停的时候修改,否则会闪退,因为运行环境的某些值会引用到这个地方,随意修改会导致程序崩溃
- 第二种方式
这个地址就是变量表所在位置,直接转到这个地址找到对应的值进行修改即可
下面是非预期大赏(x
- 手打(真-pvz高手)
- 由于游戏机制不是无尽模式,直接开变速利用小推车把僵尸一波清了,然后手动收集阳光
- 使用
pyinjector
注入到游戏进程,拿到pythonshell,可以使用dir看看类的方法,会发现有getflag的方法,直接getflag - 使用
pydumpck
解包(这里解不全的,但是直接搜索内存flag,可以很容易看出密文和加密方式,base32+base64解密即可 - 修改游戏胜利条件,搜索10000,逐个修改为0
…and more
ZipZip
简单的压缩包攻击
掩码爆破->明文攻击->jsfuck->morsecode->flag