iOS逆向-LLDB高级用法&Cycript-(ASLR)(Ⅷ)

2019-10-29  本文已影响0人  鼬殿

ASLR

ASLR(Address Space Layout Randomization),地址空间布局随机化。
是一种针对缓冲区溢出的安全保护技术,通过对堆、栈、共享库映射等线性区布局的随机化,通过增加攻击者预测目的地址的难度,防止攻击者直接定位攻击代码位置,达到阻止溢出攻击的目的的一种技术。
iOS4.3开始引入了ASLR技术。

MachOView中查看LC_SEGMENT_64(_TEXT)VM_Address0x100000000(__PAGEZERO VM Size),如果没有ASLR技术,MachO文件在内存中的物理地址就是0x100000000


查看MachO文件的在内存中的物理地址0x00000001043bc000
(lldb) image list
[  0] 802EFF39-2417-3E7E-97B8-E21AD7AFD27A 0x00000001043bc000 /Users/niujf/Library/Developer/Xcode/DerivedData/001--Demo-dantuskxyprjdbcmfkmwgrxzoxbt/Build/Products/Debug-iphoneos/001--Demo.app/001--Demo 
[  1] 571392A7-E1E6-369F-8805-C1A141F3C1C5 0x0000000104488000 /Users/niujf/Library/Developer/Xcode/iOS DeviceSupport/13.1.3 (17A878)/Symbols/usr/lib/dyld 
...

可以看到ASLR随机产生的Offset,也就是MachO文件的偏移值是0x1043bc000-0x100000000=0x43bc000

如何给一个函数设置内存断点?

随便写一个方法,在Hopper中查看方法在文件中的地址是00000001000065f0,由于Hopper会自动加上一个__PAGEZERO VM Size 0x100000000,所以实际方法在文件中的偏移值是0x65f0


MachOView中查看__PAGEZERO,可以看到在文件中的File offsetFile Size都是0

Hopper、IDA都是未使用ASLR的VM Address

方法在内存中的物理地址 = __PAGEZERO VM Size + File Offset + ASLR Offset = 0x100000000 + 0x65f0 + 0x43bc000
如下对方法的在内存中的物理地址下断点,可以看到下断点成功了。

(lldb) b -a 00000001000065f0+0x43bc000
Breakpoint 1: where = 001--Demo`-[ViewController eatWithObjc:] at ViewController.m:17, address = 0x00000001043c25f0
(lldb) breakpoint list
Current breakpoints:
1: address = 001--Demo[0x00000001000065f0], locations = 1, resolved = 1, hit count = 0
  1.1: where = 001--Demo`-[ViewController eatWithObjc:] at ViewController.m:17, address = 0x00000001043c25f0, resolved, hit count = 0 

如何查看一个全局变量在MachO文件中的位置?

查看一个int类型的全局变量a在内存的物理地址

int a = 10;

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    a = 20;   //打上断点
    NSLog(@"%d",a);
}
(lldb) p a
(int) $0 = 10
(lldb) p &a
(int *) $1 = 0x0000000102ad4df0

可以看到全局变量a在内存中的物理地址是0x0000000102ad4df0

(lldb) image list
[  0] 802EFF39-2417-3E7E-97B8-E21AD7AFD27A 0x0000000102acc000 /Users/niujf/Library/Developer/Xcode/DerivedData/001--Demo-dantuskxyprjdbcmfkmwgrxzoxbt/Build/Products/Debug-iphoneos/001--Demo.app/001--Demo 

MachO文件在内存中的物理地址是0x0000000102acc000,全局变量a在文件中的偏移值就是0x0000000102ad4df0 - 0x0000000102acc000 = 0x8df0

MachOView中查看0x8df0位置对应的数据是0xA0,也就是十进制10.

chisel

chisel一个LLDB命令集合,用于帮助调试iOS应用程序。
可以通过Homebrew安装,具体的安装命令在README里有

chisel在Xcode11上遇到的问题
error: module importing failed: Missing parentheses in call to 'print'. Did you mean print('Whoops! You are missing the <' + arg.argName + '> argument.')? (fblldb.py, line 98)
  File "temp.py", line 1, in <module>

莫慌,在issues里面已经给出了解决方案,有两种,lz是在 /usr/local/Cellar/chisel/1.8.1 路径下替换了修改了源码兼容Python 3libexec文件

chisel的Commands

如果对那个Commands不熟悉,可以通过(lldb) help Commands 查看,也可以看README

(lldb) pviews
<UIWindow: 0x135e0be70; frame = (0 0; 375 812); gestureRecognizers = <NSArray: 0x283f42310>; layer = <UIWindowLayer: 0x283142fa0>>
   | <UITransitionView: 0x135e14430; frame = (0 0; 375 812); autoresize = W+H; layer = <CALayer: 0x2831688c0>>
   |    | <UIDropShadowView: 0x135e14be0; frame = (0 0; 375 812); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x283168980>>
   |    |    | <UIView: 0x135e13cd0; frame = (0 0; 375 812); autoresize = W+H; layer = <CALayer: 0x283168620>>
   |    |    |    | <UIButton: 0x135e13320; frame = (100 200; 100 100); opaque = NO; layer = <CALayer: 0x283168780>>
   |    |    |    |    | <UIButtonLabel: 0x135e23c50; frame = (31.6667 39; 37 22); text = ''; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x281268000>>
   |    |    |    |    |    | <_UILabelContentLayer: 0x283171be0> (layer)
(lldb) pviews self.view
<UIView: 0x135e13cd0; frame = (0 0; 375 812); autoresize = W+H; layer = <CALayer: 0x283168620>>
   | <UIButton: 0x135e13320; frame = (100 200; 100 100); opaque = NO; layer = <CALayer: 0x283168780>>
   |    | <UIButtonLabel: 0x135e23c50; frame = (31.6667 39; 37 22); text = ''; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x281268000>>
   |    |    | <_UILabelContentLayer: 0x283171be0> (layer)
(lldb) pvc
<ViewController 0x135e0afc0>, state: appeared, view: <UIView 0x135e13cd0>
(lldb) presponder 0x149d05b60 //按钮的在内存中的真实地址
<UIButton: 0x149d05b60; frame = (100 200; 100 100); opaque = NO; layer = <CALayer: 0x280e3ab00>>
   | <UIView: 0x149d039d0; frame = (0 0; 375 812); autoresize = W+H; layer = <CALayer: 0x280e3aa00>>
   |    | <ViewController: 0x149e07d80>
   |    |    | <UIDropShadowView: 0x149d073a0; frame = (0 0; 375 812); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x280e3aae0>>
   |    |    |    | <UITransitionView: 0x149d06bf0; frame = (0 0; 375 812); autoresize = W+H; layer = <CALayer: 0x280e3aac0>>
   |    |    |    |    | <UIWindow: 0x149e08c30; frame = (0 0; 375 812); gestureRecognizers = <NSArray: 0x280050420>; layer = <UIWindowLayer: 0x280e14f00>>
   |    |    |    |    |    | <UIWindowScene: 0x149e04330; scene = <FBSSceneImpl: 0x28202cc80; identifier: sceneID:com.ttt.jinxiao-default>; persistentIdentifier = 42D38740-A3B7-4D1F-BB16-34AA4FE0252A; activationState = UISceneActivationStateForegroundActive; settingsCanvas = <UIWindowScene: 0x149e04330>; windows = (
    "<UIWindow: 0x149e08c30; frame = (0 0; 375 812); gestureRecognizers = <NSArray: 0x280050420>; layer = <UIWindowLayer: 0x280e14f00>>",
    "<UITextEffectsWindow: 0x149d32600; frame = (0 0; 375 812); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x280e160a0>>"
)>
   |    |    |    |    |    |    | <UIApplication: 0x149e02140>
   |    |    |    |    |    |    |    | <AppDelegate: 0x280e3a600>
(lldb) pactions 0x149d05b60
<ViewController: 0x149e07d80>: btClicked
(lldb) pclass 0x149d05b60
UIButton
   | UIControl
   |    | UIView
   |    |    | UIResponder
   |    |    |    | NSObject
(lldb) fvc ViewController
0x105002580 ViewController
(lldb) fvc -v 0x105002580
Found the owning view controller.
<ViewController: 0x105002580>
(lldb) pmethods 0x105002580
Class Methods:
No methods were found

Instance Methods:
- (void)btClicked
- (void)setBtn:(id)arg0 
- (void)testMethod:(id)arg0 
- (void)setTestArray:(id)arg0 
- (id)btn
- (void).cxx_destruct
- (void)touchesBegan:(id)arg0 withEvent:(id)arg1 
- (void)viewDidLoad
- (id)test
- (id)testArray
- (void)setTest:(id)arg0 
(lldb) pinternals 0x105002580
(ViewController) $16 = {
  _test = nil
  _testArray = nil
  _btn = 0x0000000105107520
}
(lldb) taplog
Process 669 resuming
<UIButton: 0x105107520; frame = (100 200; 100 100); opaque = NO; layer = <CALayer: 0x282a70f80>>

要查看的view必须能接收点击事件,也就是他的userInteractionEnabled必须为YES才能被找到,UILabel和UIImageView默认userInteractionEnabled为NO。

flicker 0x105107520  //view的在内存中的真实地址
(lldb) vs 0x105107520

Use the following and (q) to quit.
(w) move to superview
(s) move to first subview
(a) move to previous sibling
(d) move to next sibling
(p) print the hierarchy

<UIButton: 0x105107520; frame = (100 200; 100 100); opaque = NO; layer = <CALayer: 0x282a70f80>>

DerekSelander-LLDB

DerekSelander-LLDB是另一款比较好用的LLDB调试工具
README.md里面有安装步骤,这里lz是把lldb_commands文件夹,放到了跟chisel同级目录,/usr/local/opt,然后在~/.lldbinit里面加上 command script import /usr/local/opt/lldb_commands/dslldb.pyok

常用命令

(lldb) search UIView
<UIViewControllerWrapperView: 0x10b76dd00; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x283716880>>

<UIImageView: 0x10b587350; frame = (0 -0.333333; 414 0.333333); userInteractionEnabled = NO; layer = <CALayer: 0x28377cb40>>

<_UINavigationBarLargeTitleView: 0x10b54eb70; frame = (0 0; 0 0); clipsToBounds = YES; hidden = YES; layer = <CALayer: 0x2837aec60>>
...
(lldb) methods 0x2814fceb0
<WCAccountLoginControlLogic: 0x2814fceb0>:
in WCAccountLoginControlLogic:
    Properties:
        @property (readonly) unsigned long hash;
        @property (readonly) Class superclass;
        @property (readonly, copy) NSString* description;
        @property (readonly, copy) NSString* debugDescription;
    Instance Methods:
        - (void) startLogic; (0x10511d4e8)
        - (void) stopLogic; (0x10511da50)
        - (void) onOneClickLoginSwitchAccount; (0x10511e2e0)
        - (void) onOneClickLoginProblem; (0x10511e314)
        - (void) onOneClickLoginGoToSecurityCenter; (0x10511e34c)
        - (void) onOneClickLoginGoToHelpCenter; (0x10511e384)
...
(lldb) b -a 0x10511dbcc           //对一个函数方法下断点
(lldb) c
Process 19583 resuming
(lldb) bt   //查看函数堆栈调用信息,frame #0是去符号的函数调用信息
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x000000010511dbcc WeChat`___lldb_unnamed_symbol142055$$WeChat
    frame #1: 0x0000000193667a44 UIKitCore`-[UIApplication sendAction:to:from:forEvent:] + 96

(lldb) sbt       //frame #0 恢复了去符号的函数调用信息
frame #0 : 0x10511dbcc WeChat`-[WCAccountLoginControlLogic onFirstViewLogin] 
frame #1 : 0x193667a44 UIKitCore`-[UIApplication sendAction:to:from:forEvent:] + 96

README.md里面还有其他命令,可以自己去尝试

Cycript

Cycript是由Cydia创始人Saurik推出的一款脚本语言,Cycript混合了OC、JavaScript语法的解释器,这意味着我们能够在一个命令中使用OC或者JavaScript,甚至两者并用。它能够挂钩正在运行的进程,能够在运行时修改很多东西。

Cycript的安装

1. 下载Cycript后,解压后直接把 cycript_0文件夹放到 /opt 目录下.


2. Terminal执行如下命令
$ cd /opt/cycript_0 
$ ./cycript

如果出现

dyld: Library not loaded: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/libruby.2.0.0.dylib
  Referenced from: /opt/cycript_0/./Cycript.lib/cycript-apl
  Reason: image not found
Abort trap: 6

这个错误是因为电脑的ruby版本太高导致

3. 查看电脑ruby版本

$ cd /System/Library/Frameworks/Ruby.framework/Versions/
$ ls
2.3 Current

4. 创建Ruby2.0版本文件,并将2.3版本文件拷贝到2.0中

sudo mkdir -p /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/
sudo ln -s /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/libruby.2.3.0.dylib /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/libruby.2.0.0.dylib

如果出现

mkdir: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/: Operation not permitted

5. 关闭系统的SIP
系统完整性保护(SIP)

6. 重新执行步骤4和步骤2,出现如下标志,安装成功!

cy# 

control + D 退出 Cycript

Cycript配置环境变量

1. 编辑bash_profile文件

$ cd ~/
$ vim .bash_profile 

2. 添加如下配置信息

#Cycript
export CY_PATH_ROOT=/opt/cycript_0
export PATH=$CY_PATH_ROOT:$PATH

3. 退出文件编辑并保存,执行如下命令查看,cycript环境变量配置成功

$ cycript
cy# 

Cycript的简单使用

Cycript连接手机有两种方式:

  1. 通过ssh登录,需要越狱手机打开ssh端口
  2. 在非越狱手机上,我们可以使用MonkeyDev(iOS逆向-反Hook防护(VI)里面有详细介绍安装和使用)。它里面有句代码CYListenServer(6666),代表在当前应用给CycriptServer端申请了一个端口号6666,我们可以在终端通过这个端口号在运行时给当前应用附加Cycript(MonkeyDev已经帮我们注入了libcycript.dylib)
$ cycript -r 172.20.0.240:6666
cy# 

172.20.0.240是手机网络的ip

cy# UIWindow.keyWindow()
#"<iConsoleWindow: 0x10b139fc0; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x283099110>; layer = <UIWindowLayer: 0x283e296e0>>"
cy# [UIApplication sharedApplication]
#"<UIApplication: 0x10b115b50>"
cy# UIApp
#"<UIApplication: 0x10b115b50>"
cy# var keyWindow = UIWindow.keyWindow()
#"<iConsoleWindow: 0x10b139fc0; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x283099110>; layer = <UIWindowLayer: 0x283e296e0>>"
cy# keyWindow
#"<iConsoleWindow: 0x10b139fc0; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x283099110>; layer = <UIWindowLayer: 0x283e296e0>>"
cy# keyWindow.rootViewController
#"<MMUINavigationController: 0x10b920a00>"
cy# #0x10b920a00 //根据地址获取对象
#"<MMUINavigationController: 0x10b920a00>"

cy# *#0x10b920a00 //获取对象的所有成员变量和值
{isa:MMUINavigationController,_responderFlags:@error,_overrideTransitioningDelegate:null,_view:#"<UILayoutContainerView: 0x10b13a2f0; frame = (0 0; 414 736); clipsToBounds = YES; 
...

cy# [i for(i in *keyWindow)]  //获取对象的所有成员变量(key)
["isa","_responderFlags","_constraintsExceptingSubviewAutoresizingConstraints","_cachedTraitCollection","_animationInfo","_layer","_layerRetained","_gestureRecognizers","_window","_subvi....

cy# choose(UIButton)  //获取所有UIButton的对象
[#"<UIButton: 0x10b54ba10; frame = (269 20; 145 49); opaque = NO; autoresize = LM; layer = <CALayer: 0x283efd4e0>>",#"<FixTitleColorButton: 0x10b11d960; baseClass = UIButton; frame = (20 18; 177 47); clipsToBounds = YES; opaque = NO; autoresize = RM; layer = <CALayer: 0x283e20a20>>",#"<FixTitleColorButton: 0x10b1477b0; baseClass = UIButton; frame = (217 18; 177 47); clipsToBounds = YES; opaque = NO; autoresize = LM; layer = <CALayer: 0x283ef8020>>"]

cy# keyWindow.recursiveDescription().toString() //打印所有的视图层级
`<iConsoleWindow: 0x10b139fc0; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x283099110>; layer = <UIWindowLayer: 0x283e296e0>>
   | <UILayoutContainerView: 0x10b13a2f0; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x283099b30>; layer = <CALayer: 0x283e29ac0>>
...

Shell脚本连接

1. 创建一个Shell脚本文件cylogin.sh, 路径如下

$ open ~/ 打开根目录

2. 添加可执行权限

$ chmod +x  cylogin.sh

3. 配置环境变量

export NJSHELL=/Users/niujf/NJShell
export PATH=$CY_PATH_ROOT:$PATH:$NJSHELL
如果以前没有配置环境变量就是
export PATH=$NJSHELL

4. 执行Shell脚本文件cylogin.sh

$ sh cylogin.sh

Cycript的高级用法

cy# APPID
@"com.ttt.jinxiao"
cy# pviews
function (){return UIApp.keyWindow.recursiveDescription().toString()}
cy# pviews()    //打印当前页面的view
`<iConsoleWindow: 0x11bd49860; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x2831f62b0>; layer = <UIWindowLayer: 0x283f7e320>>
   | <UILayoutContainerView: 0x11bd48310; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x2831cb0f0>; layer = <CALayer: 0x283f7d380>>
   |    | <UINavigationTransitionView: 0x11be2c9b0; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x283f65300>>
   |    |    | <UIViewControllerWrapperView: 0x11bd601d0; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x283fa09e0>>
   |    |    |    | <UIView: 0x11bd24df0; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x283f749a0>>
   |    |    |    |    | <UIView: 0x11bd37310; frame = (0 20; 414 801); autoresize = W; layer = <CALayer: 0x283f74bc0>>
   |    |    |    |    |    | <UIImageView: 0x11be11970; frame = (0 -20; 414 736); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x283f70ec0>>
   |    |    |    |    | <UIView: 0x11be12b70; frame = (0 651; 414 65); autoresize = W+TM; layer = <CALayer: 0x283f70fc0>>
   |    |    |    |    |    | <FixTitleColorButton: 0x11be35910; baseClass = UIButton; frame = (20 18; 177 47); clipsToBounds = YES; opaque = NO; autoresize = RM; layer = <CALayer: 0x283f71040>>
   |    |    |    |    |    |    | <UIButtonLabel: 0x11bd0dfe0; frame = (70 12.6667; 37 22); text = '\u767b\u5165'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x281c4e760>>
   |    |    |    |    |    |    |    | <_UILabelContentLayer: 0x283fa0ee0> (layer)
   |    |    |    |    |    | <FixTitleColorButton: 0x11be40660; baseClass = UIButton; frame = (217 18; 177 47); clipsToBounds = YES; opaque = NO; autoresize = LM; layer = <CALayer: 0x283faba40>>
   |    |    |    |    |    |    | <UIButtonLabel: 0x11be40a70; frame = (70 12.6667; 37 22); text = '\u8a3b\u518a'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x281c45cc0>>
   |    |    |    |    |    |    |    | <_UILabelContentLayer: 0x283fa0da0> (layer)
   |    |    |    |    | <UIButton: 0x11bd37fc0; frame = (269 20; 145 49); opaque = NO; autoresize = LM; layer = <CALayer: 0x283f52600>>
   |    |    |    |    |    | <UIButtonLabel: 0x11be427b0; frame = (15 16; 115 17); text = '\u7e41\u9ad4\u4e2d\u6587\uff08\u81fa\u7063\uff09'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x281c45950>>
   |    |    |    |    |    |    | <_UILabelContentLayer: 0x283fa0d20> (layer)`
cy# pvcs()     //打印当前页面的控制器
"<MMUINavigationController 0x11c0f3e00>, state: appeared, view: <UILayoutContainerView 0x11bd48310>\n   | <WCAccountLoginFirstViewController 0x11c87ae00>, state: appeared, view: <UIView 0x11bd24df0>"
cy# pactions(#0x11be35910)      //获取对象的action
"<WCAccountLoginControlLogic: 0x281c4a8a0> onFirstViewLogin"
cy# rp(#0x11be35910)      //获取对象的响应者
`<FixTitleColorButton: 0x11be35910; baseClass = UIButton; frame = (20 18; 177 47); clipsToBounds = YES; opaque = NO; autoresize = RM; layer = <CALayer: 0x283f71040>>
<UIView: 0x11be12b70; frame = (0 651; 414 65); autoresize = W+TM; layer = <CALayer: 0x283f70fc0>>
<UIView: 0x11bd24df0; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x283f749a0>>
<WCAccountLoginFirstViewController: 0x11c87ae00>
<UIViewControllerWrapperView: 0x11bd601d0; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x283fa09e0>>
<UINavigationTransitionView: 0x11be2c9b0; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x283f65300>>
<UILayoutContainerView: 0x11bd48310; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x2831cb0f0>; layer = <CALayer: 0x283f7d380>>
<MMUINavigationController: 0x11c0f3e00>
<iConsoleWindow: 0x11bd49860; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x2831f62b0>; layer = <UIWindowLayer: 0x283f7e320>>
<UIWindowScene: 0x11be11c40; scene = <FBSSceneImpl: 0x28113c500; identifier: sceneID:com.ttt.jinxiao-default>; persistentIdentifier = 62B17F00-49F3-4938-80BC-83289F774DF4; activationState = UISceneActivationStateForegroundActive; settingsCanvas = <UIWindowScene: 0x11be11c40>; windows = (
    "<iConsoleWindow: 0x11bd1a530; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x2831a7600>; layer = <UIWindowLayer: 0x283f1dee0>>",
    "<iConsoleWindow: 0x11bd49860; baseClass = UIWindow; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x2831f62b0>; layer = <UIWindowLayer: 0x283f7e320>>",
    "<UITextEffectsWindow: 0x11be3cc90; frame = (0 0; 414 736); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x283fb3f00>>"
)>
<UIApplication: 0x11bd16880>
<MicroMessengerAppDelegate: 0x28032ef00>`

MonkeyDevMDConfig.plist文件中,里面有链接,打开可以看到上面的命令其实都是已经封装好的

cy文件的封装

1. 在MonkeyDev中新建一个空的文件,命名test.cy
2. 在Build Phases->Copy Files中添加test.cy文件


3. 将test.cy文件类型改为 javaScript Source类型,撸代码,可以参考mjcript
4. 运行项目,终端调用
$ sh cylogin.sh
cy# @import test
{}
cy# MJAppId
@"com.ttt.jinxiao"
...

里面封装了很多命令就不一一演示了

上一篇下一篇

猜你喜欢

热点阅读