今年招新赛,出了几个水题,出题的过程中也学到了不少东西,虽然自己出的是一坨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变量引用机制的几个关键点:

  1. 对象和引用
    • Python中的数据类型(如整数、浮点数、字符串、列表等)都是对象。
    • 变量名指向这些对象,而不是直接存储数据。
  1. 引用计数
    • Python使用引用计数来跟踪一个对象被多少个变量引用。
    • 当一个对象的引用计数变为0时,意味着没有任何变量引用该对象,Python的垃圾回收机制会回收该对象,释放内存。
  1. 变量赋值
    • 当你将一个值赋给一个变量时,Python会创建一个对象,并将变量指向这个对象。
    • 如果你将一个变量赋值给另一个变量,新的变量会指向同一个对象,引用计数会增加。
  1. 可变与不可变对象
    • 不可变对象(如整数、浮点数、字符串和元组)一旦创建,其值不能改变。
    • 可变对象(如列表、字典、集合等)可以在不改变其身份(即内存地址)的情况下改变其内容。
  1. 垃圾回收
    • Python使用引用计数来管理内存,但当出现循环引用(两个或多个对象互相引用,形成闭环)时,引用计数无法正确减少到0,这时Python的垃圾回收器会介入,使用更复杂的算法来识别和回收这些循环引用。
  1. 深拷贝与浅拷贝
    • 浅拷贝(shallow copy)创建一个新的对象,但是它包含对原始对象中包含的可变对象的引用。
    • 深拷贝(deep copy)创建一个新的对象,并且递归地复制所有对象,使得新对象与原始对象完全独立。

对于[-5,256]区间的数值,python解释器会提前在内存区域加载,提高程序的运行效率,超出这个区间python就会在堆中malloc一个数然后再引用,引用数为0就free掉

img

可以看到这个变量表实际上是连续的

我们要修改真实sun_ value,就必须要找到上图的变量表,将引用的结构体的值修改为想要的值即可

下面是实操部分

  • 第一种方式
img

先找到虚假的sun_value,看看是什么改变了这篇内存

img

下断点看看调用栈

img img

以这个函数为例

单步调着调着就发现了有趣的地方

img

显然这就是那块内存区域,在此时我的阳光值是75 直接找到75即0x4B 改成 FFFF即可

img

(这里要在游戏暂停的时候修改,否则会闪退,因为运行环境的某些值会引用到这个地方,随意修改会导致程序崩溃

img
  • 第二种方式
img img img

这个地址就是变量表所在位置,直接转到这个地址找到对应的值进行修改即可


下面是非预期大赏(x

  • 手打(真-pvz高手)
  • 由于游戏机制不是无尽模式,直接开变速利用小推车把僵尸一波清了,然后手动收集阳光
  • 使用pyinjector注入到游戏进程,拿到pythonshell,可以使用dir看看类的方法,会发现有getflag的方法,直接getflag
  • 使用pydumpck解包(这里解不全的,但是直接搜索内存flag,可以很容易看出密文和加密方式,base32+base64解密即可
  • 修改游戏胜利条件,搜索10000,逐个修改为0

…and more

ZipZip

简单的压缩包攻击

掩码爆破->明文攻击->jsfuck->morsecode->flag