Android中通过进程注入技术改动广播接收器的优先级

前言

这个周末又没有吊事,在家研究了怎样通过进程的注入技术改动广播接收器的优先级。关于这个应用场景是非常多的。并且也非常重要。所以就非常急的去fixed了。

Android中的四大组件中有一个广播:Broadcast

关于它的相关知识能够转战:http://blog.csdn.net/jiangwei0910410003/article/details/19150705

我们这里就不做太多解释了,如今来看一下问题:


知识前提

这篇文章和我之前介绍一篇文章: Andrdoid中相应用程序的行为拦截实现方式之----从Java层进行拦截

内容和知识点非常类似,假设想看明确这篇文章的话。那么必须先看懂上面的一篇文章。否则非常难理解的。


知识点

1、进程注入技术

2、获取系统中全部应用的IntentFilter


问题

一、让我们自己定义的广播接收器的最先接收到系统发送的安装应用的广播

如今非常多安全应用都会注冊这个广播(360手机卫士、清理大师等)。广播中能够设置优先级的。

同一时候动态注冊的广播的优先级比静态注冊的广播的优先级高。

通过上面的知识我们能够这么做:

1、将自己的广播接收器注冊的优先级设置最高。通常是用最大值:Integer.MAX_VALUE

2、进行动态注冊广播(那么我们可能须要开启一个后台服务了,不然应用退出之后,这个接收器就没有了,是接收不到广播的)

通过上面的两步我们能够发现,我们自己的广播接收器的优先级应该比較高了。能够最先接收到广播了。


问题来了,你的应用这么做,那么其它应用也会这么做的,并且这样的做法的成本和代价不是非常高。

非常easy实现的。

好吧。那么我们如今该怎么办呢?

这时候我们就须要通过Android中的进程注入技术来进行拦截操作。然后去改动其它应用的广播接收器的优先级了

以下来看一下详细实现:

首先关于进程的注入技术这里就不做介绍了,假设有疑问的同学能够转战:

http://blog.csdn.net/jiangwei0910410003/article/details/40949475

注:另一个问题,我今天介绍的内容事实上和这篇文章非常类似,功能差点儿相同。所以强烈建议大家最好认真的把这篇文章从头到尾细致的读一遍,同一时候最后动手去实现以下,那么在来看这篇文章就简单多了。不然是非常费劲的。


这里我们须要注入到系统进程:system_server

然后在Java层自己定义一个Binder对象。在通过底层去替换系统的Binder。然后我们须要做的工作就是在Java中的自己定义的这个Binder对象的onTransact方法中进行操作


不多说了,先来看代码:

DemoInject3项目:

EntryClass.java

package com.demo.inject3;

import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;

/**
 * 
 * @author boyliang
 * 
 */
public final class EntryClass {

	private static final class ProxyActivityManagerServcie extends Binder {
		private static final String CLASS_NAME = "android.app.IActivityManager";
		private static final int s_broadcastIntent_code;

		private SmsReceiverResorter mResorter;

		static {
			if (ReflecterHelper.setClass(CLASS_NAME)) {
				s_broadcastIntent_code = ReflecterHelper.getStaticIntValue("BROADCAST_INTENT_TRANSACTION", -1);
			} else {
				s_broadcastIntent_code = -1;
			}
		}

		private IBinder mBinder;

		public ProxyActivityManagerServcie(IBinder binder) {
			Logger.init();
			mBinder = binder;
			mResorter = new SmsReceiverResorter(binder);
		}

		@Override
		protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {

			if (code == s_broadcastIntent_code) {
				Log.i("TTT", "broadcastintent:"+s_broadcastIntent_code);
				mResorter.updatePriority("com.demo.sms");
			}

			return mBinder.transact(code, data, reply, flags);
		}
	}

	public static Object[] invoke(int i) {
		IBinder activity_proxy = null;

		try {
			activity_proxy = new ProxyActivityManagerServcie(ServiceManager.getService("activity"));

			Log.i("TTT", ">>>>>>>>>>>>>I am in, I am a bad boy 3!!!!<<<<<<<<<<<<<<");
		} catch (Exception e) {
			e.printStackTrace();
		}

		return new Object[] { "activity", activity_proxy };
	}
}

核心的方法是onTransact:

这里须要推断一下code值。我们仅仅对广播的code做操作。关于这个code的值,在上面的提到的那篇文章中有详细介绍。

看到调用了mResorter.updatePriority方法。那么我们在来看一下mResorter变量的类型

SmsReceiverResorter.java

package com.demo.inject3;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;

import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;

final class SmsReceiverResorter {

	private static final String key = Intent.ACTION_PACKAGE_ADDED;
	
	private final String TAG = "TTT";
	private HashMap<String, IntentFilter[]> mActionToFilter;
	private Field mPackageNameField;

	@SuppressWarnings("unchecked")
	public SmsReceiverResorter(IBinder am) {
		Class<?> claxx = am.getClass();
		try {
			Field field = claxx.getDeclaredField("mReceiverResolver");
			field.setAccessible(true);
			Object mReceiverResolver = field.get(am);
			Log.i("TTT", "Binder:"+mReceiverResolver.getClass().getName());

			claxx = mReceiverResolver.getClass();
			
			field = claxx.getSuperclass().getDeclaredField("mActionToFilter");
			field.setAccessible(true);

			mActionToFilter = (HashMap<String, IntentFilter[]>) field.get(mReceiverResolver);
			Log.i("TTT", "mActionToFilter:"+mActionToFilter);
			
			if(mActionToFilter == null){
				return;
			}
			
			Log.i("TTT", "size:"+mActionToFilter.size());
			
			Log.i("TTT", "isHave:"+mActionToFilter.containsKey(key));
			
			IntentFilter[] filters_tmp = (IntentFilter[]) mActionToFilter.get(key);
			Log.i("TTT", "filters:"+filters_tmp);
			
			if (filters_tmp != null) {
				Log.i("TTT", "length:"+filters_tmp.length);
				for (int i=0;i<filters_tmp.length;i++) {
					String pkg = getPackageName(filters_tmp[i]);
					Log.i("TTT", "pkg:"+pkg);
				}
			}
			
			Set<Entry<String, IntentFilter[]>> sets = mActionToFilter.entrySet();
			Iterator<Entry<String, IntentFilter[]>> iterators = sets.iterator();
			while(iterators.hasNext()){
				Log.i("TTT", "key:"+iterators.next().getKey());
			}
			
			
		} catch (Exception e) {
			Log.e(TAG, e.toString());
		}
	}

	public void updatePriority(String target_pkg) {
		
		if (mActionToFilter != null) {
				IntentFilter[] filters_tmp = (IntentFilter[]) mActionToFilter.get(key);

				Log.i("TTT", "filters:"+filters_tmp);
				
				if (filters_tmp != null) {
					
					Log.i("TTT", "add package...");
					
					IntentFilter[] newFilters = new IntentFilter[1];

					for (int i=0;i<filters_tmp.length;i++) {
						String pkg = getPackageName(filters_tmp[i]);
						Log.i("TTT", "pkg:"+pkg+",priority:"+filters_tmp[i].getPriority());
						//现将全部的应用的广播接收器的优先级设置最低
						filters_tmp[i].setPriority(Integer.MIN_VALUE);
						if(pkg == null){
							continue;
						}
						if (target_pkg.equals(pkg)) {
							Log.i("TTT", "find pkg:"+pkg);
							//把我们自己的广播接收器的优先级设置最高
							filters_tmp[i].setPriority(Integer.MAX_VALUE);
							//newFilters[0] = filters_tmp[i];
							break;
						}
					}
					
					/*mActionToFilter.put(key, newFilters);
					
					IntentFilter[] filterss = mActionToFilter.get(key);
					for(int i=0;i<filterss.length;i++){
						Log.i("TTT", "new_pkg:"+getPackageName(filters_tmp[i]));
					}*/
					
				}
			}

	}

	private String getPackageName(IntentFilter filter) {
		
		if (mPackageNameField == null && filter != null) {
			Class<?> claxx = filter.getClass();
			try {
				mPackageNameField = claxx.getDeclaredField("packageName");
				mPackageNameField.setAccessible(true);
			} catch (Exception e) {
				Log.e(TAG, e.toString());
			}
		}
		
		String result = null;

		if (filter != null) {
			try {
				result = (String) mPackageNameField.get(filter);
			} catch (Exception e) {
				Log.e(TAG, e.toString());
			}
		}
		
		return result;
	}
}

这里面有两个重要的方法:

1、构造方法

public SmsReceiverResorter(IBinder am) {
		Class<?> claxx = am.getClass();
		try {
			Field field = claxx.getDeclaredField("mReceiverResolver");
			field.setAccessible(true);
			Object mReceiverResolver = field.get(am);
			Log.i("TTT", "Binder:"+mReceiverResolver.getClass().getName());

			claxx = mReceiverResolver.getClass();
			
			field = claxx.getSuperclass().getDeclaredField("mActionToFilter");
			field.setAccessible(true);

			mActionToFilter = (HashMap<String, IntentFilter[]>) field.get(mReceiverResolver);
			Log.i("TTT", "mActionToFilter:"+mActionToFilter);
			
			if(mActionToFilter == null){
				return;
			}
			
			Log.i("TTT", "size:"+mActionToFilter.size());
			
			Log.i("TTT", "isHave:"+mActionToFilter.containsKey(key));
			
			IntentFilter[] filters_tmp = (IntentFilter[]) mActionToFilter.get(key);
			Log.i("TTT", "filters:"+filters_tmp);
			
			if (filters_tmp != null) {
				Log.i("TTT", "length:"+filters_tmp.length);
				for (int i=0;i<filters_tmp.length;i++) {
					String pkg = getPackageName(filters_tmp[i]);
					Log.i("TTT", "pkg:"+pkg);
				}
			}
			
			Set<Entry<String, IntentFilter[]>> sets = mActionToFilter.entrySet();
			Iterator<Entry<String, IntentFilter[]>> iterators = sets.iterator();
			while(iterators.hasNext()){
				Log.i("TTT", "key:"+iterators.next().getKey());
			}
			
			
		} catch (Exception e) {
			Log.e(TAG, e.toString());
		}
	}

在构造方法中我们主要做的工作是获取mActionToFilter的值,它的定义:

private HashMap<String, IntentFilter[]> mActionToFilter;
这个值是干什么的呢?它是全部应用的IntentFilter的值,关于IntentFilter的作用能够自行百度。这里就不解释了。

这里的key是action的名称。

由于我们在动态注冊广播的时候。须要传递IntentFilter的。

所以。我们拿到这个值之后,就能够获取全部应用注冊广播的信息了

这个变量是非公开的,我们无法通过api去获取。那么不用说用反射去搞定它:

这个变量的定义是在  Android源代码文件夹\services\java\com\android\server\IntentResolver.java  

   /**
     * All filters that have been registered.
     */
    private final HashSet<F> mFilters = new HashSet<F>();

    /**
     * All of the MIME types that have been registered, such as "image/jpeg",
     * "image/*", or "{@literal *}/*".
     */
    private final ArrayMap<String, F[]> mTypeToFilter = new ArrayMap<String, F[]>();

    /**
     * The base names of all of all fully qualified MIME types that have been
     * registered, such as "image" or "*".  Wild card MIME types such as
     * "image/*" will not be here.
     */
    private final ArrayMap<String, F[]> mBaseTypeToFilter = new ArrayMap<String, F[]>();

    /**
     * The base names of all of the MIME types with a sub-type wildcard that
     * have been registered.  For example, a filter with "image/*" will be
     * included here as "image" but one with "image/jpeg" will not be
     * included here.  This also includes the "*" for the "{@literal *}/*"
     * MIME type.
     */
    private final ArrayMap<String, F[]> mWildTypeToFilter = new ArrayMap<String, F[]>();

    /**
     * All of the URI schemes (such as http) that have been registered.
     */
    private final ArrayMap<String, F[]> mSchemeToFilter = new ArrayMap<String, F[]>();

    /**
     * All of the actions that have been registered, but only those that did
     * not specify data.
     */
    private final ArrayMap<String, F[]> mActionToFilter = new ArrayMap<String, F[]>();

    /**
     * All of the actions that have been registered and specified a MIME type.
     */
    private final ArrayMap<String, F[]> mTypedActionToFilter = new ArrayMap<String, F[]>();
那么IntentResolver这个类的对象我们能够从哪里获取呢?

Android源代码文件夹\services\java\com\android\server\am\ActivityManagerService.java 中定义:

 /**
     * Resolver for broadcast intents to registered receivers.
     * Holds BroadcastFilter (subclass of IntentFilter).
     */
    final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
            = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
        @Override
        protected boolean allowFilterResult(
                BroadcastFilter filter, List<BroadcastFilter> dest) {
            IBinder target = filter.receiverList.receiver.asBinder();
            for (int i=dest.size()-1; i>=0; i--) {
                if (dest.get(i).receiverList.receiver.asBinder() == target) {
                    return false;
                }
            }
            return true;
        }

        @Override
        protected BroadcastFilter newResult(BroadcastFilter filter, int match, int userId) {
            if (userId == UserHandle.USER_ALL || filter.owningUserId == UserHandle.USER_ALL
                    || userId == filter.owningUserId) {
                return super.newResult(filter, match, userId);
            }
            return null;
        }

        @Override
        protected BroadcastFilter[] newArray(int size) {
            return new BroadcastFilter[size];
        }

        @Override
        protected boolean isPackageForFilter(String packageName, BroadcastFilter filter) {
            return packageName.equals(filter.packageName);
        }
    };

关于这个ActivityManagerService的对象,我们该怎么获取呢?我们知道它是一个系统的Service,还有系统的Service都是一个IBinder对象的。

ServiceManager.getService("activity")
这样的方式就能够获取到ActivityManagerService对象了。

详细代码在回去看一下EntryClass.java中初始化SmsReceiverResorter的部分内容。


好了,找到了它,以下的工作就是用反射去获取了,工作就简单了,这里就不多说了。


另一个重要的方法

2、改动优先级的方法:updatePriority

public void updatePriority(String target_pkg) {
		
		if (mActionToFilter != null) {
				IntentFilter[] filters_tmp = (IntentFilter[]) mActionToFilter.get(key);

				Log.i("TTT", "filters:"+filters_tmp);
				
				if (filters_tmp != null) {
					
					Log.i("TTT", "add package...");
					
					IntentFilter[] newFilters = new IntentFilter[1];

					for (int i=0;i<filters_tmp.length;i++) {
						String pkg = getPackageName(filters_tmp[i]);
						Log.i("TTT", "pkg:"+pkg+",priority:"+filters_tmp[i].getPriority());
						//现将全部的应用的广播接收器的优先级设置最低
						filters_tmp[i].setPriority(Integer.MIN_VALUE);
						if(pkg == null){
							continue;
						}
						if (target_pkg.equals(pkg)) {
							Log.i("TTT", "find pkg:"+pkg);
							//把我们自己的广播接收器的优先级设置最高
							filters_tmp[i].setPriority(Integer.MAX_VALUE);
							//newFilters[0] = filters_tmp[i];
							break;
						}
					}
					
					/*mActionToFilter.put(key, newFilters);
					
					IntentFilter[] filterss = mActionToFilter.get(key);
					for(int i=0;i<filterss.length;i++){
						Log.i("TTT", "new_pkg:"+getPackageName(filters_tmp[i]));
					}*/
					
				}
			}

	}
在这种方法中。传递进来一个包名(com.demo.sms)。这个包名事实上就是我们想将其优先级设置最高的一个应用。

我们首先通过key去获取相应的IntentFilter[]对象

IntentFilter[] filters_tmp = (IntentFilter[]) mActionToFilter.get(key);
这里的key是:

private static final String key = Intent.ACTION_PACKAGE_ADDED;
就是安装应用的相应的系统action名

那么我们就获取到了系统中全部注冊了安装应用的广播的应用了。

这里我们再次使用反射从IntentFilter对象中拿到包名。这样我们就能够进行过滤了。

for (int i=0;i<filters_tmp.length;i++) {
	String pkg = getPackageName(filters_tmp[i]);
	Log.i("TTT", "pkg:"+pkg+",priority:"+filters_tmp[i].getPriority());
	//现将全部的应用的广播接收器的优先级设置最低
	filters_tmp[i].setPriority(Integer.MIN_VALUE);
	if(pkg == null){
		continue;
	}
	if (target_pkg.equals(pkg)) {
		Log.i("TTT", "find pkg:"+pkg);
		//把我们自己的广播接收器的优先级设置最高
		filters_tmp[i].setPriority(Integer.MAX_VALUE);
		//newFilters[0] = filters_tmp[i];
		break;
	}
}
然后就開始遍历IntentFilter[]对象,首先将其说有的应用的广播接收器的优先级设置最低,直接调用IntentFilter的setPriority方法

然后发现假设当前的包名和我们须要设置优先级的包名一样,就将其优先级设置最高。


好了。上面的代码看完了。


以下来看一下我们自己定义的两个广播来进行測试:

第一个測试项目:com.demo.sms

我们看了上面的代码之后,会发现,这个项目就是我们须要改动最高优先级的应用

1、广播接收器:

package com.demo.sms;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public final class SmsReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(final Context context, Intent intent) {
		Log.i("TTT", "com.demo.sms:"+intent.getAction());
	}
}
打印一下action的值


2、后台用于动态注冊广播的service

package com.demo.sms;

import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;

public final class MyService extends Service {

	@Override
	public void onCreate() {
		super.onCreate();
		IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
		filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
		filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
		filter.addDataScheme("package");
		filter.setPriority(Integer.MIN_VALUE);
		registerReceiver(new SmsReceiver(), filter);
		filter = null;
	}
	
	@Override
	public IBinder onBind(Intent paramIntent) {
		return null;
	}

}
然后就开启这个service就能够了。这里我们将它的优先级设置最低


第二个測试项目:com.demo.smstrojan

这个项目的代码和上面的一个測试项目代码一模一样。就是相应的包名不一样以及注冊广播的优先级不一样。这里就不做解释了。

package com.demo.smstrojan;

import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;

public final class MyService extends Service {

	@Override
	public void onCreate() {
		super.onCreate();
		
		IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
		filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
		filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
		filter.addDataScheme("package");
		filter.setPriority(Integer.MAX_VALUE);
		registerReceiver(new SmsReceiver(), filter);
	}
	
	@Override
	public IBinder onBind(Intent paramIntent) {
		return null;
	}

}
这里我们将它的优先级设置最高

好了,我们如今首先执行这两个測试项目。后台的Service也起来了

在来执行一下上面的DemoInject3,

这个应用是不会执行有界面的,他仅仅是一个插件apk.

我们执行之后,获取DemoInject3.apk文件。


以下就開始进行注入了。

这里我不做演示了。操作步骤和:http://blog.csdn.net/jiangwei0910410003/article/details/40949475  这篇文章一模一样。


以下来看一下执行结果:

这里事实上还须要两个文件:libproxybinder.so和poison

这两个文件从上面提到的那篇文章中能够找到的


开启一个终端来查看一下系统进程的pid:

=>adb shell

=>ps |grep system_server



在开启一个终端进行注入:

=>adb shell

=>su

=> cd /data/data/

=>./poison /data/data/libproxybinder.so 579



在开启一个终端来打印log值。由于这个log值有点多:所以我们将log输出到一个文件里:

=>adb logcat -s TTT >log.txt

这里须要等待一会。然后我们退出这个命令(Ctrl+C),查看log.txt文件

=>start log.txt


这里的log.txt文件有点大,这里直截取一部分内容:

我们看到了打印的key值了。可是这里发现一个问题

isHave:false

这个值是在SmsReceiverResorter.java的构造方法中打印的:

Log.i("TTT", "isHave:"+mActionToFilter.containsKey(key));
这里的key是:android.intent.action.PACKAGE_ADDED,安装应用的系统action名

那么问题就来了,我们在两个測试项目中都进行注冊了这个action,为什么这里获取到的mActionToFilter中的key没有这个action呢?

这个纠结了我一天,最后才发现问题所在的。

我们在測试项目中注冊广播是:

IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
filter.setPriority(Integer.MIN_VALUE);
registerReceiver(new SmsReceiver(), filter);
发现有一个地方:就是IntentFilter中不仅加入了action值,另一个scheme的值,好吧,问题还得去看源代码:

还是在IntentResolver.java

我们看到另一个变量:mSchemeToFilter,用来存储scheme的IntentFilter的值。

那么继续来看一下IntentResolver类中的addFilter方法



发现到问题了:

这里有两个推断:

首先将IntentFilter加入到mSchemeToFilter变量中

然后推断IntentFilter中有没有scheme和mime,没有的话就将IntentFilter加入到mActionToFilter变量中

好吧,到这里我们就找到问题了,由于我们如今有scheme字段的,值是:package

那么我们注冊的IntentFilter就不会再mActionToFilter中。而是在mSchemeToFilter中。


问题找到了。以下我就開始改动DemoInject项目中的SmsReceiverResorter.java代码:

1)首先改动一下反射的字段

将以下代码:

field = claxx.getSuperclass().getDeclaredField("mActionToFilter");
改成:

field = claxx.getSuperclass().getDeclaredField("mSchemeToFilter");


2)在改动一下key值

将以下代码:

private static final String key = Intent.ACTION_PACKAGE_ADDED;
改成:

private static final String key = "package";
由于我们注冊的时候都是用的是这个值:package


我们再次执行DemoInject项目。得到DemoInject3.apk

然后再次进行操作(和上面的操作一样):

只是这里有一个问题,就是system_server进程仅仅能注入一次,所以假设在次进行注入操作的话,须要又一次启动设备了

等到设备重新启动之后。还要记得分别执行上面两个測试项目,然后我们随便安装一个应用,用于測试广播接收的

这时候我们在来看一下log.txt


这时候看到了isHave是true了



这时候,我们发现,com.demo.sms项目的优先级最高。其它的应用的优先级都是最低的。

我们还发现

com.demo.sms比com.demo.smstrojan先获取广播

我们看到上面的两个測试项目的代码:

com.demo.sms项目中的广播优先级设置最低

com.demo.smstrojan项目的广播优先级设置最高

所以正常情况下,应该是com.demo.smstrojan项目最先接收到广播的。

可是如今我们改动了优先级之后,com.demo.sms项目最先接收到广播

到这里我们的问题攻克了。能够将我们自己特定的应用的广播接收的优先级设置最高。让其最先接收到广播。


二、如今想特定的应用最先接收到广播之后,就不让其它应用在接收到这个广播了

可是问题还没有结束。如今还有这样的需求,假设我们如今想让一个应用最先接收到广播。之后就不让兴许的应用接收到这个广播了,有人说能够在这个特定的应用中终止这个广播,那个仅仅是对于有序广播来说的,如今假设是无序广播呢?我们该怎么操作呢?

事实上看懂了SmsReceiverResorter.java中的updatePriority方法,我们这里就easy改动了。

原理:我们能够将其它应用的IntentFilter删除,仅仅保留须要改动优先级的应用的IntentFilter就可以

实现:那么能够从新定义一个IntentFilter[]对象。然后将我们须要设置最先接收到广播的那个应用的IntentFilter加入进去,然后在put进map中

详细改动例如以下:

updatePriority方法:

public void updatePriority(String target_pkg) {
	
	if (mActionToFilter != null) {
			IntentFilter[] filters_tmp = (IntentFilter[]) mActionToFilter.get(key);

			Log.i("TTT", "filters:"+filters_tmp);
			
			if (filters_tmp != null) {
				
				Log.i("TTT", "add package...");
				
				IntentFilter[] newFilters = new IntentFilter[1];

				for (int i=0;i<filters_tmp.length;i++) {
					String pkg = getPackageName(filters_tmp[i]);
					Log.i("TTT", "pkg:"+pkg+",priority:"+filters_tmp[i].getPriority());
					if(pkg == null){
						continue;
					}
					if (target_pkg.equals(pkg)) {
						Log.i("TTT", "find pkg:"+pkg);
						newFilters[0] = filters_tmp[i];
						break;
					}
				}
				
				//从新覆盖IntentFilter[]
				mActionToFilter.put(key, newFilters);
				
				IntentFilter[] filterss = mActionToFilter.get(key);
				for(int i=0;i<filterss.length;i++){
					Log.i("TTT", "new_pkg:"+getPackageName(filters_tmp[i]));
				}
				
			}
		}

}

核心代码:

mActionToFilter.put(key, newFilters);
将我们新的IntentFilter[]对象去覆盖mActionToFilter中的指定key的对象。


其它地方不须要改动,再次执行

查看log.txt


这里看到了,我们上面代码打印新的IntentFilter[]

如今仅仅有一个

new_pkg:com.demo.sms

并且。我们在安装一个apk包。发现仅仅有com.demo.sms能够接收到广播了

而com.demo.smstrojan已经接收不到广播了

同一时候我们会发现曾经非常牛逼的360卫士如今也接收不到广播了,哈哈~~

我们没有操作前360卫士能够接收到这个安装广播:



我们操作之后。哈哈~~。没有拦截到。由于这个广播被我们手动的给干掉了

通知栏中没有通知了。


好吧,到这里我们算是彻底的做到了广播接收的独裁专政了。如今是能够设置特定的应用能接收到广播,并且无论这个广播是有序的还是无序的。我们都能够将其精巧,不让其它应用接收到。

说实话,这个问题攻克了。真的好开心好开心,特别是发现360如今也接收不到这个广播了。

心里特别爽。哈哈~~


项目下载

DemoInject项目下载

DemoSms项目(com.demo.sms)下载

DemoSms1项目(com.demo.smstrojan)下载


总结

关于这篇文章的研究意义在于我们能够控制特定的应用的广播接收器的优先级了,如今市面上有非常多应用都会接收系统发送的一些广播。那么每一个应用可能都会将自己的广播接收器的优先级设置最高,让自家的接收器最先接收到广播。

那么主动权就可控了,可是那些常规的方法貌似如今每一个应用都在用,所以假设想做到最牛逼的,那么仅仅能用非常规的方法了,那么这些非常规的方法也是须要一定代价的:设备必须root了。同一时候这么做从理论上来说就有点流氓了。

并且如今有一些恶意的apk,它须要接收到系统发送的短信广播。那么这时候他肯定希望自己最先收到这个短信了。然后把这个广播给终止了。

这时候就能够这么做了。


PS:

有的同学可能会有疑问,说我们这么做。那么其它家的应用应该也想到这么做了,是的。所以这里就须要强调一点:

这样的做法是非常流氓的,不合常规的。并且设备必须root,所以我们以后在做类似的功能的时候。不妨依照常规的方式去实

现。不要用非常规的方法,那些方法仅仅能骗骗小白用户。长期这样对于应用本身发展也是不利的。以上仅仅是我个人观点。




























posted @ 2016-02-04 11:01  mfrbuaa  阅读(285)  评论(0编辑  收藏  举报