nssctf_easyapp

下载、查壳、

jadx反编译,打开encoder类和MainActlvity 类

这道题的核心逻辑分为两个类:Encoder(加密算法类)和MainActlvity(主界面 + 反射改密钥类),下面逐行拆解。


一、Encoder 类(加密核心)

复制代码
public class Encoder {
    // 【迷惑项】初始默认密钥,private私有,外部无法直接访问
    private int key = 123456789;

    // 加密方法:输入明文字符串,输出密文字符串
    public String encode(String str) {
        StringBuilder sb = new StringBuilder();
        // 遍历输入字符串的每一个字符
        for (char c : str.toCharArray()) {
            // 核心运算:字符 与 key 做异或运算,强转为char类型拼接
            sb.append((char) (c ^ this.key));
        }
        return sb.toString();
    }
}

逻辑说明

  1. 加密算法 :单字节异或对称加密。
    • 加密:密文字符 = 明文字符 ^ 密钥
    • 解密:明文字符 = 密文字符 ^ 密钥(异或是可逆运算,同一个密钥运算两次就还原明文)
  2. 数据类型 :Java 的char是 16 位 Unicode 字符,因此异或后会得到中文类的宽字符,也就是我们看到的乱码密文。
  3. 坑点提示 :这里的key = 123456789是写死的初始值,但程序运行时并不会用这个值,后面会通过反射动态修改。

二、MainActlvity 类(反射改密钥,核心考点)

复制代码
public class MainActlvity {
    public MainActlvity() {
        try {
            // 1. 获取Encoder类中名为"key"的私有字段
            Field declaredField = Encoder.class.getDeclaredField("key");
            // 2. 暴力反射:打破private访问权限限制
            declaredField.setAccessible(true);
            // 3. 动态修改:将encoder对象的key字段,设置为新值 987654321
            declaredField.set(MainActivity.encoder, 987654321);
        } catch (IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

逐行逻辑

  1. getDeclaredField("key")
    反射获取Encoder类的key成员变量。因为key是private私有的,常规方式访问不到,必须用反射。
  2. setAccessible(true)
    开启暴力访问,忽略 Java 的访问修饰符检查,才能修改 private 字段。
  3. set(..., 987654321)
    把全局encoder实例的key值,从原来的123456789覆盖为987654321。

✅ 程序运行时,真实生效的加密密钥是 987654321,不是类里写的 123456789,这是这道题最核心的考点。


三、完整校验流程(结合题目逻辑)

  1. APP 启动时,创建MainActlvity实例,构造方法执行,通过反射把Encoder的key改成987654321。
  2. 用户在输入框输入 flag,点击校验按钮。
  3. 调用encoder.encode(输入内容),用修改后的密钥 987654321对输入做异或加密。
  4. 把加密后的结果,和代码里固定的密文字符串棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌做对比。
  5. 完全相等则提示验证成功,否则失败。
  1. 成员变量
  • public static Encoder encoder;:静态加密类引用,Encoder 是外部类,截图看不到实现。
  • public static MainActivity mainActivity;:静态 Activity 引用;mainActivity = new MainActivity();这行写法不符合 Android 规范,Activity 不能直接 new,该行不会参与业务逻辑,属于冗余无效代码。
  1. onCreate 生命周期方法
  • setContentView(R.layout.activity_main):加载布局页面;
  • findViewById获取输入框、按钮控件;
  • 给按钮绑定点击事件;点击时调用lambda$onCreate$0$MainActivity方法。

lambda$onCreate$0$MainActivity:synthetic 合成方法,Java 编译 lambda / 匿名内部类时自动生成,不是开发者手写的原始方法名。

  1. 校验逻辑 lambda$onCreate000MainActivity
  2. 获取输入框文本,调用encoder.encode()做加密,把加密结果打印控制台;
  3. 关键条件:用户输入 → encode加密 → 和写死的中文密文字符串比对
    • 如果加密结果等于 "梡椆梮棜椋椒粜棐棁梲棨槮梀" → Toast 弹出 YES
    • 否则弹出 NO
  4. Toast第三个参数 0,等价Toast.LENGTH_SHORT短时弹窗。

写解密脚本:

python 复制代码
cipher="棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌"
key=987654321
flag=""
for c in cipher:
    flag+=chr((ord(c)^key)%128);

print(flag)

对128取模的原因是因为ASCII字符集只有128个字符,所以如果不取模,那么异或运算的结果可能超出ASCII范围,导致无法正确解密。取模128可以保证结果在0到127之间,也就是ASCII字符集的有效范围。

本题知识点:1、查壳

2、加后缀名

3、知道函数逻辑

4、知道对128求余

相关推荐
Chengbei1114 小时前
拒绝无效洞!蚂蚁Src榜一Clown 2.0 SRC SKill 第二代带状态闭环的白盒 & 黑盒审计 Skill
网络·人工智能·安全·web安全·网络安全·自动化·安全架构
XLYcmy15 小时前
PDF 论文处理器 — 优势与功能文档
大数据·python·网络安全·pdf·dify·rag·漏洞检测
白帽攻防录18 小时前
SRC 挖洞:V8 Turbofan 沙箱逃逸深度复盘,CVE-2026-6307 一根长矛怎么刺穿 Chrome 两道边界
网络·chrome·安全·网络安全·浏览器安全
hengdonghui19 小时前
Writeup 4 红帽杯 2021 WebsiteManger
web·ctf·ssrf·sql布尔盲注
菩提小狗19 小时前
每日安全情报报告 · 2026-10-05
网络安全·漏洞·cve·安全情报·每日安全
sbjdhjd20 小时前
云安全 | Docker 容器逃逸复盘(一):从隔离边界到运行时链路,如何确认自己身处容器
网络安全·docker·云原生·容器·kubernetes·云计算·云安全
XLYcmy20 小时前
PDF 论文处理器 — 技术报告文档
数据库·python·网络安全·pdf·embedding·dify·rag
杭州领祺科技2 天前
27 号令横向隔离落地清单:储能边缘计算网关 ≠ 电力专用网闸,算电协同中心安全分区/纵向加密/SPDnet 怎么配
人工智能·安全·网络安全·边缘计算·储能·电力·电力监控
菩提小狗2 天前
每日安全情报报告 · 2026-10-04
网络安全·漏洞·cve·安全情报·每日安全
迪康coolmu2 天前
屏幕水印与防拍照落地:从水印类型到泄密溯源的完整配置
运维·网络·安全·网络安全·数据安全