查看原文
其他

Oo0代码混淆实现方法

Bin MT管理器v 2022-06-09

看过 MT 的 dex 文件的朋友们肯定都发现了它的所有类名、方法名、字段名都成了 Oo0 的各种混合体,这虽然不能起很好的保护作用,但还是可以恶心一下反编译你软件的人。



最开始我是通过给 Proguard 设置字典的方式来实现这个效果,也就是提前生成 N 个不同的 Oo0 组合保存到 txt 文件,然后在混淆配置中设置下即可。


不过这个方法存在一些局限性,首先你要手动生成字典文件,不能在每次混淆时随机生成名字,其次你要确保字典名字中数量要够用,否则又会变回 abcd 的组合了。


另外 Android Studio 默认 Pruguard 配置是不区分名称大小写,也就是像 OO|Oo|oO|oo 会被过滤得只剩下一个,其它三个由于在不区分大小写的情况下是相同的被删掉了。


最后我打起了修改 Proguard 源码的主意。


首先我们先去看看 Android Studio 使用的 Proguard 版本,Mac 上是在 Finder 的应用程序中找到 Android Studio,右键-显示包内容,接着进入

Contents/gradle/m2repository/net/sf/proguard/proguard-base


Windows 版本如果我没记错是先进入 Android Studio 的安装目录,然后再进入

gradle/m2repository/net/sf/proguard/proguard-base


最后你可以看到下面几个文件夹:



最高版本是5.3.3,所以现在我们去下载 Proguard-5.3.3 的源码,网址在 https://sourceforge.net/projects/proguard/files/proguard/


然后我们用 Intellij IDEA 来创建个 Java 项目,就取名 Oo0Proguard,创建完成后,解压 Proguard 的源码,把 src 文件夹复制过来。



由于我们只需要编译 proguard-base.jar 包给 Android Studio 使用,所以删掉先一些不需要的源代码,分别为下面五个包:

  • proguard/ant

  • proguard/gradle

  • proguard/gui

  • proguard/retrace

  • proguard/wtk


同时把 proguard/MANIFEST.MF 也删掉,最终效果:



现在来配置一下项目的 Artifacts,用来将源码打包成 jar。点击菜单 File - Project Structrue,然后如下图操作:



重命名输出的 jar 文件名为 proguard-base-5.3.3,操作如下:



最后点击 OK 保存设置。我们再点击菜单 Build - Build Artifacts - Oo0Projuard:jar - Build,然后就可以看到打包好的 jar 了。



OK,到这边我们完成了第一步,可以编译出原版的 proguard-base.jar 了。




现在开始对 Proguard 进行修改。我研究了半天源码才找到下面这些修改位置的,具体过程就不多说了,直接给你们。


修改版本名称

具体在 proguard.Proguard.VERSION,这样方便我们在 Android Studio 的编译日志中确定是否调用了我们修改的 Proguard。


强制名称混合大小写

Android Studio 默认的 Proguard 配置中有一条

-dontusemixedcaseclassnames

可以修改源码忽略掉这条规则。


定位到 proguard/obfuscate/ClassObfuscator.java 的 125 行

this.useMixedCaseClassNames = useMixedCaseClassNames;

修改为

this.useMixedCaseClassNames = true;


强制不保留内部类

Android Studio 默认的 Proguard 配置中有一条

-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod

其中 InnerClasses 和 EnclosingMethod 会导致混淆后可能出现 Oo0$1 之类的名称,可以修改源码忽略掉这两个值。


打开 proguard/ConfigurationParser.java,搜索KEEP_ATTRIBUTES_OPTION,给该行的 if 语句加对大括号,然后添加代码删掉 configuration.keepAttributes 内的 InnerClasses 和 EnclosingMethod,如下图,红色框出来的是添加的代码。



创建Oo0名称工厂

具体代码放在 Github 上,在 src/proguard/obfuscate/ONameFactory.java,其中我使用了 Random 来让每次运行生成的名称顺序不一样。


使用Oo0名称工厂

打开 proguard/obfuscate/ClassObfuscator.java,把全部

new SimpleNameFactory(useMixedCaseClassNames)

替换为

new ONameFactory()


打开 proguard/obfuscate/Obfuscator.java,把全部

new SimpleNameFactory()

替换为

new ONameFactory()


如果后续的 Proguard 版本出现变化,你们搜一下 SimpleNameFactory 的引用,把除了出现在 main 方法中的,其它全部都替换掉就行了。


修改源文件名

我们在编写应用时总难免会出现 bug,当程序奔溃后,主要是通过异常堆栈、源文件名、行号来定位代码,由于类名和源文件名基本一样,既然我们混淆了类名,自然也不希望源文件名暴露出去。


第一种方法是通过 Proguard 来删除源文件名,这样奔溃日志中也是看不到源文件名的,我们可以通过混淆时生成的 mapping.txt 文件来恢复。但使用这种方法的话,你需要保存各个版本的 mapping.txt 文件,相当不方便。


第二种方法是对源文件名进行加密,这样我们在奔溃日志中看到的是加密后的名称,只需要解密一下就行了,直接上修改方法:


定位到 proguard.obfuscate.SourceFileRenamer 的 visitSourceFileAttribute 方法,将方法中的全部代码替换为

String sourceFile = clazz.getString(sourceFileAttribute.u2sourceFileIndex);

if (!(clazz.getName() + ".java").endsWith(sourceFile))

    sourceFile = encrypt(sourceFile);

sourceFileAttribute.u2sourceFileIndex =

        new ConstantPoolEditor((ProgramClass) clazz).addUtf8Constant(sourceFile);


其中的 if 判断是过滤掉类名没变化的类,例如所有 Activity 的类名是不会被混淆的,其源文件名自然也不需要加密。encrypt 方法用于加密字符串,具体实现由你们自行设计。


然后我们在定位到 SourceFileRenamer 的唯一调用处,在 proguard/obfuscate/Obfuscator.java 的 467 行,把 if 判断注释掉。


到这边我们已完成了所有的修改,再次点击菜单 Build - Build Artifacts - Oo0Projuard:jar - Build,编译出 proguard-base-5.3.3.jar 文件。




现在来替换 Android Studio 的 Proguard,在这之前记得先退出 Android Studio,然后回到我们刚刚打开的目录



打开 5.3.3,把 proguard-base-5.3.3.jar 重命名为 proguard-base-5.3.3_bak.jar,再把我们编译好的 proguard-base-5.3.3.jar 复制进来。注意,当我们通过补丁升级 Android Studio 前需要还原文件,否则无法升级。



现在我们再次打开 Android Studio,打开项目,进入 app 下的 build.gradle,把 minifyEnabled 设为 true,开启 Proguard 混淆功能。



然后再打开 proguard-rules.pro 混淆配置文件,加入下面的内容:

# 修改包名

-repackageclass ""

# 忽略访问修饰符,配合上一句使用

-allowaccessmodification

# 不要删除源文件名和行号

-keepattributes SourceFile,LineNumberTable


配置完成,编译发行版的 APK,然后点击右下角的 Gradle Console,当开始混淆时会看到一行 ProGuard, version 5.3.3(Oo0),这是我修改后的版本名称,说明我修改的 Proguard 已经成功被 Android Studio 调用了。


编译完成后,点击菜单 Build- Analyze APK,打开我们刚刚编译好的 apk 文件,然后点击 classes.dex,就可以看到类名、方法名、字段名都被混淆成了各种 Oo0 了。



把 apk 复制到手机,使用 MT 打开里面的 classes.dex 文件,随便打开一个类,可以看到源文件名也更改成功了,这边我没有加密,只是在后面加了 -encrypt



全部代码已上传到 Github

https://github.com/L-JINBIN/Oo0Proguard

也可以点击下面的阅读原文查看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存