1 需要绕过反射限制(推荐 github FreeReflection)
2 从android.app.ApplicationPackageManager中拿mPM
3 从android.content.pm.IPackageManager$Stub$Proxy中拿mRemote
4 模拟调用transact
上代码:
public String get_install_pkg() {
try {
PackageManager packageManager = getBaseContext().getPackageManager();
// 第一步:Object Obj = getObjectField(packageManager, "mPM");
String spackageManagerClassName = packageManager.getClass().getName();
Log.i("testtest", "sPMClassName - " + spackageManagerClassName);
Class<?> clsApplicationPackageManager = Class.forName(spackageManagerClassName);
Field fieldmPM = clsApplicationPackageManager.getDeclaredField("mPM");
fieldmPM.setAccessible(true);
Object objmPM = fieldmPM.get(packageManager);
// 第二部:取binder
//IBinder mRemote = (IBinder) getObjectField(objmPM, "mRemote");
String smPMClassName = objmPM.getClass().getName();
Log.i("testtest", "smPMClassName - " + smPMClassName);
Class<?> clsmPM = Class.forName(smPMClassName);
Field fieldmRemote = clsmPM.getDeclaredField("mRemote");
fieldmRemote.setAccessible(true);
IBinder objmRemote = (IBinder)fieldmRemote.get(objmPM);
Log.i("testtest", "objmRemote - " + objmRemote.toString());
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
_data.writeInterfaceToken("android.content.pm.IPackageManager");
_data.writeLong(PackageManager.INSTALL_SCENARIO_DEFAULT); // MATCH_UNINSTALLED_PACKAGES INSTALL_SCENARIO_DEFAULT
_data.writeInt(android.os.Process.myUid());
//拿调用号
int TRANSACTION_getInstalledPackages = -1;
try {
Class<?> pkmIPCClazz = Class.forName("android.content.pm.IPackageManager$Stub");
Field field = pkmIPCClazz.getDeclaredField("TRANSACTION_getInstalledPackages");
assert field != null;
field.setAccessible(true);
TRANSACTION_getInstalledPackages = field.getInt(null);
} catch (Throwable e) {
e.printStackTrace();
return null;
}
//与服务端通信
boolean _status = objmRemote.transact(TRANSACTION_getInstalledPackages, _data, _reply, 0);
Log.i("testtest", "_status - " + String.valueOf(_status));
_reply.readException();
// 第三步:ParceledListSlice<PackageInfo> parceledList = ParceledListSlice.CREATOR.createFromParcel(_reply);
// 1 反射获取静态字段ParceledListSlice.CREATOR
Class<?> clsParceledListSlice = Class.forName("android.content.pm.ParceledListSlice");
Field fieldCREATOR = clsParceledListSlice.getDeclaredField("CREATOR");
fieldCREATOR.setAccessible(true);
Parcelable.Creator objCREATOR = (Parcelable.Creator)fieldCREATOR.get(null);
Log.i("testtest", "objCREATOR - " + objCREATOR.toString());
// 2 _reply.readTypedObject(ParceledListSlice.CREATOR);
Object objParceledListSlice = _reply.readTypedObject(objCREATOR);
Log.i("testtest", "objParceledListSlice - " + objParceledListSlice.toString());
// 3 反射调用List<PackageInfo> listPKG = parceledList.getList()
Method methodgetList = clsParceledListSlice.getDeclaredMethod("getList");
methodgetList.setAccessible(true);
List<PackageInfo> retgetList = (List)methodgetList.invoke(objParceledListSlice);
Log.i("testtest", "retgetList - " + retgetList.size());
StringBuffer sb = new StringBuffer();
for (PackageInfo pk:retgetList){
sb.append(pk.packageName);
sb.append("\n");
Log.i("testtest", "smPMClassName - " + pk.packageName);
}
_data.recycle();
_reply.recycle();
return sb.toString();
} catch (Throwable e) {
Log.i("testtest", "get_install_pkg error " + e);
}
return null;
}
效果: