自定义混淆字典

文章首发于本人语雀 https://www.yuque.com/hysteria/oemyze/sooo5r
转载请注明出处。

一.背景

混淆

混淆一般用作压缩代码,增加逆向破解难度,大部分情况下只需要在配置文件中添加一些规则即可,常用的有规则有Android官方的,被反射的类,第三方、Js和webview相关的。
通常在app包的build.gradle下会有这样一段代码,用来标识是否开启混淆和混淆的规则文件。

 buildTypes {
        release {
            minifyEnabled true
            debuggable false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug {
            minifyEnabled false
            debuggable true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

其中proguard-android.txt是官方的混淆文件,主要用于四大组件,View等的keep,而proguard-rules.pro是我们自定义的规则,在使用三方库的时候需要添加对应的混淆规则在里面。

马甲包与混淆

通常一个App需要上线很多马甲包,而如果对马甲包进行单独的修改又较为麻烦,所以基本上所有的包都长一样,IOS有代码相似度对比的机制,如果两个包相似度超过一定阈值就会被判定为马甲包而导致不能上线,同样Google Play也有相应的机制,不太清楚国内的应用商店是否会有相应的判定工具,所以在代码相似度的方面做一定尝试。
对于代码相似度,官方的一些接口或者代码模板等等肯定不在监测范围内(或者说占比xx%都可以接受),而自己写的那部分又不能针对马甲包来做区分,所以一个可行的方案就是利用混淆。通常我们看到的混淆会把代码变成a,b,c,d这样的一些看不太懂的代码。而且这也不是随机的,意思就是对2个相同的包进行默认混淆,得到的结果是一样的。
但实际上混淆成什么样子是可以被决定的。

二. 混淆字典

混淆有很多参数,比如说这份规则,就有很多属性配置。


image.png

其中有这样的三个配置

# from proguard-rules.pro

#####方法名等混淆指定配置
-obfuscationdictionary ../proguard_keywords.txt
#####类名混淆指定配置
-classobfuscationdictionary ../proguard_keywords.txt
#####包名混淆指定配置
-packageobfuscationdictionary ../proguard_keywords.txt

可指定一个混淆字典,用来存放一些自定义的混淆词。
如上述我是在App的根目录下放了一个proguard_keywords.txt内容如下。

do
if
for
int
new
try
byte
case
char
else
goto
long
this
void
break
catch
class
const
final
float
short
super
throw
while
double
import
native
public
return
static
switch
throws
boolean
default
extends
finally
package
private
abstract
continue
strictfp
volatile
interface
protected
transient
implements
instanceof
synchronized

这是一些java的关键字,配置这样的字典就可以使混淆结果不是abcd这样的,同时也可以增加破译难度。
我这边写了一个demo来测试一下效果。

三. Demo

包下有一个Vibrates(震动工具类)UtilsManager,他们是工具类,而MainActivity里有一个按钮来触发震动

image.png

public class MainActivity extends AppCompatActivity {

    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = findViewById(R.id.btn);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Vibrates.setContext(MainActivity.this);
                Vibrates.startVibrate(1000);
                Toast.makeText(MainActivity.this, "点击按钮", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

首先测试环境打开混淆,然后进行运行。先运行一个不配置字典的。

 buildTypes {
        release {
            minifyEnabled true
            debuggable false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug {
            //打开测试环境混淆
            minifyEnabled true
            debuggable true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

然后在build里面找到这个包。看下classes.dex 里的内容


image.png

可以看到由于没有配置字典,混淆依然是abc形式的。
假如说我们配置Java关键字字典效果的话。


image.png

混淆的结果就是一些java关键字命名的了。
下面同样对这个包进行了反编译,实际上也是这样的。
image.png

四. 总结

通过这种方案,我们只需要给马甲包配置不同的字典就可以实现混淆后的代码相似度降低,有一定几率可以"骗过"代码相似度检验工具,从而上架。

你可能感兴趣的:(自定义混淆字典)