Android 逆向工程:防止apk被破解的方法总结

保证apk安全是非常重要的工作,这篇文件文件我们来总结如何防逆向工程。

  1. Java代码混淆
  2. 资源文件混淆
  3. 使用HTTPS,校验密钥
  4. URL签名
  5. DEX加固
  6. so文件校验签名

Java代码混淆

Android 工程本身就已经有代码混淆的方法,我们只需要按照要求对代码进行混淆即可。建议开发者除了对自己编写的代码混淆,也要对引入的第三方代码进行混淆,这样可以大大降低代码被破解的风险。

资源文件混淆

推荐使用微信开源的 AndResGuard 对资源文件进行混淆,不但可以降低资源文件被盗用的风险,还可以降低APP的大小,实际测试使用 AndResGuard 后,apk降低了2M大小。

混淆前

混淆前
混淆后

混淆后
使用HTTPS,校验证书

使用HTTPS可以非常有效防止被抓包,避免APP请求的内容被破解,但是单纯引入HTTPS是不足够的,还是可以被抓包的,必须要对证书进行校验。
《Android 逆向工程:Charles + Android 实现 HTTPS 抓包》
《Android 网络安全:如何避免 Okhttp 的 HTTPS 请求被抓包》

URL签名

使用HTTPS可以避免被抓包,但是如果别人知道了请求的URL和参数,就可以直接请求URL获取数据,所以我们非常有必要在请求的URL增加签名,服务器确认这个请求是从APP发起了,而不是别人伪造的。
《Android 网络安全:URL签名验证的实现API防篡改》

DEX加固

加固也避免dex文件直接暴露在apk压缩文件中,但是加固也有明确的缺点,可能会影响启动的速度,apk体积增大,无法使用补丁,依然可以脱壳逆向。所以加固已经不再被推荐使用,基本上大公司的apk都不会使用加固技术。

so文件校验签名

这个是针对apk中有编写了C++代码的项目,一些重要的算法我们通常是写在C++中,比如URL签名算法,因为写在Java就意味着容易被破解。但是so文件也通常存在被盗用的风险,我们有必要在C++层对apk的签名进行校验,避免apk被重新打包,so被盗用。

可以从这个方法中读取Application:ActivityThread.currentActivityThread().getApplication()

不用直接通过传入context到C++层校验,因为context是可以伪造的。

int get_apk_signature_hash(JNIEnv *env) {
    // 不直接使用传入的context,避免是mock出来的,通过ActivityThread.currentActivityThread().getApplication()方式获取Application
    jclass ActivityThreadClass = env->FindClass("android/app/ActivityThread");
    jmethodID currentActivityThreadMethodID = env->GetStaticMethodID(ActivityThreadClass,"currentActivityThread","()Landroid/app/ActivityThread;");
    jobject ActivityThreadObject = env->CallStaticObjectMethod(ActivityThreadClass,
                                                               currentActivityThreadMethodID);
    jmethodID getApplication = env->GetMethodID(ActivityThreadClass, "getApplication","()Landroid/app/Application;");
    jobject context = env->CallObjectMethod(ActivityThreadObject, getApplication);


    jclass ContextWrapperClass = env->FindClass("android/content/ContextWrapper");
    //this.getPackageManager();
    jmethodID getPackageManagerMethodID = env->GetMethodID(ContextWrapperClass, "getPackageManager","()Landroid/content/pm/PackageManager;");


    jobject packageManagerObject = env->CallObjectMethod(context, getPackageManagerMethodID);

    //this.getPackageName();
    jmethodID getPackageNameMethodID = env->GetMethodID(ContextWrapperClass, "getPackageName",
                                                        "()Ljava/lang/String;");
    jstring packageName = (jstring) env->CallObjectMethod(context, getPackageNameMethodID);
    const char *tmp = env->GetStringUTFChars(packageName, NULL);
    std::string packageName_ = tmp;
    // 校验apk的包名
    int findPackage = packageName_.find("com.xxx.xxx");
    if(findPackage < 0){
        return -4;
    }

    // packageManager->getPackageInfo(packageName, GET_SIGNATURES);
    jclass PackageManagerClass = env->FindClass("android/content/pm/PackageManager");
    jclass PackageInfoClass = env->FindClass("android/content/pm/PackageInfo");

    jmethodID getPackageInfoMethodID = env->GetMethodID(PackageManagerClass, "getPackageInfo",
                                                        "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
    jobject packageInfo = env->CallObjectMethod(packageManagerObject, getPackageInfoMethodID,
                                                packageName, 0x40); //GET_SIGNATURES = 64;
    jfieldID fid = env->GetFieldID(PackageInfoClass, "signatures",
                                   "[Landroid/content/pm/Signature;");
    jobjectArray signatures = (jobjectArray) env->GetObjectField(packageInfo, fid);
    jobject sig = env->GetObjectArrayElement(signatures, 0);

    ContextWrapperClass = env->GetObjectClass(sig);
    getPackageInfoMethodID = env->GetMethodID(ContextWrapperClass, "hashCode", "()I");
    int sig_value = (int) env->CallIntMethod(sig, getPackageInfoMethodID);
    return sig_value;
}

上面的C++代码对应的Java代码(简化思路)

int signaturesHash = getApplication().getPackageManager()
  .getPackageInfo("com.xxx.xxx",0).signatures.hashCode();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • Author:杨空明 Date:2018-8-17 一、前言 Android开发者常常面临的一个问题就是防破解、 ...
    问心2018阅读 27,862评论 4 66
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,204评论 0 17
  • 以前用第三方库VVDocumenter快速注释,但是自从Xcode升级到Xcode8就不能使用了,但是Xcode自...
    晴朗Nic阅读 1,953评论 2 0
  • 我有一颗玻璃心 轻易的就碎成了渣 没人能护得住却有人来摔碎 心就那么小一块肉 却总不停地挤进烦心事 不怪我现在装不...
    豆论中心阅读 190评论 0 0
  • 感恩昆明的天气,不冷不热,今天还是个好晴天,一早可以跑步锻炼,最近有几个亲友都做了子宫全切手术,还有一个和自己差不...
    顺路99阅读 152评论 0 0