攻防世界 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 就出来啦

相关推荐
2501_915373882 小时前
Redis线程安全深度解析:单线程模型的并发智慧
数据库·redis·安全
恰薯条的屑海鸥6 小时前
零基础在实践中学习网络安全-皮卡丘靶场(第十五期-URL重定向模块)
学习·安全·web安全·渗透测试·网络安全学习
Tipray20066 小时前
让敏感数据在流转与存储中始终守护在安全范围
安全
前端页面仔7 小时前
易语言是什么?易语言能做什么?
开发语言·安全
大话性能11 小时前
Mysql 百万级数据迁移实战笔记
测试
Guheyunyi14 小时前
监测预警系统重塑隧道安全新范式
大数据·运维·人工智能·科技·安全
IT科技那点事儿16 小时前
引领AI安全新时代 Accelerate 2025北亚巡展·北京站成功举办
人工智能·安全
乾巫宇宙国监察特使18 小时前
Python的设计模式
python·测试
恰薯条的屑海鸥20 小时前
零基础在实践中学习网络安全-皮卡丘靶场(第十四期-XXE模块)
网络·学习·安全·web安全·渗透测试
20242817李臻20 小时前
20242817李臻-安全文件传输系统-项目验收
数据库·安全