利用cycript动态调试app

一、准备

  ios系统越狱环境
  安装ssh
  安装cycript

二、执行命令

  找到进程注入:

chentekiiPhone:/var/containers/Bundle/Application root# ps aux | grep test
mobile             758   0.0  1.0  5031504  20176   ??  Ss    2:20PM   1:36.66 /var/containers/Bundle/Application/6E27936D-08FB-4F5B-A7BC-FC1A4D6AEB05/test.app/test
root              1182   0.0  0.2  4207888   4560 s000  S+    2:29PM   0:00.01 grep test
chentekiiPhone:/var/containers/Bundle/Application root# cycript -p 758
cy# 

注入之后执行hook指令

@import com.saurik.substrate.MS
var oldm = {};
var log = []
MS.hookMessage(objc_getClass("ViewController"),@selector(viewDidLoad), function(arg0) {
    var d = [NSDate date]
    log.push([d.toString()]);
    return oldm->call(this, arg0);
}, oldm)

打印log

cy# log
[["2017-03-15 03:30:15 +0000"],["2017-03-15 03:30:15 +0000"],["2017-03-15 03:30:15 +0000"]]

choose命令,获取内存对象地址

cy# choose(ViewController) 
[#"<ViewController: 0x101031b20>"]

操作符来获取这个对象

[#0x101031b20 show]

description函数能够把对象的内容表示成一个NSString,object_getClassName函数能够把对象
的类名表示成一个char*,两者可分别用%@和%s打印出来,这就为解析参数提供了足够参考。

cy# [#0x101031b20 description]
@"<ViewController: 0x101031b20>"
cy# object_getClassName(0x101031b20)
&"__NSCFNumber"

recursiveDescription - 打印UIView对象

cy# [[UIApp keyWindow] recursiveDescription].toString()
`<UIWindow: 0x10092f020; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x281c38960>; layer = <UIWindowLayer: 0x28121b5a0>>
   | <UITransitionView: 0x1009317e0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x28121e620>>
   |    | <UIDropShadowView: 0x100934800; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x28121e380>>
   |    |    | <UIView: 0x100934290; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x28121e880>>
   |    |    |    | <_UILayoutGuide: 0x100934470; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x28121fc80>>
   |    |    |    | <_UILayoutGuide: 0x100934a00; frame = (0 667; 0 0); hidden = YES; layer = <CALayer: 0x28121e6e0>>
   | <XLFloatBtn: 0x100935560; baseClass = UIButton; frame = (335 313.5; 40 40); opaque = NO; layer = <CALayer: 0x281215f20>>
   |    | <UIButtonLabel: 0x100940bc0; frame = (6.5 12; 27 16); text = '\u5b58\u6863'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x283103cf0>>
   |    |    | <_UILabelContentLayer: 0x28122bf20> (layer)`

_printHierarchy - 直接打印所有UIViewController

cy# [[[UIWindow keyWindow] rootViewController] _printHierarchy].toString()

_autolayoutTrace – recursiveDescription的简化版,去掉了UIView的一些描述

cy# [[UIApp keyWindow] _autolayoutTrace].toString()
`
UIWindow:0x10092f020
|   UITransitionView:0x1009317e0
|   |   UIDropShadowView:0x100934800
|   |   |   \u2022UIView:0x100934290
|   |   |   |   *_UILayoutGuide:0x100934470
|   |   |   |   *_UILayoutGuide:0x100934a00
|   XLFloatBtn:0x100935560'\u5b58\u6863'
|   |   UIButtonLabel:0x100940bc0'\u5b58\u6863'

Legend:
\t* - is laid out with auto layout
\t+ - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
\t\u2022 - layout engine host`

_ivarDescription – 打印某个对象所有instance的名字和值

cy# [choose(SBApplication)[0] _ivarDescription].toString()
`<SBApplication: 0x1766cab0>:
in SBApplication:
\t_bundleIdentifier (NSString*): @"com.apple.social.remoteui.SocialUIService"
\t_displayIdentifier (NSString*): @"com.apple.social.remoteui.SocialUIService"
\t_path (NSString*): @"/Applications/SocialUIService.app"
\t_bundleVersion (NSString*): @"87"
\t_defaultImageNamesByScreenType (NSMutableDictionary*): <__NSDictionaryM: 0x17672a90>
\t_defaultImageNamesForOrientation (NSDictionary*): nil
...
in NSObject:
\tisa (Class): SBApplication`

_methodDescription – 打印某个对象的属性,实例和类方法

cy# [choose(SBApplicationController)[0] _methodDescription].toString()
`<SBApplicationController: 0x17642990>:
in SBApplicationController:
\tClass Methods:
\t\t+ (void) setClearSystemAppSnapshotsWhenLoaded:(BOOL)arg1; (0x1b2ad1)
...
\t\t+ (id) sharedInstanceIfExists; (0x1b2b6d)
\tInstance Methods:
\t\t- (id) setupApplication; (0x1b3e3d)
...
\t\t- (id) applicationWithDisplayIdentifier:(id)arg1; (0x1b3d0d)
in NSObject:
\tClass Methods:
\t\t+ (bool) cy\$hasImplicitProperties; (0xdb45d80)
...
\t\t+ (void) finalize; (0x39a49ad1)
\tProperties:
\t\t@property (nonatomic) BOOL isAccessibilityElement;  (@dynamic isAccessibilityElement;)
...
\t\t@property (nonatomic) BOOL shouldGroupAccessibilityChildren;  (@dynamic shouldGroupAccessibilityChildren;)
\tInstance Methods:
\t\t- (id) cy\$toCYON:(bool)arg1 inSet:(set<void *, std::less<void *>, std::allocator<void *> >*)arg2; (0xdb45b60)
...
\t\t- (void) finalize; (0x39a49ad5)`

找到目标App的Documents目录路径

cy# [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0] 
#"file:///var/mobile/Containers/Data/Application/5CA182CC-253F-4F55-814B-DDEB42FEDF19/Documents/"

获取bundle info

cy# [[NSBundle mainBundle] infoDictionary].toString()
`{
    BuildMachineOSBuild = 19H2;
    CFBundleDevelopmentRegion = en;
    CFBundleExecutable = test;
    CFBundleIdentifier = "cn.6us.test";
    CFBundleInfoDictionaryVersion = "6.0";
    CFBundleName = test;
    CFBundleNumericVersion = 16809984;
    CFBundlePackageType = APPL;
    CFBundleShortVersionString = "1.0";
    CFBundleSupportedPlatforms =     (
        iPhoneOS
    );
    CFBundleVersion = 1;
    DTCompiler = "com.apple.compilers.llvm.clang.1_0";
    DTPlatformBuild = 18A390;
    DTPlatformName = iphoneos;
    DTPlatformVersion = "14.0";
    DTSDKBuild = 18A390;
    DTSDKName = "iphoneos14.0";
    DTXcode = 1201;
    DTXcodeBuild = 12A7300;
    LSRequiresIPhoneOS = 1;
    MinimumOSVersion = "9.2";
    UIApplicationSceneManifest =     {
        UIApplicationSupportsMultipleScenes = 0;
        UISceneConfigurations =         {
            UIWindowSceneSessionRoleApplication =             (
                                {
                    UISceneConfigurationName = "Default Configuration";
                    UISceneDelegateClassName = SceneDelegate;
                    UISceneStoryboardFile = Main;
                }
            );
        };
    };
    UIApplicationSupportsIndirectInputEvents = 1;
    UIDeviceFamily =     (
        1,
        2
    );
    UILaunchStoryboardName = LaunchScreen;
    UIMainStoryboardFile = Main;
    UIRequiredDeviceCapabilities =     (
        arm64
    );
    UISupportedInterfaceOrientations =     (
        UIInterfaceOrientationPortrait,
        UIInterfaceOrientationLandscapeLeft,
        UIInterfaceOrientationLandscapeRight
    );
}`

关于Zeno Chen

本人涉及的领域较多,杂而不精 程序设计语言: Perl, Java, PHP, Python; 数据库系统: MySQL,Oracle; 偶尔做做电路板的开发,主攻STM32单片机
此条目发表在Objective-C分类目录。将固定链接加入收藏夹。