news 2026/8/29 18:06:39

nssctf_easyapp

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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短时弹窗。

写解密脚本:

cipher="棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌"key=987654321flag=""forcincipher:flag+=chr((ord(c)^key)%128);print(flag)

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

本题知识点:1、查壳
2、加后缀名
3、知道函数逻辑
4、知道对128求余

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/29 18:04:47

Claude Code默认自动模式:配置、成本与工程实践

最近 Claude Code 的讨论热度又一次被拉满,原因不是模型能力又突破了,而是产品默认行为的一次调整:默认自动模式进入倒计时。按照社区流传的消息,再过 5 天左右,Claude Code 的默认模式会从“手动确认”切换到“自动执…

作者头像 李华
网站建设 2026/8/29 18:01:31

网易2016研发工程师编程题解析:链表、动态规划与贪心算法实战

每年的校招季,总有几套题会被反复拿出来讨论,网易2016研发工程师的编程题就是其中之一。我身边不少后来进了大厂的朋友,当年都把这份卷子当作练手标配。这轮题目的特点很鲜明:不玩偏题怪题,基础知识覆盖扎实&#xff0…

作者头像 李华
网站建设 2026/8/29 17:58:03

MATLAB数学建模实战:从核心工具箱到高效工作流

1. 项目概述:为什么数学建模离不开MATLAB? 如果你正在接触数学建模,或者准备参加相关的竞赛,那么“MATLAB练习”这个标题对你来说一定不陌生。这几乎是每个建模人从入门到精通的必经之路。我刚开始接触建模时,也以为它…

作者头像 李华
网站建设 2026/8/29 17:55:27

研究谷氨酸神经毒性的 HT-22 海马细胞,培养要点一次说清

做神经退行、氧化应激或者谷氨酸兴奋毒性的同学,HT-22 是很常用的一株。它是永生化的小鼠海马神经元细胞,对谷氨酸特别敏感,是研究谷氨酸诱导神经毒性的标准模型。HT-22 是小鼠海马神经元细胞,从 HT-4 细胞系亚克隆而来&#xff1…

作者头像 李华
网站建设 2026/8/29 17:54:34

BFS与图论建模:八数码问题的最小步数求解与状态空间搜索

1. 项目概述:从“八数码”到“最小步数”的思维跃迁如果你玩过那种3x3滑块拼图,目标是通过滑动空白块来将打乱的数字(通常是1到8)按顺序排列,那么你已经接触过“八数码”问题的实体版本了。在算法竞赛和人工智能的入门…

作者头像 李华
网站建设 2026/8/29 17:54:24

智能体交出控制权|从开箱到自建的控制边界

最实用的智能体,可能不是最强的一个,而是我能放心让它跑一整天的那个。 常被推荐的产品化方向,是把编码助手改造成面向普通白领的自主智能体,让它带着明确目标,自己拆步骤、自己查资料、自己产出结果,用户只…

作者头像 李华