欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

对梆梆APP加固产品方案进行简要分析

最编程 2024-08-13 16:36:57
...

目录:

一、APP加固背景
二、APP加固前世今生
三、整体框架
四、详细流程分析
五、总结

一、APP加固背景

1.1、概述

Android系统是基于Linux开发己具有其开放性、*性的一种操作系统,现主要应用于移动设备,如手机、平板电脑和车载系统等。从2007年Google推出第一代Android操作系统至今已有10多年的时间,移动行业的市场份额与规模也在急速增长,现在几乎每人都在用或曾用过接触过Android智能手机。

1.2、安全问题

移动APP越来越普及,大多业务己放到APP中完 成,带来的安全隐患也越来越突出,漏洞、APP破解、恶意代码植入、广告植入、病毒木马、支付篡改、数据爬取等安全问题。
在发版前可通过对APP进行安全检测,加固APP可以提高安全性,解决大部分风险。

二、APP加固前世今生

2.1、APP加固发展与现状

App加固技术,前后经历了四代技术变更,保护级别在每一代都有所提升,破解成本也越来超高,发展流程大致如图2-1所示:

图2-1

第一代加固技术(动态加载):

第一代Android加固技术用于保护应用的逻辑不被逆向与分析,最早普遍在恶意软件中使用,其主要基于虚拟机提供的动态加载技术。
缺陷:只能对抗静态分析,无法对抗攻击者通过动态调试或自定义虚拟机进行脱壳。

第二代加固技术(内存加载):

第二代加固技术在APK修改方面已经完善,能做到对开发的零干扰。开发过程中不需要对应用做特殊处理,只需要在最终发布前进行保护即可。而为了实现这个零干扰的流程,Loader需要处理好Android的组件的生命周期。hook读写等方法,读写文件时进行加解密。
缺陷:只能对抗静态分析,无法对抗攻击者通过动态调试、内存dump或自定义虚拟机进行脱壳。

第三代加固技术(指令抽取):

第三代加固技术对Dex中代码的方法名和方法体进行分离,并对分离的方法体进行加密,通过Hook虚拟机方法,在程序运行的同时对方法进行解密运行。这种保护技术有效的防止了破解者通过内存dump的方式获取明文dex,将保护级别降到了函数级别。
缺陷:无法对抗攻击者通过自定义Android虚拟机进行脱壳。

第四代加固技术(java2C/VMP):

第四代加固技术对DEX中方法提取并转化成native方法后在底层进行注册,在调用native方法的同时在底层使用自定义解释器解释虚拟机指令。
java2c是将DEX文件内的函数被标记为native,内容被抽离并转换成一个符合JNI要求的动态库。动态库内通过JNI方法和Android系统进行交互。
缺陷:不论VMP还是java2c,都必须通过虚拟机提供的JNI接口与虚拟机进行交互,攻击者可以直接hook系统JNI接口、记录和分析执行流程,进而推断出完整DEX程序。

2.1、产品介绍

梆梆加固产品主要分为免费版与定制版,应用场景如下:

防逆向(Anti-RE) :

抽取classes.dex中的所有代码,剥离敏感函数功能,混淆关键逻辑代码,整体文件深度加密加壳,防止通过apktool,dex2jar,JEB等静态工具来查看应用的Java层代码,防止通过IDA,readelf等工具对so里面的逻辑进行分析,保护native代码。

防篡改(Anti-tamper)

每个代码文件、资源文件、配置文件都会分配唯一识别指纹,替换任何一个文件,将会导致应用无法运行,存档替换、病毒广告植入、内购破解、功能屏蔽等恶意行为将无法实施。

防调试(Anti-debug)

多重加密技术防止代码注入,彻底屏蔽游戏外挂、应用辅助工具,避免钓鱼攻击、交易劫持、数据修改等调试行为。

防窃取(Storage Encryption)

支持存储数据加密,提供输入键盘保护、通讯协议加密、内存数据变换、异常进程动态跟踪等安防技术,有效防止针对应用动、静态数据的捕获、劫持和篡改。 免费版与定制版本区别如图2-2所示:

图2-2

免费版本相对于定制化加固在安全能力方面要弱很多,我们分析的目标是定制版本的加固。

三、整体框架

梆梆定制版加固保护代码的方式主要分为两种,一是指令抽取,二是指令虚拟化,指令还原与虚拟化基本的流程与逻辑如图3-1所示:

图3-1

四、详细流程分析

4.1 加固后APP基本情况介绍

通过JEB反编译DUMP出来的DEX,方法指令抽取与指令虚拟化后如图4-1与4-2所示,方法指令抽取后的结果如图4-1所示:

图4-1

方法指令虚拟化后大部分函数是调用JniLib.cV解析执行的,最后一个参数是一个函数code索引,用来查找被虚拟化后的指令,其它是方法参数,如图4-2所示:

图4-2

4.2 So壳简单分析

壳的SO文件本身做了加壳保护,壳入口为.init_proc,如图4-3所示:

图4-3

解壳流程如大致为获取加密的代码基址->解密->修改属性,解密代码如下:

#define CODE_DATA_SIZE 0X00053DB3
#define CODE_DATA_OFFSET 0XE500
int DecCode(int copydata, unsigned int datasize, int codebufer, int* a4)
{
    index_2 = 0;
    v5 = 1;
    index = 0;
    v7 = 0;
    while (1)
    {
        while (1)
        {
            v8 = (v7 & 0x7F) == 0;
            if ((v7 & 0x7F) != 0)
                v7 *= 2;
            else
                v7 = *(unsigned __int8*)(copydata + index);
            if (v8)
            {
                v7 = 2 * v7 + 1;
                ++index;
            }
            if ((v7 & 0x100) == 0)
                break;
            codebyte = *(unsigned char*)(copydata + index++);
            *(unsigned char*)(codebufer + index_2++) = codebyte;
        }
        for (i = 1; ; i = v20 + ((unsigned int)(v7 << 23) >> 31))
        {
            v11 = (v7 & 0x7F) == 0;
            if ((v7 & 0x7F) != 0)
                v12 = 2 * v7;
            else
                v12 = *(unsigned __int8*)(copydata + index);
            if (v11)
            {
                v12 = 2 * v12 + 1;
                ++index;
            }
            v13 = (v12 & 0x7F) == 0;
            v14 = v12 << 23;
            if ((v12 & 0x7F) != 0)
                v15 = 2 * v12;
            else
                v15 = *(unsigned __int8*)(copydata + index);
            if (v13)
                v15 = 2 * v15 + 1;
            v16 = 2 * i;
            if (v13)
                ++index;
            v17 = v16 + (v14 >> 31);
            if ((v15 & 0x100) != 0)
                break;
            v18 = (v15 & 0x7F) == 0;
            if ((v15 & 0x7F) == 0)
                v15 = *(unsigned __int8*)(copydata + index);
            v19 = v17 + 0x7FFFFFFF;
            v7 = 2 * v15;
            if (v18)
                ++v7;
            v20 = 2 * v19;
            if (v18)
                ++index;
        }
        index_1 = index;
        if (v17 != 2)
            break;
        v22 = (v15 & 0x7F) == 0;
        if ((v15 & 0x7F) != 0)
            v15 *= 2;
        else
            v15 = *(unsigned __int8*)(copydata + index);
        if (v22)
            v15 = 2 * v15 + 1;
        if (v22)
            ++index;
        v23 = (v15 >> 8) & 1;
    LABEL_41:
        v25 = (v15 & 0x7F) == 0;
        if ((v15 & 0x7F) != 0)
            v7 = 2 * v15;
        else
            v7 = *(unsigned __int8*)(copydata + index);
        if (v25)
            v7 = 2 * v7 + 1;
        v26 = 2 * v23;
        if (v25)
            ++index;
        v27 = v26 + ((unsigned int)(v7 << 23) >> 31);
        if (!v27)
        {
            v28 = 1;
            do
            {
                v29 = (v7 & 0x7F) == 0;
                if ((v7 & 0x7F) != 0)
                    v30 = 2 * v7;
                else
                    v30 = *(unsigned __int8*)(copydata + index);
                if (v29)
                {
                    v30 = 2 * v30 + 1;
                    ++index;
                }
                v31 = (v30 & 0x7F) == 0;
                v32 = v30 << 23;
                if ((v30 & 0x7F) != 0)
                    v7 = 2 * v30;
                else
                    v7 = *(unsigned __int8*)(copydata + index);
                if (v31)
                    v7 = 2 * v7 + 1;
                v33 = 2 * v28;
                if (v31)
                    ++index;
                v28 = v33 + (v32 >> 31);
            } while ((v7 & 0x100) == 0);
            v27 = v28 + 2;
        }
        if (v5 > 0x500)
            v34 = v27 + 1;
        else
            v34 = v27;
        v35 = (unsigned char*)(codebufer + index_2 - v5);
        *(unsigned char*)(codebufer + index_2) = *v35;
        v36 = index_2 + 1;
        v37 = &v35[v34];
        v38 = codebufer + index_2;
        do
        {
            v39 = *++v35;
            *(unsigned char*)++v38 = v39;
        } while (v35 != v37);
        index_2 = v36 + v34;
    }
    v24 = *(unsigned __int8*)(copydata + index++) + ((v17 + 16777213) << 8);
    if (v24 != -1)
    {
        v23 = !(*(unsigned char*)(copydata + index_1) & 1);
        v5 = (v24 >> 1) + 1;
        goto LABEL_41;
    }
    *a4 = index_2;
    if (index == datasize)
        return 0;
    if (index >= datasize)
        return -201;
    return -205;
}
int __fastcall sub_D1F2EA88(int result, int a2)
{
    int v2; // r4
    unsigned int v3; // r12
    int v4; // r6
    int v5; // r7
    int v6; // r5
    int v7; // r2
    unsigned int v8; // r5
    int v9; // r3
    int v10; // r6
    unsigned int v11; // r1

    v2 = *(int*)(result + a2 + 8);
    v3 = *(int*)(result + a2 + 12);
    v4 = *(int*)(result + a2 + 16);
    v5 = *(int*)(result + a2 + 20);
    v6 = *(int*)(result + a2 + 24);
    if (*(int*)(result + a2) == 2146926590)
    {
        result += *(int*)(result + a2 + 4);
        v7 = 0;
        v8 = v3 + 4 * v6;
        v9 = 0;
        v10 = v5 + v4;
        while (v9 != v2)
        {
            v11 = *(int*)(result + 8 * v9);
            if (v11 >= v3 && v11 < v8)
                * (int*)(result + 8 * v9) = v10 + 4 * v7++;
            ++v9;
        }
    }
    return result;
}
4.3 DEX 指令抽取原理分析
JNI_OnLoad 分析

壳解密完成后执行到JNI_OnLoad方法,JNI_OnLoad主要完成几个重要步骤。
1、注册JNI方法,方法如下:

i()V
attach(Landroid/app/Application;Landroid/content/Context;)V
b(Landroid/content/Context;Landroid/app/Application;)V
c()V
d(Ljava/lang/String;)Ljava/lang/String;
e(Ljava/lang/Object;Ljava/util/List;Ljava/lang/String;)[Ljava/lang/Object;
f()[Ljava/lang/String;
g()[Ljava/lang/String;
h()[Ljava/lang/String;
n()[Ljava/lang/String;
j()[Ljava/lang/String;
k()Ljava/lang/String;
l()Ljava/lang/String;
m()Ljava/lang/String;

2、hook libc.so方法,hook如下方法:

__open
__openat
write
read
munmap
msync
__mmap2
pread64
ftruncate64
close

3、读取classes0.jar、classes.dgc并解密,代码逻辑如下:

//读取资源文件
seg131:CEE8E1B0 01 1C       MOVS            R1, R0
seg131:CEE8E1B2 06 98       LDR             R0, [SP,#0x18]
seg131:CEE8E1B4 D1 F7 A4 EA BLX             AAssetManager_fromJava_0
seg131:CEE8E1B8 31 1C       MOVS            R1, R6
seg131:CEE8E1BA 03 22       MOVS            R2, #3
seg131:CEE8E1BC D1 F7 A6 EA BLX             AAssetManager_open_0
seg131:CEE8E1C0 17 90       STR             R0, [SP,#0x5C]
seg131:CEE8E1C2 D1 F7 B0 EA BLX             AAsset_getBuffer_0
seg131:CEE8E1C6 1D 90       STR             R0, [SP,#0x74]
seg131:CEE8E1C8             ; START OF FUNCTION CHUNK FOR map_bufer
seg131:CEE8E1C8
seg131:CEE8E1C8             loc_CEE8E1C8                            ; CODE XREF: map_bufer+62↑j
seg131:CEE8E1C8 17 98       LDR             R0, [SP,#0x5C]          ; asset
seg131:CEE8E1CA D1 F7 A6 EA BLX             AAsset_getLength_0
seg131:CEE8E1CE 00 23       MOVS            R3, #0
seg131:CEE8E1D0 33 93       STR             R3, [SP,#0xCC]
seg131:CEE8E1D2 33 9A       LDR             R2, [SP,#0xCC]
seg131:CEE8E1D4 A4 4A       LDR             R2, =0xFFFFFC84

//解密代码
seg131:CEE72568             EXPORT Dec_classes_dgc_p1053869DF5E0CBA2E958A4809845A982
seg131:CEE72568             Dec_classes_dgc_p1053869DF5E0CBA2E958A4809845A982
seg131:CEE72568             var_248= -0x248
seg131:CEE72568             var_244= -0x244
seg131:CEE72568             var_240= -0x240
seg131:CEE72568             var_238= -0x238
seg131:CEE72568             var_11C= -0x11C
seg131:CEE72568             var_1C= -0x1C
seg131:CEE72568             arg_48=  0x48
seg131:CEE72568             arg_314=  0x314
seg131:CEE72568 F0 B5       PUSH            {R4-R7,LR}
seg131:CEE7256A 87 4C       LDR             R4, loc_CEE72788
seg131:CEE7256C 87 4A       LDR             R2, loc_CEE7278C
seg131:CEE7256E 88 4B       LDR             R3, loc_CEE72790
seg131:CEE72570 A5 44       ADD             SP, R4
seg131:CEE72572 01 90       STR             R0, [SP,#0x248+var_244]
seg131:CEE72574 80 20       MOVS            R0, #0x80
seg131:CEE72576 7A 44       ADD             R2, PC             
seg131:CEE72578 D6 58       LDR             R6, [R2,R3]
seg131:CEE7257A 00 91       STR             R1, [SP,#0x248+var_248]
seg131:CEE7257C
seg131:CEE7257C             loc_CEE7257C  
seg131:CEE7257C 80 02       LSLS            R0, R0, #0xA
seg131:CEE7257E 33 68       LDR             R3, [R6]
seg131:CEE72580 04 96       STR             R6, [SP,#0x248+var_238]
seg131:CEE72582 8B 93       STR             R3, [SP,#0x248+var_1C]
seg131:CEE72584 81 42       CMP             R1, R0
seg131:CEE72586 00 DD       BLE             loc_CEE7258A
seg131:CEE72588 00 90       STR             R0, [SP,#0x248+var_248]
seg131:CEE7258A
seg131:CEE7258A             loc_CEE7258A
seg131:CEE7258A 82 4B       LDR             R3, loc_CEE72794
seg131:CEE7258C 7B 44       ADD             R3, PC
seg131:CEE7258E 1B 68       LDR             R3, [R3]
seg131:CEE72590 00 2B       CMP             R3, #0
seg131:CEE72592 40 D1       BNE             loc_CEE72616
seg131:CEE72594 80 49       LDR             R1, loc_CEE72798
seg131:CEE72596 52 58       LDR             R2, [R2,R1]
seg131:CEE72598 12 68       LDR             R2, [R2]
seg131:CEE7259A 02 92       STR             R2, [SP,#0x248+var_240]
seg131:CEE7259C 80 22 52 00 MOVS            R2, #0x100
seg131:CEE725A0
seg131:CEE725A0             loc_CEE725A0
seg131:CEE725A0 4B A9       ADD             R1, SP, #0x248+var_11C
seg131:CEE725A2 5B 54       STRB            R3, [R3,R1]
seg131:CEE725A4
seg131:CEE725A4             loc_CEE725A4
seg131:CEE725A4 01 33       ADDS            R3, #1
seg131:CEE725A6 93 42       CMP             R3, R2
seg131:CEE725A8 FA D1       BNE             loc_CEE725A0
seg131:CEE725AA 00 23       MOVS            R3, #0
seg131:CEE725AC 0F 27       MOVS            R7, #0xF
seg131:CEE725AE 1D 1C       MOVS            R5, R3
seg131:CEE725B0 18 1C       MOVS            R0, R3
seg131:CEE725B2 9C 46       MOV             R12, R3
seg131:CEE725B4
seg131:CEE725B4             loc_CEE725B4
seg131:CEE725B4 02 9A       LDR             R2, [SP,#(dword_CEE727D4 - 0xCEE727CC)]
seg131:CEE725B6 46 5C       LDRB            R6, [R0,R1]
seg131:CEE725B8
seg131:CEE725B8             loc_CEE725B8               
seg131:CEE725B8 64 46       MOV             R4, R12
seg131:CEE725BA D2 5C       LDRB            R2, [R2,R3]
seg131:CEE725BC 01 33       ADDS            R3, #1
seg131:CEE725BE 92 19       ADDS            R2, R2, R6
seg131:CEE725C0 55 19       ADDS            R5, R2, R5
seg131:CEE725C2 FF 22       MOVS            R2, #0xFF
seg131:CEE725C4 15 40       ANDS            R5, R2
seg131:CEE725C6 DA 0F       LSRS            R2, R3, #0x1F
seg131:CEE725C8
seg131:CEE725C8             loc_CEE725C8 
seg131:CEE725C8 9F 42       CMP             R7, R3
seg131:CEE725CA
seg131:CEE725CA             loc_CEE725CA     
seg131:CEE725CA 62 41       ADCS            R2, R4
seg131:CEE725CC 52 42       NEGS            R2, R2
seg131:CEE725CE 13 40       ANDS            R3, R2
seg131:CEE725D0
seg131:CEE725D0             loc_CEE725D0
seg131:CEE725D0 4A 5D       LDRB            R2, [R1,R5]
seg131:CEE725D2 0A 54       STRB            R2, [R1,R0]
seg131:CEE725D4 80 22       MOVS            R2, #0x80
seg131:CEE725D6 01 30       ADDS            R0, #1
seg131:CEE725D8 4E 55       STRB            R6, [R1,R5]
seg131:CEE725DA 52 00       LSLS            R2, R2, #1
seg131:CEE725DC 90 42       CMP             R0, R2
seg131:CEE725DE E9 D1       BNE             loc_CEE725B4
seg131:CEE725DE         
seg131:CEE725DE
seg131:CEE725E0
seg131:CEE725E0
seg131:CEE725E0             loc_CEE725E0
seg131:CEE725E0 00 22       MOVS            R2, #0
seg131:CEE725E2 FF 27       MOVS            R7, #0xFF
seg131:CEE725E4 10 1C       MOVS            R0, R2
seg131:CEE725E6 01 99       LDR             R1, [SP,#4]
seg131:CEE725E8 00 9B       LDR             R3, [SP]
seg131:CEE725EA CC 18       ADDS            R4, R1, R3
seg131:CEE725EC             ; START OF FUNCTION CHUNK FOR DecString_5
seg131:CEE725EC
seg131:CEE725EC             loc_CEE725EC 
seg131:CEE725EC                    
seg131:CEE725EC A1 42       CMP             R1, R4
seg131:CEE725EE 00 D1       BNE             loc_CEE725F2
seg131:CEE725F0 BE E0       B               loc_CEE72770
seg131:CEE725F2
seg131:CEE725F2             loc_CEE725F2
seg131:CEE725F2 01 30       ADDS            R0, #1
seg131:CEE725F4
seg131:CEE725F4             loc_CEE725F4
seg131:CEE725F4 4B AE       ADD             R6, SP, #0x248+var_11C
seg131:CEE725F6 38 40       ANDS            R0, R7
seg131:CEE725F8 33 5C       LDRB            R3, [R6,R0]
seg131:CEE725FA
seg131:CEE725FA             loc_CEE725FA 
seg131:CEE725FA D2 18       ADDS            R2, R2, R3
seg131:CEE725FC 3A 40       ANDS            R2, R7
seg131:CEE725FE B5 5C       LDRB            R5, [R6,R2]
seg131:CEE72600 35 54       STRB            R5, [R6,R0]
seg131:CEE72602 B3 54       STRB            R3, [R6,R2]
seg131:CEE72604 35 5C       LDRB            R5, [R6,R0]
seg131:CEE72606 ED 18       ADDS            R5, R5, R3
seg131:CEE72608 3D 40       ANDS            R5, R7
seg131:CEE7260A 0B 78       LDRB            R3, [R1]
seg131:CEE7260C 75 5D       LDRB            R5, [R6,R5]
seg131:CEE7260E 6B 40       EORS            R3, R5
seg131:CEE72610 0B 70       STRB            R3, [R1]
seg131:CEE72612 01 31       ADDS            R1, #1
seg131:CEE72614 EA E7       B               loc_CEE725EC
seg131:CEE72616
seg131:CEE72616             loc_CEE72616 
seg131:CEE72616 01 2B       CMP             R3, #1
seg131:CEE72618 00 D0       BEQ             loc_CEE7261C
seg131:CEE7261A
seg131:CEE7261A             loc_CEE7261A
seg131:CEE7261A A9 E0       B               loc_CEE72770
seg131:CEE7261C
seg131:CEE7261C             loc_CEE7261C
seg131:CEE7261C 5E 4B       LDR             R3, loc_CEE72798
seg131:CEE7261E 06 A8       ADD             R0, SP, #0x248+var_230
seg131:CEE72620 D3 58       LDR             R3, [R2,R3]
seg131:CEE72620             ; END OF FUNCTION CHUNK FOR DecString_5
seg131:CEE72622 19 68       LDR             R1, [R3]
seg131:CEE72624 FF F7 48 FC BL              _Z33p70A9D4C5060D53A50764B3505C16E6F2P33p4ABCBA1E0CA9993D681F7E561B3486DCPh
seg131:CEE72628 00 98       LDR             R0, [SP]
seg131:CEE7262A EC F7 98 EF BLX             malloc_0
seg131:CEE7262E 01 99       LDR             R1, [SP,#4]
seg131:CEE72630 00 9A       LDR             R2, [SP]
seg131:CEE72632 06 1C       MOVS            R6, R0
seg131:CEE72634 EC F7 80 EF BLX             memcpy_0_
seg131:CEE72638 01 9D       LDR             R5, [SP,#4]
seg131:CEE7263A             loc_CEE7263A 
seg131:CEE7263A 00 9B       LDR             R3, [SP,#0x130+var_130]
seg131:CEE7263C
seg131:CEE7263C             loc_CEE7263C  
seg131:CEE7263C 01 9A       LDR             R2, [SP,#0x130+var_12C]
seg131:CEE7263E 5B 1B       SUBS            R3, R3, R5
seg131:CEE72640 D3 18       ADDS            R3, R2, R3
seg131:CEE72642 00 2B       CMP             R3, #(unk_13F0E000 - 0x13F0E000)
seg131:CEE72644
seg131:CEE72644             loc_CEE72644  
seg131:CEE72644 00 DC       BGT             loc_CEE72648
seg131:CEE72646 93 E0       B               loc_CEE72770
seg131:CEE72648             loc_CEE72648
seg131:CEE72648 27 AF       ADD             R7, SP, #0x130+var_94
seg131:CEE7264A 00 21
																				
															

推荐阅读