攻防世界 XCTF 【Mobile】easy-app 题解

正常先下载附件,解压后,先拖到 JADX-gui 中去放编译一下,然后保存到文件夹里去,后用 IDEA 打开,方便我们编辑。

打开之后,先观察一下 AndroidManifest.xml 里面都有什么。

值得注意的东西:

js 复制代码
包名:com.testjava.jack.pingan1
Main Activity:com.testjava.jack.pingan1.MainActivity

看看 MainActivity 怎么写的

java 复制代码
public void onCreate(Bundle savedInstanceState) {
    ...

    btn.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {
            EditText edit1 = (EditText) MainActivity.this.findViewById(R.id.editText);
            String strIn = edit1.getText().toString();
            Base64New nb = new Base64New();
            String enStr = nb.Base64Encode(strIn.getBytes());
            if (enStr.equals("5rFf7E2K6rqN7Hpiyush7E6S5fJg6rsi5NBf6NGT5rs=")) {
                Toast.makeText(MainActivity.this, "验证通过!", 1).show();
            } else {
                Toast.makeText(MainActivity.this, "验证失败!", 1).show();
            }
        }
    });
}

逻辑也很简单,获取用户输入,然后使用 nb.Base64Encode() 函数给处理一下,然后判断一下和 5rFf7E2K6rqN7Hpiyush7E6S5fJg6rsi5NBf6NGT5rs= 是否相等,这里写 Base64New 估计是想误导一下,估计不是正常的 base64

看一下 Base64New 类的实现,跟普通的 base64 差不多,只是码表变了顺序

这里给出一些解决的思路: 1、 去 github 上搜索一下

可以看到,直接就找到了别人写的加密和解密函数,那么你拿来用就行了。

2、观察一下这个编码函数,既然叫 base64 ,那么算法应该就是 base64 的算法,但是观察可以发现,这个码表和 base64 的码表顺序不一样

所以第二种思路就是,把 java base64 的代码复制一份,然后删除不需要的代码,然后把码表顺序改一下,我这里就给出一份我改的吧

java 复制代码
import java.nio.charset.StandardCharsets;
import java.util.Arrays;


public class Check {
    public static void main(String[] args) {
        // 解码
        Decoder decoder = new Decoder();
        byte[] result = decoder.decode("5rFf7E2K6rqN7Hpiyush7E6S5fJg6rsi5NBf6NGT5rs=".getBytes(StandardCharsets.UTF_8));
        System.out.println("flag{" + new String(result) + "}");

        // 验证一下
        Base64New bn = new Base64New();
        System.out.println(bn.Base64Encode("05397c42f9b6da593a3644162d36eb01".getBytes(StandardCharsets.UTF_8)));
    }
}

class Base64New {
    private static final char[] Base64ByteToStr = {
            'v', 'w', 'x', 'r', 's', 't', 'u', 'o', 'p', 'q', '3', '4', '5',
            '6', '7', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'y',
            'z', '0', '1', '2', 'P', 'Q', 'R', 'S', 'T', 'K', 'L', 'M', 'N',
            'O', 'Z', 'a', 'b', 'c', 'd', 'U', 'V', 'W', 'X', 'Y', 'e', 'f',
            'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', '8', '9', '+', '/'
    };

    public String Base64Encode(byte[] bytes) {
        StringBuilder res = new StringBuilder();
        for (int i = 0; i <= bytes.length - 1; i += 3) {
            byte[] enBytes = new byte[4];
            byte tmp = 0;
            for (int k = 0; k <= 2; k++) {
                if (i + k <= bytes.length - 1) {
                    enBytes[k] = (byte) (((bytes[i + k] & 255) >>> ((k * 2) + 2)) | tmp);
                    tmp = (byte) ((((bytes[i + k] & 255) << (((2 - k) * 2) + 2)) & 255) >>> 2);
                } else {
                    enBytes[k] = tmp;
                    tmp = 64;
                }
            }
            enBytes[3] = tmp;
            for (int k2 = 0; k2 <= 3; k2++) {
                if (enBytes[k2] <= 63) {
                    res.append(Base64ByteToStr[enBytes[k2]]);
                } else {
                    res.append('=');
                }
            }
        }
        return res.toString();
    }
}


class Decoder {
    /* 这是原本的码表
    private static final char[] toBase64 = {
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
    };
    */

    // 修改后的码表
    private static final char[] toBase64 = {
            'v', 'w', 'x', 'r', 's', 't', 'u', 'o', 'p', 'q', '3', '4', '5',
            '6', '7', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'y',
            'z', '0', '1', '2', 'P', 'Q', 'R', 'S', 'T', 'K', 'L', 'M', 'N',
            'O', 'Z', 'a', 'b', 'c', 'd', 'U', 'V', 'W', 'X', 'Y', 'e', 'f',
            'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', '8', '9', '+', '/'
    };

    private static final int[] fromBase64 = new int[256];

    static {
        Arrays.fill(fromBase64, -1);
        for (int i = 0; i < toBase64.length; i++)
            fromBase64[toBase64[i]] = i;
        fromBase64['='] = -2;
    }

    public byte[] decode(byte[] src) {
        byte[] dst = new byte[src.length];
        int ret = decode0(src, 0, src.length, dst);
        if (ret != dst.length) {
            dst = Arrays.copyOf(dst, ret);
        }
        return dst;
    }

    private int decodeBlock(byte[] src, int sp, int sl, byte[] dst, int dp, boolean isURL, boolean isMIME) {
        int[] base64 = fromBase64;
        int sl0 = sp + ((sl - sp) & ~0b11);
        int new_dp = dp;
        while (sp < sl0) {
            int b1 = base64[src[sp++] & 0xff];
            int b2 = base64[src[sp++] & 0xff];
            int b3 = base64[src[sp++] & 0xff];
            int b4 = base64[src[sp++] & 0xff];
            if ((b1 | b2 | b3 | b4) < 0) {    // non base64 byte
                return new_dp - dp;
            }
            int bits0 = b1 << 18 | b2 << 12 | b3 << 6 | b4;
            dst[new_dp++] = (byte)(bits0 >> 16);
            dst[new_dp++] = (byte)(bits0 >>  8);
            dst[new_dp++] = (byte)(bits0);
        }
        return new_dp - dp;
    }

    private int decode0(byte[] src, int sp, int sl, byte[] dst) {
        int[] base64 = fromBase64;
        int dp = 0;
        int bits = 0;
        int shiftto = 18;       // pos of first byte of 4-byte atom

        while (sp < sl) {
            if (shiftto == 18 && sp < sl - 4) {       // fast path
                int dl = decodeBlock(src, sp, sl, dst, dp, false, false);
                int chars_decoded = ((dl + 2) / 3) * 4;
                sp += chars_decoded;
                dp += dl;
            }
            if (sp >= sl) {
                break;
            }
            int b = src[sp++] & 0xff;
            if ((b = base64[b]) < 0) {
                if (b == -2) {
                    if (shiftto == 6 && (sp == sl || src[sp++] != '=') ||
                            shiftto == 18) {
                        throw new IllegalArgumentException(
                                "Input byte array has wrong 4-byte ending unit");
                    }
                    break;
                }
            }
            bits |= (b << shiftto);
            shiftto -= 6;
            if (shiftto < 0) {
                dst[dp++] = (byte)(bits >> 16);
                dst[dp++] = (byte)(bits >>  8);
                dst[dp++] = (byte)(bits);
                shiftto = 18;
                bits = 0;
            }
        }
        // reached end of byte array or hit padding '=' characters.
        if (shiftto == 6) {
            dst[dp++] = (byte)(bits >> 16);
        } else if (shiftto == 0) {
            dst[dp++] = (byte)(bits >> 16);
            dst[dp++] = (byte)(bits >>  8);
        } else if (shiftto == 12) {
            // dangling single "x", incorrectly encoded.
            throw new IllegalArgumentException(
                    "Last unit does not have enough valid bits");
        }

        return dp;
    }
}

OK,运行一遍之后,flag 就出来啦

相关推荐
huaiyanchen41 分钟前
chorme浏览器 您的连接不是私密连接
安全
安全方案3 小时前
政务安全运营核心能力模块
安全
aqymnkstkw4 小时前
2024年【电气试验】考试题库及电气试验模拟试题
大数据·c语言·人工智能·嵌入式硬件·安全
Lossya4 小时前
【自动化测试】常见的自动化遍历工具以及如何选择合适的自动化遍历工具
自动化测试·功能测试·测试工具·自动化·测试
xiaojiesec4 小时前
第157天: 安全开发-Python 自动化挖掘项目&SRC 目标&FOFA 资产&Web 爬虫解析库
python·安全
亿林科技网络安全5 小时前
阿里云盘照片事件!网络安全警钟长鸣
网络·安全·web安全
玄客)6 小时前
MACCMS 远程命令执行漏洞复现(CVE-2017-17733)
学习·安全
HinsCoder6 小时前
【渗透测试】——Upload靶场实战(1-5关)
笔记·学习·安全·web安全·渗透测试·测试·upload靶场
newxtc7 小时前
【天怡AI-注册安全分析报告-无验证方式导致安全隐患】
人工智能·安全