小菜鸟一枚 发表于 2022-10-30 00:13

学破解第199天,《攻防世界reverse练习区easyEZbaby_app》学习

前言:

  坛友们,年轻就是资本,和我一起逆天改命吧,我的学习过程全部记录及学习资源:(https://www.52pojie.cn/thread-1582287-1-1.html)

**立帖为证!--------记录学习的点点滴滴**

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

  2.题目描述

!(https://s1.ax1x.com/2022/10/29/x5v5P1.png)

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

!(https://s1.ax1x.com/2022/10/29/x5xmR0.png)

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

## 0x2 静态分析

  1.使用jadx-1.3.2工具反编译apk文件,找到onclick函数,可以看到是将我输入的用户名调用checkUsername校验,密码调用checkPass校验。

```
        public void onClick(View view) {
      String obj = this.username.getText().toString();
      String obj2 = this.password.getText().toString();
      if (!checkUsername(obj) || !checkPass(obj2)) {
            Toast.makeText(this, "登录失败", 0).show();
            return;
      }
      Toast.makeText(this, "登录成功", 0).show();
      Toast.makeText(this, "flag{" + obj + obj2 + "}", 0).show();
    }
```

  2.先去看用户名校验函数,似乎使用了md5加密,加密的数据是zhishixuebao,然后执行了一个for循环,对加密后的数据取奇数位i+=2,1,3,5,7......这样,然后调用equals函数判断是否等于我输入的字符串。

```
    public boolean checkUsername(String str) {
      if (str != null) {
            try {
                if (!(str.length() == 0 || str == null)) {
                  MessageDigest instance = MessageDigest.getInstance("MD5");
                  instance.reset();
                  instance.update("zhishixuebao".getBytes());
                  String hexString = toHexString(instance.digest(), "");
                  StringBuilder sb = new StringBuilder();
                  for (int i = 0; i < hexString.length(); i += 2) {
                        sb.append(hexString.charAt(i));
                  }
                  String sb2 = sb.toString();
                  return (sb2).equals(str);
                }
                return false;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
      }
      return false;
    }
```

&emsp;&emsp;3.再去看看校验密码函数,判断长度是不是等于15,后面也是一个for循环,这里给它化简255-i+2-98-未知数x需要等于'0'对应的ASCII值48,那么求x的值,x=111-i,而i的值就是从0到14,这样便可以计算出15位的密码。

```
    public boolean checkPass(String str) {
      if (str == null) {
            return false;
      }
      char[] charArray = str.toCharArray();
      if (charArray.length != 15) {
            return false;
      }
      for (int i = 0; i < charArray.length; i++) {
            charArray = (char) ((((255 - i) + 2) - 98) - charArray);
            if (charArray != '0' || i >= 15) {
                return false;
            }
      }
      return true;
    }
```

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

## 0x3 动态调试

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

!(https://s1.ax1x.com/2022/10/29/xISSu8.png)

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

!(https://s1.ax1x.com/2022/10/29/xISF4s.png)

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

!(https://s1.ax1x.com/2022/10/29/xIpNzq.png)

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

!(https://s1.ax1x.com/2022/10/29/xIC054.png)

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

!(https://s1.ax1x.com/2022/10/29/xICG2n.png)

## 0x4总结

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

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

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

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class test01 {

        public static void main(String[] args) {
               
                //搬运原算法得到用户名
                try {
                        MessageDigest instance = MessageDigest.getInstance("MD5");
                        instance.reset();
                        instance.update("zhishixuebao".getBytes());
                        String hexString = toHexString(instance.digest(), "");
                        StringBuilder sb = new StringBuilder();
                        for (int i = 0; i < hexString.length(); i += 2) {
                                sb.append(hexString.charAt(i));
                        }
                        String user = sb.toString();
                        System.out.println("用户名:"+user);
                } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                }

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

        private static String toHexString(byte[] bArr, String str) {
                StringBuilder sb = new StringBuilder();
                for (byte b : bArr) {
                        String hexString = Integer.toHexString(b & 255);
                        if (hexString.length() == 1) {
                                sb.append('0');
                        }
                        sb.append(hexString);
                        sb.append(str);
                }
                return sb.toString();
        }
}
```

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

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

!(https://s1.ax1x.com/2022/10/30/xIPBef.png)

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

GGabc 发表于 2022-10-30 00:29

学习一下!

webzdqdxkj 发表于 2022-10-30 00:57

hao123亮了。。。不过lz提供的书籍有参考价值,先ma'r

jinhougou 发表于 2022-10-30 01:07

感谢受教了

tyosei 发表于 2022-10-30 01:27

感谢,牛逼

judgecx 发表于 2022-10-30 07:08

这个动态调试是什么工具

Transcend 发表于 2022-10-30 08:23

厉害,谢谢分享

yyb1813 发表于 2022-10-30 08:26

dhwl9899 发表于 2022-10-30 08:38

谢谢分享,好难。学习学习。

litaozi 发表于 2022-10-30 09:04

又学到了不少知识,感谢分享
页: [1] 2 3 4
查看完整版本: 学破解第199天,《攻防世界reverse练习区easyEZbaby_app》学习