拿到一款App(名字暂且该叫tangzhanglao),听说壳很厉害,于是好奇拿来研究一番。
用Apktool解压是没有反应的,猜测是做了针对性保护;拿不到AndroidManifest.xml怎么办?
用Jadx-gui直接解压,文件出来了,如下:
大体看一下,发现貌似是用爱加密加密的。但是,仔细分析一下,发现保护级别比之前的爱加密高多了;为何这么说,且听慢慢道来。
首先我们看下这里的AndroidManifest.xml,关键处如下:
可见加壳后的程序名为: android:name="p008s.p009h.p010e.p011l.p012l.ApplicationC0083S"
且: android:appComponentFactory="s.h.e.l.l.A"
我们看下ApplicationC0083S,部分代码如下:
从这里,往后就是常规爱加密壳保护的方法了;但是注意,这个壳的关键并不在这里,而是在解密程序之前还有一层保护;而且是动态保护的。关键就是上边的这个工厂类:AppComponentFactoryC0080A
首先说明一下:整个动态保护的关键,就是在爱加密壳之前又加了一层动态保护,这里的动态不是仅仅通过DEXclassloader来实现的,而是通过重写AppComponentFactory类,拦截了壳的整个解密过程,也就是说从壳程序加载一直到运行、解密整个过程都是被监控的;我们看下这个类的代码:
因为时间原因,仅仅做了静态分析;native层需要动态分析的;有时间再补充。
有错误之处,请大侠指正。
<application android:theme
=
"@style/AppTheme"
android:label
=
"@string/app_name"
android:icon
=
"@mipmap/ic_launcher"
android:name
=
"p008s.p009h.p010e.p011l.p012l.ApplicationC0083S"
android:allowBackup
=
"false"
android:supportsRtl
=
"true"
android:usesCleartextTraffic
=
"true"
android:roundIcon
=
"@mipmap/ic_launcher_round"
android:appComponentFactory
=
"s.h.e.l.l.A"
>
<uses
-
library android:name
=
"org.apache.http.legacy"
android:required
=
"false"
/
>
<activity android:theme
=
"@style/SplashActivityStyle"
android:name
=
"com.tangzhanglao.activity.splash.SplashActivity"
android:launchMode
=
"singleTask"
android:screenOrientation
=
"portrait"
>
<intent
-
filter
>
<action android:name
=
"android.intent.action.MAIN"
/
>
<category android:name
=
"android.intent.category.LAUNCHER"
/
>
<
/
intent
-
filter
>
<application android:theme
=
"@style/AppTheme"
android:label
=
"@string/app_name"
android:icon
=
"@mipmap/ic_launcher"
android:name
=
"p008s.p009h.p010e.p011l.p012l.ApplicationC0083S"
android:allowBackup
=
"false"
android:supportsRtl
=
"true"
android:usesCleartextTraffic
=
"true"
android:roundIcon
=
"@mipmap/ic_launcher_round"
android:appComponentFactory
=
"s.h.e.l.l.A"
>
<uses
-
library android:name
=
"org.apache.http.legacy"
android:required
=
"false"
/
>
<activity android:theme
=
"@style/SplashActivityStyle"
android:name
=
"com.tangzhanglao.activity.splash.SplashActivity"
android:launchMode
=
"singleTask"
android:screenOrientation
=
"portrait"
>
<intent
-
filter
>
<action android:name
=
"android.intent.action.MAIN"
/
>
<category android:name
=
"android.intent.category.LAUNCHER"
/
>
<
/
intent
-
filter
>
/
*
renamed
from
: s.h.e.l.l.S
*
/
这里是shells,不是shell A ;
public final
class
ApplicationC0083S extends Application {
……
/
*
renamed
from
: l ;注意这个布尔变量f170l,在整个壳的保护中很关键,是起开关作用的
*
/
public static boolean f170l
=
false;
……
public void onCreate() {
……
/
*
再看下onCreate()入口函数中,这个函数是壳解密的入口,是Native层的。
*
/
C0082N.m209ra(this,
"com.tangzhanglao.TangzhanglaoApplication"
);
if
(f172n !
=
null) {
}
super
.onCreate();
/
*
我们可以来到C0082N类看下;
*
/
public final
class
C0082N {
/
*
renamed
from
: al
*
/
public static native ClassLoader m205al(ClassLoader classLoader, ApplicationInfo applicationInfo, String
str
, String str2);
public static native byte[] b2b(byte[] bArr,
int
i);
/
*
renamed
from
: l
*
/
public static native boolean m206l(Application application, String
str
);
/
*
renamed
from
: m
*
/
public static native void m207m(String
str
,
int
i);
/
*
renamed
from
: r
*
/
public static native boolean m208r(Application application, String
str
);
/
*
renamed
from
: ra;这里把要解密的程序包名传进去
*
/
public static native boolean m209ra(Application application, String
str
);
/
*
renamed
from
: sa
*
/
public static native void m210sa(String
str
, String str2);
/
*
renamed
from
: s.h.e.l.l.S
*
/
这里是shells,不是shell A ;
public final
class
ApplicationC0083S extends Application {
……
/
*
renamed
from
: l ;注意这个布尔变量f170l,在整个壳的保护中很关键,是起开关作用的
*
/
public static boolean f170l
=
false;
……
public void onCreate() {
……
/
*
再看下onCreate()入口函数中,这个函数是壳解密的入口,是Native层的。
*
/
C0082N.m209ra(this,
"com.tangzhanglao.TangzhanglaoApplication"
);
if
(f172n !
=
null) {
}
super
.onCreate();
/
*
我们可以来到C0082N类看下;
*
/
public final
class
C0082N {
/
*
renamed
from
: al
*
/
public static native ClassLoader m205al(ClassLoader classLoader, ApplicationInfo applicationInfo, String
str
, String str2);
public static native byte[] b2b(byte[] bArr,
int
i);
/
*
renamed
from
: l
*
/
public static native boolean m206l(Application application, String
str
);
/
*
renamed
from
: m
*
/
public static native void m207m(String
str
,
int
i);
/
*
renamed
from
: r
*
/
public static native boolean m208r(Application application, String
str
);
/
*
renamed
from
: ra;这里把要解密的程序包名传进去
*
/
public static native boolean m209ra(Application application, String
str
);
/
*
renamed
from
: sa
*
/
public static native void m210sa(String
str
, String str2);
@TargetApi
(
28
)
/
*
renamed
from
: s.h.e.l.l.A
*
/
注意这里的shellA
public final
class
AppComponentFactoryC0080A extends AppComponentFactory {
private AppComponentFactory acf
=
null;
/
*
监控类
*
/
private AppComponentFactory orignACF
=
null;
private String orignAppName
=
"com.tangzhanglao.TangzhanglaoApplication"
;
private String orignName
=
"androidx.core.app.CoreComponentFactory"
;
/
*
为了本地AppComponentFactoryC0080A类实现必须应用原始类
*
/
private String packageName
=
"vip.mytangzhanglao"
;
private boolean supportInstantiateClassLoader
=
false;
/
*
监控开关
*
/
/
*
renamed
from
: al 这个类是写在native层的,具体功能没有分析
*
/
public static native ClassLoader m203al(ClassLoader classLoader, ApplicationInfo applicationInfo, String
str
, String str2);
/
函数getACF()
*
工厂类的典型方法,加载自身类,并实例化类,从此系统中有了两个类;获取本地实现类的指针,通过指针调用监控行为
*
/
public synchronized AppComponentFactory getACF(ClassLoader classLoader) {
if
(this.acf
=
=
null && this.orignName !
=
null && !this.orignName.equals("")) {
try
{
this.acf
=
(AppComponentFactory) classLoader.loadClass(this.orignName).newInstance();
} catch (Exception e) {
}
}
return
this.acf;
}
/
*
注意,因为重写了Activity,所以整个壳的行为过程都被拦截了
*
/
@Override
/
/
android.app.AppComponentFactory
public Activity instantiateActivity(ClassLoader classLoader, String
str
, Intent intent) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
if
(ApplicationC0083S.f170l) {
AppComponentFactory acf2
=
getACF(classLoader);
this.acf
=
acf2;
if
(acf2 !
=
null) {
return
this.acf.instantiateActivity(classLoader,
str
, intent);
/
*
if
体内,如果是壳程序,就拦截
*
/
}
}
return
super
.instantiateActivity(classLoader,
str
, intent);
}
/
*
如果不是壳程序,就放行
*
/
/
*
Application的加载被监控
*
/
@Override
/
/
android.app.AppComponentFactory
public Application instantiateApplication(ClassLoader classLoader, String
str
) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
if
(this.supportInstantiateClassLoader &&
str
.equals(
"s.h.e.l.l.S"
)) {
str
=
this.orignAppName;
}
else
if
(ApplicationC0083S.f170l) {
AppComponentFactory acf2
=
getACF(classLoader);
this.acf
=
acf2;
if
(acf2 !
=
null) {
return
this.acf.instantiateApplication(classLoader,
str
);
}
}
return
super
.instantiateApplication(classLoader,
str
);
}
/
*
这里ClassLoader类重置,才是实现动态保护的核心;一般App的加载是没有hook行为的;整个动态壳的保护,就是通过这里实现hook,进行解密、或者加密等功能的
*
/
@TargetApi
(
29
)
public ClassLoader instantiateClassLoader(ClassLoader classLoader, ApplicationInfo applicationInfo) {
if
(!this.supportInstantiateClassLoader) {
File
file
=
new
File
(applicationInfo.dataDir,
"files"
);
if
(!
file
.exists()) {
file
.mkdirs();
/
*
创建文件
*
/
}
ApplicationC0083S.f173p
=
file
.getAbsolutePath();
/
*
获取路径
*
/
ApplicationC0083S.f169f
=
applicationInfo.sourceDir;
/
*
重置需要解密文件
*
/
ApplicationC0083S.m216l(null);
/
*
这个函数就不具体贴代码了,就是设置系统信息的,获取解密需要的系统参数,为解密做准备
*
/
classLoader
=
C0082N.m205al(classLoader, applicationInfo, this.packageName, this.orignAppName);
/
*
native层解密
*
/
applicationInfo.className
=
this.orignAppName;
this.supportInstantiateClassLoader
=
true;
/
*
设置可以加载
*
/
}
if
(ApplicationC0083S.f170l) {
this.acf
=
getACF(classLoader);
if
(this.acf !
=
null) {
return
this.acf.instantiateClassLoader(classLoader, applicationInfo);
/
*
返回解密后的程序包
*
/
}
}
return
super
.instantiateClassLoader(classLoader, applicationInfo);
/
*
不是壳程序,就放行
*
/
}
/
*
ContentProvider组件监控
*
/
@Override
/
/
android.app.AppComponentFactory
public ContentProvider instantiateProvider(ClassLoader classLoader, String
str
) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
if
(ApplicationC0083S.f170l) {
AppComponentFactory acf2
=
getACF(classLoader);
this.acf
=
acf2;
if
(acf2 !
=
null) {
return
this.acf.instantiateProvider(classLoader,
str
);
}
}
return
super
.instantiateProvider(classLoader,
str
);
}
/
*
BroadcastReceiver 组件监控
*
/
@Override
/
/
android.app.AppComponentFactory
public BroadcastReceiver instantiateReceiver(ClassLoader classLoader, String
str
, Intent intent) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
if
(ApplicationC0083S.f170l) {
AppComponentFactory acf2
=
getACF(classLoader);
this.acf
=
acf2;
if
(acf2 !
=
null) {
return
this.acf.instantiateReceiver(classLoader,
str
, intent);
}
}
return
super
.instantiateReceiver(classLoader,
str
, intent);
}
/
*
Service组件监控
*
/
@Override
/
/
android.app.AppComponentFactory
public Service instantiateService(ClassLoader classLoader, String
str
, Intent intent) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
if
(ApplicationC0083S.f170l) {
AppComponentFactory acf2
=
getACF(classLoader);
this.acf
=
acf2;
if
(acf2 !
=
null) {
return
this.acf.instantiateService(classLoader,
str
, intent);
}
}
return
super
.instantiateService(classLoader,
str
, intent);
}
}
@TargetApi
(
28
)
/
*
renamed
from
: s.h.e.l.l.A
*
/
注意这里的shellA
public final
class
AppComponentFactoryC0080A extends AppComponentFactory {
private AppComponentFactory acf
=
null;
/
*
监控类
*
/
private AppComponentFactory orignACF
=
null;
private String orignAppName
=
"com.tangzhanglao.TangzhanglaoApplication"
;
private String orignName
=
"androidx.core.app.CoreComponentFactory"
;
/
*
为了本地AppComponentFactoryC0080A类实现必须应用原始类
*
/
private String packageName
=
"vip.mytangzhanglao"
;
private boolean supportInstantiateClassLoader
=
false;
/
*
监控开关
*
/
/
*
renamed
from
: al 这个类是写在native层的,具体功能没有分析
*
/
public static native ClassLoader m203al(ClassLoader classLoader, ApplicationInfo applicationInfo, String
str
, String str2);
/
函数getACF()
*
工厂类的典型方法,加载自身类,并实例化类,从此系统中有了两个类;获取本地实现类的指针,通过指针调用监控行为
*
/
public synchronized AppComponentFactory getACF(ClassLoader classLoader) {
if
(this.acf
=
=
null && this.orignName !
=
null && !this.orignName.equals("")) {
try
{
this.acf
=
(AppComponentFactory) classLoader.loadClass(this.orignName).newInstance();
} catch (Exception e) {
}
}
return
this.acf;
}
/
*
注意,因为重写了Activity,所以整个壳的行为过程都被拦截了
*
/
@Override
/
/
android.app.AppComponentFactory
public Activity instantiateActivity(ClassLoader classLoader, String
str
, Intent intent) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
if
(ApplicationC0083S.f170l) {
AppComponentFactory acf2
=
getACF(classLoader);
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!