scriptCTF|div|python代码审计

打开附件后得到代码

点击查看代码 ```
```plaintext
# 导入需要的模块
import os           # 用于生成随机数
import decimal      # 用于高精度 decimal 运算

# 设置 decimal 模块的全局精度为 50 位,确保高精度计算
decimal.getcontext().prec = 50

# 生成一个随机的 16 字节数据,转换为十六进制字符串后再转为整数作为秘密值
# os.urandom(16) 生成 16 字节的随机字节串
# .hex() 将字节串转换为十六进制字符串
# int(..., 16) 将十六进制字符串转换为十进制整数
secret = int(os.urandom(16).hex(), 16)

# 获取用户输入的数字
num = input('Enter a number: ')

# 检查用户输入中是否包含科学计数法的标志 'e' 或 'E'
# 如果包含则提示"Nice try..."并退出程序
if 'e' in num.lower():
    print("Nice try...")
    exit(0)

# 检查用户输入的数字长度是否大于等于 10 位
# 如果是则提示"Number too long..."并退出程序
if len(num) >= 10:
    print('Number too long...')
    exit(0)

# 将用户输入的字符串转换为 decimal.Decimal 类型,用于高精度计算
fl_num = decimal.Decimal(num)

# 计算秘密值除以用户输入数字的结果
div = secret / fl_num

# 判断除法结果是否为 0
# 如果结果为 0,则读取并打印 flag.txt 文件内容(通常是解题的目标)
# 否则提示"Try again..."
if div == 0:
    print(open('flag.txt').read().strip())
else:
    print('Try again...')


代码的核心逻辑是:程序生成一个随机的大整数secret,然后要求用户输入一个数字。程序会检查输入是否符合格式要求(不允许科学计数法、长度不超过 9 位),然后用secret除以用户输入的数字。如果结果为 0,就会输出 flag。
从逻辑上看,要使secret / fl_num == 0成立,需要fl_num是一个比secret大得多的数。但由于程序限制了输入长度不超过 9 位,这在常规情况下几乎不可能实现,可能需要利用decimal模块的一些特性或漏洞来解决。

要解决这个问题,我们需要找到一个符合输入限制的数值,使得 secret / fl_num == 0 成立。结合代码逻辑和 decimal 模块的特性,突破口在于利用 无穷大(Infinity) 的特性。
关键分析:
代码的核心条件是 secret / fl_num == 0。由于 secret 是一个随机生成的 128 位大整数(必然大于 0),要让除法结果为 0,只有两种可能:
被除数 secret 为 0(但 secret 由随机数生成,不可能为 0);
除数 fl_num 为 无穷大(Infinity)(因为任何正数除以无穷大的结果都是 0)。
输入限制的突破:
代码对输入的限制是:
不能包含 e 或 E(排除科学计数法);
长度不能超过 9 位。
而 decimal.Decimal 模块支持解析特殊字符串 "Infinity"(表示正无穷大),其特性为:
字符串 "Infinity" 长度为 8(满足 len < 10);
不含 e 或 E(满足格式要求);
转换为 decimal.Decimal 后会被识别为正无穷大。
解决方案:
输入字符串 "Infinity"(或小写 "inf",decimal 模块对大小写不敏感),具体步骤如下:
输入 "Infinity",其长度为 8(符合 len < 10),且不含 e,通过输入检查;
转换为 decimal.Decimal 后,fl_num 会被解析为正无穷大;
计算 secret / fl_num 时,结果为 0(任何正数除以无穷大都是 0);
触发 div == 0 的条件,程序会输出 flag.txt 中的内容。
验证:
测试输入 "Infinity":
长度检查:len("Infinity") = 8 < 10 → 通过;
格式检查:不含 e → 通过;
转换结果:fl_num = Decimal('Infinity')(正无穷大);
除法运算:secret / Infinity = 0 → 满足条件,输出 flag。
因此,最终答案是输入 Infinity(或 inf)。

提取文字后得到flag
image

posted @ 2025-08-16 20:35  Dragon_Roar  阅读(7)  评论(0)    收藏  举报