前期对app的Classloader理解的不够充分,现在慢慢能理解APP的加壳过程了。
主要是看Claasloader的各个作用,通过手敲代码理解classloader。
classloader相关文章,可以重点看看dexclassloader:
https://blog.csdn.net/fegus/article/details/124704467
https://gityuan.com/2017/03/19/android-classloader/
手写了一段代码,可以跟着试试
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import dalvik.system.DexClassLoader;
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ClassLoader classLoader = MainActivity.class.getClassLoader();
Log.i("test Classloader","app=>"+classLoader);
ClassLoader parentloader = null;
parentloader = classLoader.getParent();
while (parentloader!=null){
Log.i("test classloader","this"+classLoader+"parentclassloader"+parentloader);
classLoader = parentloader;
parentloader = classLoader.getParent();
}
Log.i("test","root=>"+classLoader);
可以在logcat中查看结果,看到各个层级的classloader
之前我们提到APP的加壳过程,实际上就是2个dex结合起来。一个是APP的dex,一个是加壳的dex,其中用到的就是dexclassloader
更想了解整体加固可以尝试看这篇文章
https://bbs.kanxue.com/thread-273293.htm#msg_header_h3_1
下面是我用dexclassloader的代码
Mainactivity
import android.Manifest;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.os.Build;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.content.pm.PackageManager;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import dalvik.system.DexClassLoader;
import androidx.annotation.NonNull;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CODE = 1;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ClassLoader classLoader = MainActivity.class.getClassLoader();
// Log.i("test Classloader","app=>"+classLoader);
// ClassLoader parentloader = null;
// parentloader = classLoader.getParent();
// while (parentloader!=null){
// Log.i("test classloader","this"+classLoader+"parentclassloader"+parentloader);
// classLoader = parentloader;
// parentloader = classLoader.getParent();
//
// }
// Log.i("test","root=>"+classLoader);
checkAndRequestPermissions();
Context context = this.getApplicationContext();
testClassLoader(context,"/sdcard/3.dex");
}
private void checkAndRequestPermissions() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE);
}
}
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 权限被授予,可以进行读写操作
} else {
// 权限被拒绝,处理相应逻辑
}
}
}
public void testClassLoader(Context context,String dexfilepath){
File optFile = context.getDir("opt_dex",0);
File libFile = context.getDir("lib_path",0);
ClassLoader parentClassloader = MainActivity.class.getClassLoader();
ClassLoader tmpClassloader = context.getClassLoader();
DexClassLoader dexClassLoader = new DexClassLoader(dexfilepath,optFile.getAbsolutePath(),libFile.getAbsolutePath(),MainActivity.class.getClassLoader());
Class<?> clazz = null;
try {
clazz =dexClassLoader.loadClass("com.r0ysue.testapp6.test02");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (clazz!=null){
try {
Method testFunction = clazz.getDeclaredMethod("testFun");
Object obj = clazz.newInstance();
testFunction.invoke(obj);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
AnroidManifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.r0ysue.testapp05">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.TestAPP05">
<activity android:name=".MainActivity">
android:hardwareAccelerated="false"
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
还有一个是
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 33
defaultConfig {
applicationId "com.r0ysue.testapp05"
minSdkVersion 21
targetSdkVersion 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.annotation:annotation:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.1'}
然后是3.dex实际上就是新建一个empty activity里面写入
将新建的这个make project后传输到手机里面
之后再运行原本的project就好了。可以看到已经加载成功
这里面还是有几个踩坑点的,第一个就是权限问题。刚开始是只有“媒体”权限,并不是/sdcard的权限。问了问GPT
根据GPT的指导才是设置成功
以往系列文章:
本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者及本公众号不为此承担任何责任。
欢迎关注公众号“呼啦啦安全”,原创技术文章第一时间推送。
原文始发于微信公众号(呼啦啦安全):安卓逆向系列补充(二)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论