[其它交流] 攻防世界reverse练习区easyEZbaby_app练习!

315 1
小菜鸟一枚 2022-10-30 00:25:52 | 显示全部楼层 |阅读模式
鸣谢大佬joker帮忙分析,真大佬!

前言:

        论坛未开启Markdown语法支持,如果想要更好的阅读,可以下载文末附件,使用浏览器打开html文件阅读体验更好哦。


0x1 题目来源
  1.攻防世界reserve练习区XSCTF联合招新赛(初赛):easyEZbaby_app。

  2.题目描述

  3. 看题目描述应该很适合我这样的菜鸟,锁定目标就可以开始分析了,拖进模拟器看看运行结果。

  4.通过简单观察可以知道我需要输入正确的用户名和密码才能拿到flag。

0x2 静态分析
  1.使用jadx-1.3.2工具反编译apk文件,找到onclick函数,可以看到是将我输入的用户名调用checkUsername校验,密码调用checkPass校验。
  1.     public void onClick(View view) {
  2.         String obj = this.username.getText().toString();
  3.         String obj2 = this.password.getText().toString();
  4.         if (!checkUsername(obj) || !checkPass(obj2)) {
  5.             Toast.makeText(this, "登录失败", 0).show();
  6.             return;
  7.         }
  8.         Toast.makeText(this, "登录成功", 0).show();
  9.         Toast.makeText(this, "flag{" + obj + obj2 + "}", 0).show();
  10.     }
复制代码

  2.先去看用户名校验函数,似乎使用了md5加密,加密的数据是zhishixuebao,然后执行了一个for循环,对加密后的数据取奇数位i+=2,1,3,5,7......这样,然后调用equals函数判断是否等于我输入的字符串。
  1.     public boolean checkUsername(String str) {
  2.         if (str != null) {
  3.             try {
  4.                 if (!(str.length() == 0 || str == null)) {
  5.                     MessageDigest instance = MessageDigest.getInstance("MD5");
  6.                     instance.reset();
  7.                     instance.update("zhishixuebao".getBytes());
  8.                     String hexString = toHexString(instance.digest(), "");
  9.                     StringBuilder sb = new StringBuilder();
  10.                     for (int i = 0; i < hexString.length(); i += 2) {
  11.                         sb.append(hexString.charAt(i));
  12.                     }
  13.                     String sb2 = sb.toString();
  14.                     return (sb2).equals(str);
  15.                 }
  16.                 return false;
  17.             } catch (NoSuchAlgorithmException e) {
  18.                 e.printStackTrace();
  19.             }
  20.         }
  21.         return false;
  22.     }
复制代码

&#8195;&#8195;3.再去看看校验密码函数,判断长度是不是等于15,后面也是一个for循环,这里给它化简255-i+2-98-未知数x需要等于'0'对应的ASCII值48,那么求x的值,x=111-i,而i的值就是从0到14,这样便可以计算出15位的密码。
  1.     public boolean checkPass(String str) {
  2.         if (str == null) {
  3.             return false;
  4.         }
  5.         char[] charArray = str.toCharArray();
  6.         if (charArray.length != 15) {
  7.             return false;
  8.         }
  9.         for (int i = 0; i < charArray.length; i++) {
  10.             charArray[i] = (char) ((((255 - i) + 2) - 98) - charArray[i]);
  11.             if (charArray[i] != '0' || i >= 15) {
  12.                 return false;
  13.             }
  14.         }
  15.         return true;
  16.     }
复制代码

&#8195;&#8195;4.基本上整个程序的逻辑就是这样的,只要想明白了,确实很简单。

0x3 动态调试
&#8195;&#8195;1.接下来动态调试一下,打开jeb,找到onclicl函数,ctrl+B下断点,输入admin和123456运行,可以看到经过md5加密后“zhishixuebao”变成了"7da5fec345fecde5fdcd641f68e0b6d1",经过和md5在线加密网站对比可以知道是标准的md5 32位加密。

&#8195;&#8195;2.然后继续单步走,可以看到v3就是for循环的下标,从0开始每次加2,取md5对应下标值存储,然后直接和我输入的用户名admin比较是否相等。

&#8195;&#8195;3.正常再单步走肯定跳转向失败了,所以强行修改返回值为true,继续往下,这里因为我输入的123456长度为6,长度必须为15,我这里直接修改,让他继续走。

&#8195;&#8195;4.继续看,v1就是for循环变量i,首先v3 = 255-i,然后再-98,然后再将我输入的123456第一个字符1给到v4,再v3=v3-v4,然后给v4赋值0x30,最后比较v3和v4是否相等。

&#8195;&#8195;5.接下来的跳转我强制改值让他跳转成功,是不是也能得到flag?flag{7afc4fcefc616ebdonmlkjihgfedcba}

0x4总结
&#8195;&#8195;1.通过前面的分析可以知道本题有两种解法,一种是简单直接的爆破,另一种就是计算用户名和密码,得到flag。

&#8195;&#8195;2.方法一:爆破,直接强制修改跳转,可参考0x3动态分析那里。

&#8195;&#8195;3.方法二:计算flag,用户名可照搬算法,密码按照刚刚的计算方程用代码表示即可。
  1. package ctf;

  2. import java.security.MessageDigest;
  3. import java.security.NoSuchAlgorithmException;

  4. public class test01 {

  5.     public static void main(String[] args) {

  6.         //搬运原算法得到用户名
  7.         try {
  8.             MessageDigest instance = MessageDigest.getInstance("MD5");
  9.             instance.reset();
  10.             instance.update("zhishixuebao".getBytes());
  11.             String hexString = toHexString(instance.digest(), "");
  12.             StringBuilder sb = new StringBuilder();
  13.             for (int i = 0; i < hexString.length(); i += 2) {
  14.                 sb.append(hexString.charAt(i));
  15.             }
  16.             String user = sb.toString();
  17.             System.out.println("用户名:"+user);
  18.         } catch (NoSuchAlgorithmException e) {
  19.             e.printStackTrace();
  20.         }

  21.         //计算密码
  22.         StringBuilder pwd = new StringBuilder();
  23.         for (int i = 0; i < 15; i++) {
  24.             pwd.append((char) ((((255 - i) + 2) - 98) - 48));
  25.         }
  26.         System.out.println("密码:"+pwd);
  27.     }

  28.     private static String toHexString(byte[] bArr, String str) {
  29.         StringBuilder sb = new StringBuilder();
  30.         for (byte b : bArr) {
  31.             String hexString = Integer.toHexString(b & 255);
  32.             if (hexString.length() == 1) {
  33.                 sb.append('0');
  34.             }
  35.             sb.append(hexString);
  36.             sb.append(str);
  37.         }
  38.         return sb.toString();
  39.     }
  40. }
复制代码

输出:
用户名:7afc4fcefc616ebd
密码:onmlkjihgfedcba

&#8195;&#8195;4.输入正确的用户名和密码也可以得到flag,和爆破的方式拿到的一样。

&#8195;&#8195;5.建议:可以让flag与前面的我输入的用户名或者密码一起参与计算,这样就没办法通过爆破得到flag。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
joker实名认证 2022-10-30 14:25:19 来自手机 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行