int main( int argc, char *argv[] ) { const char *libname = "libui.so"; int classBuf[ 100 ]; int r1[ 10 ]; int r2[ 10 ]; int r3[ 10 ]; int jellybean = 0; int ( *unflatten )( int *r0, int *r1, int *r2, int *r3 ) = NULL; printf( "hello world\n" ); fflush( stdout ); void *handle = dlopen( libname, RTLD_NOW | RTLD_GLOBAL ); if( !handle ) { LOG_D( "error opening %s: %s\n", libname, dlerror() ); return -1; } bzero( classBuf, sizeof( classBuf ) ); bzero( r1, sizeof( r1 ) ); bzero( r2, sizeof( r2 ) ); bzero( r3, sizeof( r3 ) ); int ( *constructor )( int *r0 ) = dlsym( handle, "_ZN7android13GraphicBufferC2Ev" ); if( !constructor ) { LOG_D( "missing android::GraphicBuffer::GraphicBuffer(void)\n" ); return -1; } unflatten = dlsym( handle, "_ZN7android13GraphicBuffer9unflattenERPKvRjRPKiS4_" ); if( !unflatten ) { unflatten = dlsym( handle, "_ZN7android13GraphicBuffer9unflattenEPKvjPij" ); if( !unflatten ) { LOG_D( "missing android::GraphicBuffer::unflatten\n" ); return -1; } jellybean = 1; } constructor( classBuf ); // setup bad values int r1Ref = (int)(&r1[0]); // this must match r1[0] = 0x47424652; // size must be > 0x1f r2[0] = 0x20; // attempt to overflow r1[8] = 0x1000; r1[9] = 0xFF5; // make sure we error out on unpatched libs before getting to the point where we corrupt the heap r1[6] = 0x20; r1[7] = 0x20; int ret = 0; if( !jellybean ) { ret = unflatten( classBuf, &r1Ref, r2, r3 ); } else { int * val = (int*)(r2[0]); ret = unflatten( classBuf, r1, val, r3 ); } // -12 = unpatched 4.4.2 // -22 = patches 5.1.1 switch( ret ) { case -ENOMEM: printf( "unpatched\n" ); break; case -EINVAL: printf( "patched\n" ); break; default: printf( "test is broken ret: %d (%08x)\n", ret, ret ); break; } return 0; }
int checkGraphicsBufferVuln(int v ) { const char *libname = "libui.so"; int classBuf[ 100 ]; int r1[ 20 ]; int r2[ 10 ]; int r3[ 10 ]; int r4[ 10 ];// r4 is necessary for marchmellow int ( *unflatten )( int *r0, int *r1, int *r2, int *r3, int *r4 ) = NULL; void *handle = dlopen( libname, RTLD_NOW | RTLD_GLOBAL ); if( !handle ) { printf( "error opening %s: %s\n", libname, dlerror() ); return -1; } bzero( classBuf, sizeof( classBuf ) ); bzero( r1, sizeof( r1 ) ); bzero( r2, sizeof( r2 ) ); bzero( r3, sizeof( r3 ) ); bzero( r4, sizeof( r4 ) ); int ( *constructor )( int *r0 ) = dlsym( handle, "_ZN7android13GraphicBufferC2Ev" ); if( !constructor ) { printf( "missing android::GraphicBuffer::GraphicBuffer(void)\n" ); return -1; } unflatten = dlsym( handle, "_ZN7android13GraphicBuffer9unflattenERPKvRjRPKiS4_" ); if( !unflatten ) { unflatten = dlsym( handle, "_ZN7android13GraphicBuffer9unflattenEPKvjPij" ); if( !unflatten ) { printf( "missing android::GraphicBuffer::unflatten\n" ); return -1; } } constructor( classBuf ); // setup bad values int r1Ref = (int)(&r1[0]); int ret = 0; switch( v ) { case JELLYBEAN: SetupBufferJ( r1, r2 ); ret = unflatten( classBuf, r1, (int*)r2[0], r3, r4 ); break; case KITKAT_AND_LOLLIPOP: SetupBufferKL( r1, r2 ); ret = unflatten( classBuf, &r1Ref, (int*)r2, r3, r4 ); break; case MARSHMELLOW: SetupBufferM( r1, r2 ); r3[0] = 0x20; ret = unflatten( classBuf, &r1Ref, (int*) r2, r3, r4 ); break; default: printf( "unsupported OS version.\n" ); return -1; } // -12 = unpatched 4.4.2 // -22 = patches 5.1.1 switch( ret ) { case -ENOMEM: printf( "unpatched\n" ); return 1; case -EINVAL: printf( "patched\n" ); return 0; default: printf( "test is broken ret: %d (%08x)\n", ret, ret ); if(ret == 0 || ret == 1){ return -1; }else{ return ret; } } }