正常先下载附件,解压后,先拖到 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 就出来啦