1 Introduction
In the previous chapters, we learned [Android Framework series] Chapter 4 PMS principle We learned about the PMS principle, [Android Framework series] Chapter 9 AMS Hook to realize the login page jump We know that AMS can be intercepted by Hook to realize the unregistered Activity page Jump, let's try it in this chapter HookPMS实现广播的发送
.
Here we only briefly introduce the ideas and key codes of HookPMS. If you need to know more, please go to the project address at the end of the article to download and view.
Do students encounter the need to dynamically deliver components? By what means?
In the previous chapters, we analyzed PMS
the relevant principles, and briefly reviewed PMS
:
PMS
it is the package management system service, which is used to manage all package information, including application installation, uninstallation, update and analysis AndroidManifest.xml
. After the mobile phone is turned on, it will traverse all the files on the device /data/app/
and /system/app/
under the directory , and cache all the data ( , , etc.) information in the memory apk
by parsing all installed applications , and then provide them to other services.AndroidManifest.xml
xml
应用信息
权限
四大组件
AMS
Whether HookPMS
it is possible to realize apk
the distribution of dynamic components, in this chapter, we realize the call dynamic distribution by HookPMS
getting the ones in the PMS . **receivers(BroadcastReceiver)
apk
BroadcastReceiver
2 achieve
The four major components are managed in the PMS, and all the apks will be parsed and the information corresponding to the four major components will be saved to the corresponding collections Activity
, receivers
, probiders
, respectively services
.
/frameworks/base/core/java/android/content/pm/PackageParser.java
6460 @UnsupportedAppUsage
6461 public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
6462 @UnsupportedAppUsage
6463 public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
6464 @UnsupportedAppUsage
6465 public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
6466 @UnsupportedAppUsage
6467 public final ArrayList<Service> services = new ArrayList<Service>(0);
BroadcastReceiver
In this chapter, we have to get the collection of HookPMS receivers
.
2.1 Implementation ideas
- Download the one to be delivered first
apk
(we directly add it to the storage of the device here)- Decompress and parse the passed
apk
method into theHook
PMS
PMS
- Then by
HookPMS
getting the collection withBroadcastReceiver
the informationreceivers
apk
Use the name in the dynamic distributionBroadcastReceiver
as a parameter,HookPMS
and call it through the method, so as to achieve the purpose of this chapter.
2.2 Project structure
As we can see in the picture above, there are two modules, namely app and pmsbr.
app module:
HookPMS
The main logic is in PMSPackageParser
the class, which is used for apk
parsing and receiving broadcasts, and for operating .PMS
Hook
ClientActivity
HookPMS
pmsbr module:
This module
is actually just for packaging into a dynamic apk
, the internal one BroadcastReceiver
is used to verify HookPMS
whether the dynamic delivery can be apk
calledBroadcastReceiver
2.3 ClientActivity
package com.yvan.hookpms;
import android.Manifest;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.io.File;
/**
* @author yvan
* @date 2023/8/7
* @description
*/
public class ClientActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
checkPermission(this);
IntentFilter filter = new IntentFilter();
filter.addAction("com.yvan.client");
registerReceiver(new FinishBroadcastReceiver(), filter);
}
public static boolean checkPermission(
Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && activity.checkSelfPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
activity.requestPermissions(new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, 1);
}
return false;
}
public void registerBroaderCast(View view) {
PMSPackageParser pmsPackageParser = new PMSPackageParser();
try {
pmsPackageParser.parserReceivers(this,
new File(getFilesDir(), "input.apk"));
} catch (Exception e) {
e.printStackTrace();
}
}
public void sendBroaderCast(View view) {
Toast.makeText(this, "1.发送消息给server", Toast.LENGTH_SHORT).show();
view.postDelayed(() -> {
Intent intent = new Intent();
intent.setAction("com.yvan.server");
sendBroadcast(intent);
}, 3000);
}
static class FinishBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "3.收到server回复消息", Toast.LENGTH_SHORT).show();
}
}
}
activity_client.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ClientActivity">
<Button
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:onClick="registerBroaderCast"
android:text="注册广播" />
<Button
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:onClick="sendBroaderCast"
android:text="发送广播" />
</LinearLayout>
- After the page is opened, create a message
BroadcastReceiver
to receive the reply from , and the two buttons are "Register Broadcast" and "Send Broadcast".server
- Click "Register Broadcast": Parse the delivered apk (here it is packaged with the pmsbr module and placed
input.pak
in the private directory of data/data/com.yvan.hookpms/files of the device) through PMS, and then deliver theHookPMS
apk through implementation broadcast registration in . - Click "Send Broadcast": Send a message to the broadcast registered in 1 above
We mainly look at step 2 to register the broadcast, here is本章的重点HookPMS
2.4 PMSPackageParser
package com.yvan.hookpms;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import dalvik.system.DexClassLoader;
/**
* @author yvan
* @date 2023/8/7
* @description
*/
public class PMSPackageParser {
public void parserReceivers(Context context, File apkFile) throws Exception {
Class<?> packageParserClass = Class.forName("android.content.pm.PackageParser");
Method parsePackageMethod = packageParserClass.getDeclaredMethod("parsePackage",
File.class, int.class);
parsePackageMethod.setAccessible(true);
Object packageParser = packageParserClass.newInstance();
Object packageObj = parsePackageMethod.invoke(packageParser, apkFile,
PackageManager.GET_RECEIVERS);
packageObj.hashCode();
Field receiversField = packageObj.getClass().getDeclaredField("receivers");
List receivers = (List) receiversField.get(packageObj);
// AndroidManifest---> Package对象 描述信息
DexClassLoader dexClassLoader = new DexClassLoader(apkFile.getAbsolutePath(),
context.getDir("plugin", Context.MODE_PRIVATE).getAbsolutePath(),
null, context.getClassLoader());
// 动态注册
Class<?> componentClass = Class.forName("android.content.pm.PackageParser$Component");
Field intentsField = componentClass.getDeclaredField("intents");
for (Object receiverObject : receivers) {
String name = (String) receiverObject.getClass().getField("className")
.get(receiverObject);
// class --->对象
try {
BroadcastReceiver broadcastReceiver = (BroadcastReceiver) dexClassLoader.loadClass(name).newInstance();
List<? extends IntentFilter> filters = (List<? extends IntentFilter>)
intentsField.get(receiverObject);
for (IntentFilter filter : filters) {
context.registerReceiver(broadcastReceiver, filter);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
We see HookPMS
the following operations done:
Hook
What is the method ofPMS
parsing the class to get the objectandroid.content.pm.PackageParser
parsePackage()
Package
- Then get the collection stored
Package
in the objectBroadcastReceiver
receivers
- Load the dynamically delivered apk through the class loader
- Then traverse the collection of PMS
receivers
to find the broadcast registered in the delivered apk - Finally sign up for this broadcast.
The broadcast registered here is a dynamic delivery component input.apk
, PMSBroadcastReceiver
let's continue to look down
2.5 PMSBroadcastReceiver
package com.yvan.pmsbr;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;
/**
* @author yvan
* @date 2023/8/7
* @description
*/
public class PMSBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 收到你的信息了
Toast.makeText(context, "2.接收到client的消息", Toast.LENGTH_SHORT).show();
new Handler(Looper.getMainLooper()).postDelayed(() -> {
Intent intent1 = new Intent();
intent1.setAction("com.yvan.client");
context.sendBroadcast(intent1);
}, 3000);
}
}
PMSBroadcastReceiver
The main thing is to receive client
the broadcast from, and then client
reply a broadcast. After we FinishBroadcastReceiver
received server
the reply above, a Toast display pops up to indicate completion, sending and receiving input.apk
messages of dynamic delivery components.
3 summary
At this point we have completed the calling and calling of the entire dynamically delivered apk. Here we summarize a little bit: mainly
through HookPMS
the implementation of parsing the dynamically delivered apk apk
, storing the information PMS
in it , and then fetching the collection PMS
containing BroadcastReceiver
the information receivers
To, the program (Client) sends a broadcast to the broadcast (Server) defined in the dynamically delivered apk, the broadcast (Server) responds to the program (Client), and then the program (Client) receives the response (similar three-way handshake logic TCP
) . PMS
So as to achieve the purpose of this chapter Hook
.
The article only HookPMS
analyzes the core code ideas. Here is the project address . Friends can download and view it by themselves. Don’t forget to click Star, thank you! !