版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/
目标 app 简介

可以看到 app 中共有 4 种 Base64 算法。选中一个随机字符串,可以选择其中一种算法进行编码解码。
app地址:https://github.com/CYRUS-STUDIO/AndroidExample
标准 Java Base64 算法还原
使用 jadx 反编译 apk,搜索找到按钮的代码

因为 app 中 ui 是用 Compose 实现的,所有 ui 都是 Function,所以这里看到 Text 是一个 Function

在 Function f57lambda2 上按 X 找到调用该 Function 的地方

再继续找 m6044getLambda2$app_release 的上层调用是 rememberedValue6

可以看到 rememberedValue6 中实际是调用了Base64ActivityKt.Base64App…$lambda$16 方法
rememberedValue6 = new Function0() { // from class: com.cyrus.example.base64.Base64ActivityKt$$ExternalSyntheticLambda6
@Override // kotlin.jvm.functions.Function0
public final Object invoke() {
Unit Base64App$lambda$37$lambda$36$lambda$20$lambda$17$lambda$16;
Base64App$lambda$37$lambda$36$lambda$20$lambda$17$lambda$16 = Base64ActivityKt.Base64App$lambda$37$lambda$36$lambda$20$lambda$17$lambda$16(Base64App$lambda$4, mutableState2);
return Base64App$lambda$37$lambda$36$lambda$20$lambda$17$lambda$16;
}
};
$lambda$16 方法实现如下:
public static final Unit Base64App$lambda$37$lambda$36$lambda$20$lambda$17$lambda$16(String selected, MutableState selectedString$delegate) {
Intrinsics.checkNotNullParameter(selected, "$selected");
Intrinsics.checkNotNullParameter(selectedString$delegate, "$selectedString$delegate");
byte[] bytes = selected.getBytes(Charsets.UTF_8);
Intrinsics.checkNotNullExpressionValue(bytes, "getBytes(...)");
String encodeToString = Base64.encodeToString(bytes, 0);
Log.d("Base64", "标准 Base64 编码(Java): " + encodeToString);
selectedString$delegate.setValue(encodeToString);
return Unit.INSTANCE;
}
-
这里使用的是 Java 库中的 Base64.encodeToString 编码
-
日志标签 Base64
使用 adb logcat 过滤出 Base64 相关日志
adb logcat -s Base64
- 清空当前缓存日志:adb logcat -c
得到日志如下:
adb logcat -s Base64
--------- beginning of system
--------- beginning of main
03-10 02:03:10.277 21281 21281 D Base64 : 标准 Base64 编码(Java): ZVpvV3NBZndXd0k2ejU=
03-10 02:04:13.786 21281 21281 D Base64 : 标准 Base64 解码(Java): eZoWsAfwWwI6z5
使用 CyberChef 解密加密串,结果和原文是一样的,确定是标准 Base64 算法。

标准 C++ Base64 算法还原
加密串特征看起来就很像 Base64,因为都有 = 填充符号
adb logcat -s Base64
--------- beginning of system
--------- beginning of main
03-10 15:10:42.840 25364 25364 D Base64 : 标准 Base64 编码(C++): UWhENDdtSU10V1picA==
03-10 15:10:47.062 25364 25364 D Base64 : 标准 Base64 解码(C++): QhD47mIMtWZbp
03-10 15:10:55.533 25364 25364 D Base64 : 标准 Base64 编码(C++): VFRtYVFiN2Y2dA==
03-10 15:10:56.215 25364 25364 D Base64 : 标准 Base64 解码(C++): TTmaQb7f6t
使用 CyberChef 对比加密串发现就是标准的 Base64

自定义码表版 Base64 算法还原
1. 算法逆向分析
adb logcat -s Base64
--------- beginning of main
--------- beginning of system
03-10 15:19:46.455 25364 25364 D Base64 : 自定义Base64 编码后的字符串: ovjsvg4ZCwu1qw9dtu1h
03-10 15:19:54.629 25364 25364 D Base64 : 自定义Base64 解码后的字符串: 9RRTn3qe5AoCMMG
03-10 15:19:57.772 25364 25364 D Base64 : 自定义Base64 编码后的字符串: m2zttLfNnW
03-10 15:19:58.273 25364 25364 D Base64 : 自定义Base64 解码后的字符串: 3fSNQg7
03-10 15:19:59.839 25364 25364 D Base64 : 自定义Base64 编码后的字符串: D29eANfhrwHJA2u
03-10 15:20:00.223 25364 25364 D Base64 : 自定义Base64 解码后的字符串: woDjqGEhcke
使用 CyberChef 对比加密串发现解密出来的参数是不一样的

通过分析反编译的代码知道,C++ Base64 编码按钮实际调用的是下面的方法
public static final Unit Base64App$lambda$37$lambda$36$lambda$30$lambda$27$lambda$26(Function1 customEncode, String selected, MutableState selectedString$delegate) {
Intrinsics.checkNotNullParameter(customEncode, "$customEncode");
Intrinsics.checkNotNullParameter(selected, "$selected");
Intrinsics.checkNotNullParameter(selectedString$delegate, "$selectedString$delegate");
byte[] bytes = selected.getBytes(Charsets.UTF_8);
Intrinsics.checkNotNullExpressionValue(bytes, "getBytes(...)");
String str = (String) customEncode.invoke(bytes);
Log.d("Base64", "自定义Base64 编码后的字符串: " + str);
selectedString$delegate.setValue(

最低0.47元/天 解锁文章
1万+

被折叠的 条评论
为什么被折叠?



