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成员变量。因为keyprivate私有的,常规方式访问不到,必须用反射。
  2. setAccessible(true)
    开启暴力访问,忽略 Java 的访问修饰符检查,才能修改 private 字段。
  3. set(..., 987654321)
    把全局encoder实例的key值,从原来的123456789覆盖为987654321

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


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

  1. APP 启动时,创建MainActlvity实例,构造方法执行,通过反射把Encoderkey改成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$MainActivitysynthetic 合成方法,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求余

相关推荐
菩提小狗3 小时前
每日安全情报报告 · 2026-08-26
网络安全·漏洞·cve·安全情报·每日安全
数据知道7 小时前
漏洞挖掘方法论:从 Fuzz 到 0day 的思维框架
网络·安全·web安全·网络安全
数据知道12 小时前
白盒审计入门:Source Code Review 检查清单
网络·安全·网络安全·代码复审
菜根Sec13 小时前
信息安全工程师该怎么准备考试
web安全·网络安全·信息安全·信息安全工程师
深念Y14 小时前
局域网 HTTP 请求转发 502 问题排查记录
网络·网络协议·http·网络安全·代理·转发·中转
2501_9160074714 小时前
免费抓包工具 Windows 和 Mac 怎么选?根据平台来选择工具
网络协议·计算机网络·网络安全·ios·adb·https·udp
我是乌鸦的空间1 天前
什么是网络安全中的电子数据取证与响应?
网络·网络安全
网安蟹佬霸1 天前
WAF绕过技术实战:从规则检测到编码绕过全指南(2026最新版,附Payload集与自动化脚本)
运维·安全·网络安全·架构·自动化·网安
数据知道1 天前
移动端渗透测试流程:Android APK 逆向与动态调试
android·web安全·网络安全