美文网首页
iOS逆向篇——Cycript调试App

iOS逆向篇——Cycript调试App

作者: Lucky_Blue | 来源:发表于2021-03-24 09:29 被阅读0次

    现在越狱后的手机都是自带安装了Cycriptadv-cmds,如果没有即添加软件源https://apt.bingner.com安装好。

    Cycript
    adv-cmds
    先通过SSH登录到服务器(iPhone

    ps 命令

    • 列出所有进程 ps -A(当前手机打开了腾讯动漫)


      可以从上图找到11095腾讯动漫的进程idpid),ComicReader腾讯动漫的进程名称
    • 搜索进程:ps –A | grep 关键词
    i-57:~ root# ps -A | grep ComicReader
    11095 ??         0:05.50 /var/containers/Bundle/Application/015C9AB9-4440-492F-911B-6DEC6915FBFC/ComicReader.app/ComicReader
    11121 ttys000    0:00.01 grep ComicReader
    i-57:~ root#
    
    • 附加App直接调试 cycript -p 进程名称/进程的编号
    cycript -p 11095
    或者
    cycript -p ComicReader
    cy#
    
    • 获取BundleIdentifier
    i-57:~ root# cycript -p 1369
    cy# [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]
    

    启动和退出

    • 启动:cycript -p 进程名称
    • 退出:control + d
    • 清屏:command + r

    Cycript 常用语法

    • UIApp = UIApplication.sharedApplication()
    cy# UIApp
    #"<UIApplication: 0x104f04470>"
    
    • 用内存地址获取对象:#内存地址
    cy# #0x104f04470
    #"<UIApplication: 0x104f04470>"
    
    • 查看对象的所有成员变量:*对象
    cy# *UIApp
    {isa:UIApplication,_responderFlags:@error,_delegate:#"<TencentXGPushAppDelegate: 0x280e46cc0>",_remoteControlEventObservers:0,_topLevelNibObjects:null,_networkResourcesCurrentlyLoadingCount:0,_hideNetworkActivityIndicatorTimer:null,_statusBar:null,_statusBarRequestedStyle:0,_statusBarWindow:null,_observerBlocks:@[],_postCommitActions:@[],_postCommitActionsNeedToSynchronize:false,_mainStoryboardName:null,_idleModeController:null,_displayLayoutMonitor:null,_systemUserInterfaceStyle:0,_eventFetcher:#"<UIEventFetcher: 0x282264540>",_eventDispatcher:#"<UIEventDispatcher: 0x281569620>",_applicationFlags:@error,_keyCommandToken:#"<BSSimpleAssertion: 0x281445110; identifier: com.apple.backboard.hid.delivery; reason: 2-keycmds; valid: YES>",_physicalKeyCommandMap:@{},_physicalKeycodeMap:[NSOrderedSet orderedSetWithArray:@[]]],_alwaysHitTestsForMainScreen:false,_backgroundHitTestWindow:null,_appInfo:#"<_UIApplicationInfoParser: 0x2830656c0>",_actionsPendingInitialization:null,_idleTimerDisabledReasons:[NSSet setWithArray:@[]]],_keyRepeatAction:null,_currentTimestampWhenFirstTouchCameDown:0,_currentLocationWhereFirstTouchCameDown:{x:0,y:0},_saveStateRestorationArchiveWithFileProtectionCompleteUntilFirstUserAuthentication:false,_fenceTaskAssertion:null,_cachedSystemAnimationFence:null,_systemNavigationAction:null,_activityContinuationManager:#"<UIActivityContinuationManager: 0x28156e310>",__gestureEnvironment:#"<UIGestureEnvironment: 0x283061d50>",_forceStageObservable:null,_HIDGameControllerEventObserver:null,_HIDGameControllerEventQueue:null,_motionNotificationGenerator:null,_appState:#"<UISApplicationState: 0x281b633c0>",_applicationPushRegistry:#"<PKPushRegistry: 0x2838401e0>",_storyboardInitialMenu:null,_endpointMonitor:#"<BSServiceConnectionEndpointMonitor: 0x283861ef0; service: com.apple.frontboard.open; active>",optOutOfRTL:false,_isDisplayingActivityContinuationUI:false,_applicationWantsGESEvents:false,_shortcutService:null,___queuedOrientationChange:null,__expectedViewOrientation:1}
    
    • 递归打印view的所有子控件:view.recursiveDescription().toString()
    UIApp.keyWindow.recursiveDescription().toString()
    
    • 定义变量:var 变量名 = 变量值
    cy# var window = UIApp.keyWindow
    #"<UIWindow: 0x104f1be40; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x281552d30>; layer = <UIWindowLayer: 0x281b753e0>>"
    
    • 定义函数:function 函数名(...) { ... }
    cy# function sum(a, b) {return a+b;}
    cy# sum(2,3)
    5
    
    • 筛选出某种类型的对象:choose(类型)
    cy# choose(UIViewController)
    [#"<UISystemInputAssistantViewController: 0x106468630>",#"<UIEditingOverlayViewController: 0x10649e1d0>",#"<ComicHomeViewController: 0x105843000>",#"<ComicNavgationController: 0x105849000>",#"<VPlaygoundViewController: 0x10584e200>",#"<ComicNavgationController: 0x105850200>",#"<WaitHomeViewController: 0x105853a00>",#"<BookShelfViewController: 0x10585aa00>",#"<ComicNavgationController: 0x10585b000>",#"<MyViewController: 0x10585b600>",#"<ComicNavgationController: 0x10585bc00>",#"<ComicNavgationController: 0x105867400>",#"<UpdateChannelViewController: 0x105883a00>",#"<UpdateChannelSubViewController: 0x1058ee400>",#"<UpdateChannelSubViewController: 0x1058f5000>",#"<UIInputWindowController: 0x10595b000>",#"<ADWebViewController: 0x105972a00>",#"<ComicTabBarController: 0x105040400>",#"<ADWebViewController: 0x105137000>",#"<GenderSelectionViewController: 0x1051e8000>"]
    

    .cy文件的应用

    .cy文件是对Cycript的封装,方便提供一些比较常用的函数。

    (function(exports) {
        var invalidParamStr = 'Invalid parameter';
        var missingParamStr = 'Missing parameter';
    
        // app id
        LBAppId = [NSBundle mainBundle].bundleIdentifier;
        // mainBundlePath
        LBAppPath = [NSBundle mainBundle].bundlePath;
        // document path
        LBDocPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
        // caches path
        LBCachesPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]; 
    
        // 加载系统动态库
        LBLoadFramework = function(name) {
            var head = "/System/Library/";
            var foot = "Frameworks/" + name + ".framework";
            var bundle = [NSBundle bundleWithPath:head + foot] || [NSBundle bundleWithPath:head + "Private" + foot];
            [bundle load];
            return bundle;
        };
    
        // keyWindow
        LBKeyWin = function() {
            return UIApp.keyWindow;
        };
    
        // 根控制器
        LBRootVc =  function() {
            return UIApp.keyWindow.rootViewController;
        };
    
        // 找到显示在最前面的控制器
        var _LBFrontVc = function(vc) {
            if (vc.presentedViewController) {
                return _LBFrontVc(vc.presentedViewController);
            }else if ([vc isKindOfClass:[UITabBarController class]]) {
                return _LBFrontVc(vc.selectedViewController);
            } else if ([vc isKindOfClass:[UINavigationController class]]) {
                return _LBFrontVc(vc.visibleViewController);
            } else {
                var count = vc.childViewControllers.count;
                for (var i = count - 1; i >= 0; i--) {
                    var childVc = vc.childViewControllers[i];
                    if (childVc && childVc.view.window) {
                        vc = _LBFrontVc(childVc);
                        break;
                    }
                }
                return vc;
            }
        };
    
        LBFrontVc = function() {
            return _LBFrontVc(UIApp.keyWindow.rootViewController);
        };
    
        // 递归打印UIViewController view的层级结构
        LBVcSubviews = function(vc) { 
            if (![vc isKindOfClass:[UIViewController class]]) throw new Error(invalidParamStr);
            return vc.view.recursiveDescription().toString(); 
        };
    
        // 递归打印最上层UIViewController view的层级结构
        LBFrontVcSubViews = function() {
            return LBVcSubviews(_LBFrontVc(UIApp.keyWindow.rootViewController));
        };
    
        // 获取按钮绑定的所有TouchUpInside事件的方法名
        LBBtnTouchUpEvent = function(btn) { 
            var events = [];
            var allTargets = btn.allTargets().allObjects()
            var count = allTargets.count;
            for (var i = count - 1; i >= 0; i--) { 
                if (btn != allTargets[i]) {
                    var e = [btn actionsForTarget:allTargets[i] forControlEvent:UIControlEventTouchUpInside];
                    events.push(e);
                }
            }
           return events;
        };
    
        // CG函数
        LBPointMake = function(x, y) { 
            return {0 : x, 1 : y}; 
        };
    
        LBSizeMake = function(w, h) { 
            return {0 : w, 1 : h}; 
        };
    
        LBRectMake = function(x, y, w, h) { 
            return {0 : LBPointMake(x, y), 1 : LBSizeMake(w, h)}; 
        };
    
        // 递归打印controller的层级结构
        LBChildVcs = function(vc) {
            if (![vc isKindOfClass:[UIViewController class]]) throw new Error(invalidParamStr);
            return [vc _printHierarchy].toString();
        };
    
        // 递归打印view的层级结构
        LBSubviews = function(view) { 
            if (![view isKindOfClass:[UIView class]]) throw new Error(invalidParamStr);
            return view.recursiveDescription().toString(); 
        };
    
        // 判断是否为字符串 "str" @"str"
        LBIsString = function(str) {
            return typeof str == 'string' || str instanceof String;
        };
    
        // 判断是否为数组 []、@[]
        LBIsArray = function(arr) {
            return arr instanceof Array;
        };
    
        // 判断是否为数字 666 @666
        LBIsNumber = function(num) {
            return typeof num == 'number' || num instanceof Number;
        };
    
        var _LBClass = function(className) {
            if (!className) throw new Error(missingParamStr);
            if (LBIsString(className)) {
                return NSClassFromString(className);
            } 
            if (!className) throw new Error(invalidParamStr);
            // 对象或者类
            return className.class();
        };
    
        // 打印所有的子类
        LBSubclasses = function(className, reg) {
            className = _LBClass(className);
    
            return [c for each (c in ObjectiveC.classes) 
            if (c != className 
                && class_getSuperclass(c) 
                && [c isSubclassOfClass:className] 
                && (!reg || reg.test(c)))
                ];
        };
    
        // 打印所有的方法
        var _LBGetMethods = function(className, reg, clazz) {
            className = _LBClass(className);
    
            var count = new new Type('I');
            var classObj = clazz ? className.constructor : className;
            var methodList = class_copyMethodList(classObj, count);
            var methodsArray = [];
            var methodNamesArray = [];
            for(var i = 0; i < *count; i++) {
                var method = methodList[i];
                var selector = method_getName(method);
                var name = sel_getName(selector);
                if (reg && !reg.test(name)) continue;
                methodsArray.push({
                    selector : selector, 
                    type : method_getTypeEncoding(method)
                });
                methodNamesArray.push(name);
            }
            free(methodList);
            return [methodsArray, methodNamesArray];
        };
    
        var _LBMethods = function(className, reg, clazz) {
            return _LBGetMethods(className, reg, clazz)[0];
        };
    
        // 打印所有的方法名字
        var _LBMethodNames = function(className, reg, clazz) {
            return _LBGetMethods(className, reg, clazz)[1];
        };
    
        // 打印所有的对象方法
        LBInstanceMethods = function(className, reg) {
            return _LBMethods(className, reg);
        };
    
        // 打印所有的对象方法名字
        LBInstanceMethodNames = function(className, reg) {
            return _LBMethodNames(className, reg);
        };
    
        // 打印所有的类方法
        LBClassMethods = function(className, reg) {
            return _LBMethods(className, reg, true);
        };
    
        // 打印所有的类方法名字
        LBClassMethodNames = function(className, reg) {
            return _LBMethodNames(className, reg, true);
        };
    
        // 打印所有的成员变量
        LBIvars = function(obj, reg){ 
            if (!obj) throw new Error(missingParamStr);
            var x = {}; 
            for(var i in *obj) { 
                try { 
                    var value = (*obj)[i];
                    if (reg && !reg.test(i) && !reg.test(value)) continue;
                    x[i] = value; 
                } catch(e){} 
            } 
            return x; 
        };
    
        // 打印所有的成员变量名字
        LBIvarNames = function(obj, reg) {
            if (!obj) throw new Error(missingParamStr);
            var array = [];
            for(var name in *obj) { 
                if (reg && !reg.test(name)) continue;
                array.push(name);
            }
            return array;
        };
    })(exports);
    

    lbtool.cy文件拷贝到iPhone/usr/lib/cycript0.9目录下

    scp /Users/mac/Desktop/lbtool.cy root@192.168.2.6:/usr/lib/cycript0.9
    lbtool.cy                                     100% 6178   760.8KB/s   00:00
    
    image.png
    • lbtool.cy文件用法
      @import + 文件名导入文件
    i-57:~ root# cycript -p 11424
    cy# @import lbtool
    {}
    

    获取当前显示的控制器

    cy# LBFrontVc()
    #"<ACReaderViewController: 0x1048ae600>"
    

    获取view的层级结构

    cy# LBSubviews(LBFrontVc().view)
    `<UIView: 0x117c54a40; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x283adab00>>
       | <ACReaderEngineView: 0x117c4b850; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x283483720>; layer = <CALayer: 0x283acd3c0>>
       |    | <ACZoomScrollView: 0x105b15600; baseClass = UIScrollView; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x2834be790>; layer = <CALayer: 0x283acd660>; contentOffset: {0, 0}; contentSize: {0, 0}; adjustedContentInset: {0, 0, 0, 0}>
       |    |    | <UICollectionView: 0x105b19600; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x283491920>; layer = <CALayer: 0x283acdbe0>; contentOffset: {0, 10}; contentSize: {375, 2130}; adjustedContentInset: {0, 0, 0, 0}; layout: <UICollectionViewFlowLayout: 0x11bf46e50>; dataSource: <ACReaderEngineView: 0x117c4b850; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x283483720>; layer = <CALayer: 0x283acd3c0>>>
    
    最后小试牛刀把腾讯动漫底部充值view隐藏
    隐藏前
    cy# #0x11bfeb950.hidden = YES
    true
    
    隐藏后

    相关文章

      网友评论

          本文标题:iOS逆向篇——Cycript调试App

          本文链接:https://www.haomeiwen.com/subject/lvvfhltx.html