-
-
[原创]某不知名App越狱检测
-
2022-9-11 16:41 19046
-
1.目标
此篇文本为入门文章,大家莫抱过多期望。此文章的目的是教大家如何从UI入手,去定位自己想要的东西。
2.操作环境
mac系统
frida-ios-dump:砸壳
已越狱iOS设备:脱壳及frida调试
IDA Pro:静态分析
3.流程
寻找切入点
启动App后,界面如下图:
分析过程
从界面可以看出,App检测到越狱后,会弹出一个弹窗,文案为越狱手机存在安全风险,做iOS开发的都知道,最终这文案显示前,会调用UILabel类的setText:方法。我们trace该方法并打印堆栈:
js代码:
1 2 3 4 5 6 7 8 9 10 | { onEnter(log, args, state) { log(` - [UILabel setText:${new ObjC. Object (args[ 2 ])}]`); log( 'UILabel setText called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE) . map (DebugSymbol.fromAddress).join( '\n' ) + '\n' ); }, onLeave(log, retval, state) { } } |
关键日志如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | - [UILabel setText:越狱手机存在安全风险] UILabel setText called from : 0x1eaa7d0f4 UIKitCore! - [_UIAlertControllerView _updateMessageLabelContents] 0x1eaa756f8 UIKitCore! - [_UIAlertControllerView _prepareMesssageLabel] 0x1eaa750f8 UIKitCore! - [_UIAlertControllerView _prepareViewsAndAddConstraints] 0x1eaa75048 UIKitCore! - [_UIAlertControllerView setAlertController:] 0x1eaa61740 UIKitCore! - [UIAlertController loadView] 0x1ead35ed8 UIKitCore! - [UIViewController loadViewIfRequired] 0x1ead36628 UIKitCore! - [UIViewController view] 0x1ead4ddd4 UIKitCore! - [UIViewController _setPresentationController:] 0x1ead461f4 UIKitCore! - [UIViewController _presentViewController:modalSourceViewController:presentationController:animationController:interactionController:completion:] 0x1ead47ccc UIKitCore! - [UIViewController _presentViewController:withAnimationController:completion:] 0x1ead4a3a8 UIKitCore!__63 - [UIViewController _presentViewController:animated:completion:]_block_invoke 0x1ead4a8a4 UIKitCore! - [UIViewController _performCoordinatedPresentOrDismiss:animated:] 0x1ead4a300 UIKitCore! - [UIViewController _presentViewController:animated:completion:] 0x1ead4a560 UIKitCore! - [UIViewController presentViewController:animated:completion:] 0x10128253c App! 0xd253c ( 0x1000d253c ) 0x1be344a38 libdispatch.dylib!_dispatch_call_block_and_release |
使用frida-ios-dump砸壳后,再使用IDA Pro编译ipa文件。
跳转到内存0x1000d253c位置
再按F5:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | __int64 __fastcall sub_1000D24D4(_QWORD * a1) { void * v1; / / x19 __int64 v2; / / x20 void * * v4; / / [xsp + 8h ] [xbp - 38h ] __int64 v5; / / [xsp + 10h ] [xbp - 30h ] __int64 (__fastcall * v6)(); / / [xsp + 18h ] [xbp - 28h ] void * v7; / / [xsp + 20h ] [xbp - 20h ] __int64 v8; / / [xsp + 28h ] [xbp - 18h ] v1 = (void * )a1[ 4 ]; v2 = a1[ 5 ]; v4 = _NSConcreteStackBlock; v5 = 3254779904LL ; v6 = sub_1000D2554; v7 = &unk_101A29970; v8 = objc_retain(a1[ 6 ]); objc_msgSend(v1, "presentViewController:animated:completion:" , v2, 1LL , &v4); return objc_release(v8); } |
查找sub_1000D24D4函数的交叉引用,一层一层往上找,最终找到如下函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | void __cdecl - [UIViewController XXX_presentViewController:presentType:presentCompletionHandler:dismissCompleteHandler:](UIViewController * self , SEL a2, id a3, unsigned __int64 a4, id a5, id a6) { id v6; / / x21 id v7; / / x20 UIViewController * v8; / / x24 void * v9; / / x19 __int64 v10; / / x20 __int64 v11; / / x21 void * v12; / / x0 __int64 v13; / / x22 dispatch_semaphore_t v14; / / x23 void * v15; / / x0 void * v16; / / x24 void * v17; / / x0 void * v18; / / x0 void * v19; / / x27 void * v20; / / x0 __int64 v21; / / x28 void * v22; / / x0 void * v23; / / x0 void * v24; / / x25 void * v25; / / x0 __int64 v26; / / x26 __int64 v27; / / [xsp + 8h ] [xbp - A8h] void * * v28; / / [xsp + 10h ] [xbp - A0h] __int64 v29; / / [xsp + 18h ] [xbp - 98h ] __int64 (__fastcall * v30)(__int64); / / [xsp + 20h ] [xbp - 90h ] void * v31; / / [xsp + 28h ] [xbp - 88h ] __int64 v32; / / [xsp + 30h ] [xbp - 80h ] __int64 v33; / / [xsp + 38h ] [xbp - 78h ] __int64 v34; / / [xsp + 40h ] [xbp - 70h ] UIViewController * v35; / / [xsp + 48h ] [xbp - 68h ] __int64 v36; / / [xsp + 50h ] [xbp - 60h ] __int64 v37; / / [xsp + 58h ] [xbp - 58h ] v6 = a6; v7 = a5; v8 = self ; v9 = (void * )objc_retain(a3); v10 = objc_retain(v7); v11 = objc_retain(v6); v37 = 0LL ; v12 = objc_msgSend( v9, "aspect_hookSelector:withOptions:usingBlock:error:" , "viewDidDisappear:" , 0LL , &off_101A2BF98, &v37); objc_unsafeClaimAutoreleasedReturnValue(v12); v13 = objc_retain(v37); if ( !v13 ) { v14 = dispatch_semaphore_create( 0LL ); v28 = _NSConcreteStackBlock; v29 = 3254779904LL ; v30 = sub_1000D23A0; v31 = &unk_101A2BFB8; v32 = objc_retain(v9); v33 = objc_retain(v11); v27 = objc_retain(v14); v34 = v27; v35 = v8; v36 = objc_retain(v10); v15 = objc_msgSend(&OBJC_CLASS___NSBlockOperation, "blockOperationWithBlock:" , &v28); v16 = (void * )objc_retainAutoreleasedReturnValue(v15); v17 = objc_msgSend((void * )qword_101F71BF8, "operations" ); v18 = (void * )objc_retainAutoreleasedReturnValue(v17); v19 = v18; v20 = objc_msgSend(v18, "lastObject" ); v21 = objc_retainAutoreleasedReturnValue(v20); objc_release(v21); objc_release(v19); if ( v21 ) { v22 = objc_msgSend((void * )qword_101F71BF8, "operations" ); v23 = (void * )objc_retainAutoreleasedReturnValue(v22); v24 = v23; v25 = objc_msgSend(v23, "lastObject" ); v26 = objc_retainAutoreleasedReturnValue(v25); objc_msgSend(v16, "addDependency:" , v26); objc_release(v26); objc_release(v24); } objc_msgSend((void * )qword_101F71BF8, "addOperation:" , v16); objc_release(v16); objc_release(v36); objc_release(v34); objc_release(v33); objc_release(v32); objc_release(v27); } objc_release(v13); objc_release(v11); objc_release(v10); objc_release(v9); } |
接下来,同时跟踪UILabel的setText:方法和UIViewController的XXX_presentViewController:presentType:presentCompletionHandler:dismissCompleteHandler:方法,获取到日志如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | - [UIViewController XXX_presentViewController: 0x104928e00 presentType: 0x1 presentCompletionHandler: 0x16ec4e5a8 dismissCompleteHandler: 0x16ec4e580 ] UIViewController XXX_presentViewController called from : 0x1012b9fdc App! + [XXXAlertPresentController presentAlertController:presentCompletionHandler:dismissCompleteHandler:] 0x1012d464c App! - [LaunchingViewController start] 0x1012d3360 App! 0x123360 ( 0x100123360 ) 0x1be3457d4 libdispatch.dylib!_dispatch_client_callout 0x1be2f3c1c libdispatch.dylib!_dispatch_lane_barrier_sync_invoke_and_complete 0x1012d3310 App! 0x123310 ( 0x100123310 ) 0x1012b9978 App! 0x109978 ( 0x100109978 ) 0x1eb76ad1c UIKitCore! - [UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] 0x1eb741a74 UIKitCore! - [UIViewAnimationState sendDelegateAnimationDidStop:finished:] 0x1eb742048 UIKitCore! - [UIViewAnimationState animationDidStop:finished:] 0x1c2e573c8 QuartzCore!CA::Layer::run_animation_callbacks(void * ) 0x1be3457d4 libdispatch.dylib!_dispatch_client_callout 0x1be2f3008 libdispatch.dylib!_dispatch_main_queue_callback_4CF$VARIANT$mp 0x1be898b20 CoreFoundation!__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ 0x1be893a58 CoreFoundation!__CFRunLoopRun 0x1be892fb4 CoreFoundation!CFRunLoopRunSpecific - [UILabel setText:您的设备不安全] UILabel setText called from : 0x1eaa7cfe8 UIKitCore! - [_UIAlertControllerView _updateTitleLabelContents] 0x1eaa75544 UIKitCore! - [_UIAlertControllerView _prepareTitleLabel] 0x1eaa750e8 UIKitCore! - [_UIAlertControllerView _prepareViewsAndAddConstraints] 0x1eaa75048 UIKitCore! - [_UIAlertControllerView setAlertController:] 0x1eaa61740 UIKitCore! - [UIAlertController loadView] 0x1ead35ed8 UIKitCore! - [UIViewController loadViewIfRequired] 0x1ead36628 UIKitCore! - [UIViewController view] 0x1ead4ddd4 UIKitCore! - [UIViewController _setPresentationController:] 0x1ead461f4 UIKitCore! - [UIViewController _presentViewController:modalSourceViewController:presentationController:animationController:interactionController:completion:] 0x1ead47ccc UIKitCore! - [UIViewController _presentViewController:withAnimationController:completion:] 0x1ead4a3a8 UIKitCore!__63 - [UIViewController _presentViewController:animated:completion:]_block_invoke 0x1ead4a8a4 UIKitCore! - [UIViewController _performCoordinatedPresentOrDismiss:animated:] 0x1ead4a300 UIKitCore! - [UIViewController _presentViewController:animated:completion:] 0x1ead4a560 UIKitCore! - [UIViewController presentViewController:animated:completion:] 0x10128253c App! 0xd253c ( 0x1000d253c ) 0x1be344a38 libdispatch.dylib!_dispatch_call_block_and_release - [UILabel setText:越狱手机存在安全风险] UILabel setText called from : 0x1eaa7d0f4 UIKitCore! - [_UIAlertControllerView _updateMessageLabelContents] 0x1eaa756f8 UIKitCore! - [_UIAlertControllerView _prepareMesssageLabel] 0x1eaa750f8 UIKitCore! - [_UIAlertControllerView _prepareViewsAndAddConstraints] 0x1eaa75048 UIKitCore! - [_UIAlertControllerView setAlertController:] 0x1eaa61740 UIKitCore! - [UIAlertController loadView] 0x1ead35ed8 UIKitCore! - [UIViewController loadViewIfRequired] 0x1ead36628 UIKitCore! - [UIViewController view] 0x1ead4ddd4 UIKitCore! - [UIViewController _setPresentationController:] 0x1ead461f4 UIKitCore! - [UIViewController _presentViewController:modalSourceViewController:presentationController:animationController:interactionController:completion:] 0x1ead47ccc UIKitCore! - [UIViewController _presentViewController:withAnimationController:completion:] 0x1ead4a3a8 UIKitCore!__63 - [UIViewController _presentViewController:animated:completion:]_block_invoke 0x1ead4a8a4 UIKitCore! - [UIViewController _performCoordinatedPresentOrDismiss:animated:] 0x1ead4a300 UIKitCore! - [UIViewController _presentViewController:animated:completion:] 0x1ead4a560 UIKitCore! - [UIViewController presentViewController:animated:completion:] 0x10128253c App! 0xd253c ( 0x1000d253c ) 0x1be344a38 libdispatch.dylib!_dispatch_call_block_and_release |
在XXX_presentViewController:presentType:presentCompletionHandler:dismissCompleteHandler:方法的调用栈,发现[LaunchingViewController start]方法,使用ida pro查看该函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | void __cdecl - [LaunchingViewController start](LaunchingViewController * self , SEL a2) { if ( !(~LODWORD( self - >_launchAchieveOption) & 0x1FLL ) ) { v2 = self ; self - >_launchAchieveOption = 0LL ; v3 = (( id (__cdecl * )(GuaTabBarController_meta * , SEL))objc_msgSend)( (GuaTabBarController_meta * )&OBJC_CLASS___GuaTabBarController, "shareTabBarController" ); v4 = objc_retainAutoreleasedReturnValue(v3); v23 = _NSConcreteStackBlock; v24 = 3254779904LL ; v25 = sub_100124684; v26 = &unk_101A2BC20; v5 = (void * )objc_retain(v4); v27 = v5; v28 = v2; + [NaviService naviModelWithNaviRoot:withNaviHead:withSourceFrom:ret:]( &OBJC_CLASS___NaviService, "naviModelWithNaviRoot:withNaviHead:withSourceFrom:ret:" , _NSConcreteStackBlock, 3254779904LL , sub_100124684, &unk_101A2BC20); if ( v2 - >_adDetailDisplayController ) { v6 = objc_msgSend(v5, "viewControllers" , v23, v24, v25, v26); v7 = (void * )objc_retainAutoreleasedReturnValue(v6); v8 = v7; v9 = objc_msgSend(v7, "objectAtIndexedSubscript:" , 0LL , v23, v24, v25, v26); v10 = (void * )objc_retainAutoreleasedReturnValue(v9); objc_msgSend(v10, "pushViewController:animated:" , v2 - >_adDetailDisplayController, 1LL , v23, v24, v25, v26); } v11 = objc_msgSend(&OBJC_CLASS___UIApplication, "sharedApplication" , v23, v24, v25, v26); v12 = (void * )objc_retainAutoreleasedReturnValue(v11); v13 = v12; v14 = objc_msgSend(v12, "delegate" , v23, v24, v25, v26); v15 = (void * )objc_retainAutoreleasedReturnValue(v14); v16 = v15; v17 = objc_msgSend(v15, "window" , v23, v24, v25, v26); v18 = (void * )objc_retainAutoreleasedReturnValue(v17); objc_msgSend(v18, "setRootViewController:" , v5, v23, v24, v25, v26); if ( (unsigned int ) + [XXXJailBreakJudge deviceIsJailBreak]( &OBJC_CLASS___XXXJailBreakJudge, "deviceIsJailBreak" , v23, v24, v25, v26) ) { v19 = objc_msgSend( &OBJC_CLASS___UIAlertController, "alertControllerWithTitle:message:preferredStyle:" , CFSTR( "您的设备不安全" ), CFSTR( "越狱手机存在安全风险" ), 1LL , v23, v24, v25, v26); v20 = (void * )objc_retainAutoreleasedReturnValue(v19); v21 = objc_msgSend( &OBJC_CLASS___UIAlertAction, "actionWithTitle:style:handler:" , CFSTR( "确定" ), 0LL , 0LL , v23, v24, v25, v26); v22 = objc_retainAutoreleasedReturnValue(v21); objc_msgSend(v20, "addAction:" , v22, v23, v24, v25, v26); + [XXXAlertPresentController presentAlertController:]( &OBJC_CLASS___XXXAlertPresentController, "presentAlertController:" , v20, v23, v24, v25, v26); } } } |
从函数中可发现越狱检测函数为[XXXJailBreakJudge deviceIsJailBreak]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | bool __cdecl + [XXXJailBreakJudge deviceIsJailBreak](XXXJailBreakJudge_meta * self , SEL a2) { XXXJailBreakJudge_meta * v2; / / x20 void * v3; / / x0 __int64 v4; / / x0 void * v5; / / x0 void * v6; / / x19 void * v7; / / x0 void * v8; / / x22 __int64 v9; / / x25 unsigned __int64 v10; / / x26 uint32_t v11; / / w0 uint32_t v12; / / w20 uint32_t v13; / / w21 void * v14; / / x25 const char * v15; / / x0 void * v16; / / x25 char v17; / / w26 _BOOL8 v18; / / x20 bool result; / / w0 __int128 v20; / / [xsp + 0h ] [xbp - 140h ] __int128 v21; / / [xsp + 10h ] [xbp - 130h ] __int128 v22; / / [xsp + 20h ] [xbp - 120h ] __int128 v23; / / [xsp + 30h ] [xbp - 110h ] char v24; / / [xsp + 40h ] [xbp - 100h ] const __CFString * v25; / / [xsp + C0h] [xbp - 80h ] const __CFString * v26; / / [xsp + C8h] [xbp - 78h ] const __CFString * v27; / / [xsp + D0h] [xbp - 70h ] const __CFString * v28; / / [xsp + D8h] [xbp - 68h ] const __CFString * v29; / / [xsp + E0h] [xbp - 60h ] __int64 v30; / / [xsp + E8h] [xbp - 58h ] v2 = self ; v25 = CFSTR( "/Applications/Cydia.app" ); v26 = CFSTR( "/Library/MobileSubstrate/MobileSubstrate.dylib" ); v27 = CFSTR( "/bin/bash" ); v28 = CFSTR( "/usr/sbin/sshd" ); v29 = CFSTR( "/etc/apt" ); v3 = objc_msgSend(&OBJC_CLASS___NSArray, "arrayWithObjects:count:" , &v25, 5LL ); v4 = objc_retainAutoreleasedReturnValue(v3); v20 = 0u ; v21 = 0u ; v22 = 0u ; v23 = 0u ; v5 = (void * )objc_retain(v4); v6 = v5; v7 = objc_msgSend(v5, "countByEnumeratingWithState:objects:count:" , &v20, &v24, 16LL , 0LL ); if ( v7 ) { v8 = v7; v9 = * (_QWORD * )v21; while ( 2 ) { v10 = 0LL ; do { if ( * (_QWORD * )v21 ! = v9 ) objc_enumerationMutation(v6); if ( (unsigned __int64)objc_msgSend( v2, "permissionForFile:" , * (_QWORD * )( * ((_QWORD * )&v20 + 1 ) + 8 * v10), (_QWORD)v20) & 1 ) { objc_release(v6); goto LABEL_16; } + + v10; } while ( v10 < (unsigned __int64)v8 ); v8 = objc_msgSend(v6, "countByEnumeratingWithState:objects:count:" , &v20, &v24, 16LL , (_QWORD)v20); if ( v8 ) continue ; break ; } } objc_release(v6); if ( !((unsigned __int64)objc_msgSend(v2, "permissionForFile:" , CFSTR( "/User/Applications/" ), (_QWORD)v20) & 1 ) ) { v11 = _dyld_image_count(); if ( !v11 ) { LABEL_14: v18 = getenv( "DYLD_INSERT_LIBRARIES" ) ! = 0LL ; goto LABEL_17; } v12 = v11; v13 = 0 ; while ( 1 ) { v14 = (void * )objc_alloc(&OBJC_CLASS___NSString); v15 = _dyld_get_image_name(v13); v16 = objc_msgSend(v14, "initWithUTF8String:" , v15, (_QWORD)v20); v17 = (unsigned __int64)objc_msgSend(v16, "containsString:" , CFSTR( "MobileSubstrate.dylib" ), (_QWORD)v20); objc_release(v16); if ( v17 & 1 ) break ; if ( v12 = = + + v13 ) goto LABEL_14; } } LABEL_16: v18 = 1 ; LABEL_17: return v18; } |
结果
1、检测以下路径是否存在:
- /Applications/Cydia.app
- /Library/MobileSubstrate/MobileSubstrate.dylib
- /bin/bash
- /usr/sbin/sshd
- /etc/apt
2、如果路径/User/Applications/不存在,检测getenv("DYLD_INSERT_LIBRARIES")是否存在
3、如果路径/User/Applications/不存在,检测当前现在在运行的动态库是否包含MobileSubstrate.dylib
End
阅读此文档的过程中遇到任何问题,请关注公众号【移动端Android和iOS开发技术分享
】或加QQ群【812546729
】
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法