iOS-逆向18-Cycript

2021-06-26  本文已影响0人  一亩三分甜

《iOS底层原理文章汇总》
上一篇文章《iOS-逆向17-LLDB》介绍了LLDB,本文介绍虚拟内存、Chisel、LLDB和Cycript。

早期的计算机没有虚拟内存的概念,直接将整个应用程序放入内存中,随着计算机的发展,有些应用程序里面的资源文件较多,会占用过多内存,导致内存不够用。也容易被外挂程序找到其他应用程序的内存地址,能很轻松很容易的跨进程访问。

虚拟内存

LLDB调试时,两个相同的内存地址,在不用的应用程序中表示的值不同,
一个应用程序,一个进程,一个表
通过表翻译指向分配的物理地址上
两个相同的LLDB调试内存地址访问的真实的物理地址是不一样的,应用程序和内存地址完全的阻隔开
每个进程4G,从上到下是0->4G,从上到下是栈空间,从下到上是堆空间,0-4G的空间随便用,也是规则,你的内存地址4G只能在这个范围内,但并不是说就全部用了,全部映射到物理内存中可能会报内存警告,为了让与其他应用隔开,是一张映射表只占用如1MB空间,0-4G空间假的只是一个范围并不是真正拥有4G的空间
PAGEZERO表示起始位置是4G0x100000000,在PAGEZERO0x100000000之前是32位的,PAGEZERO隔开32位和64位,所有的位置是从4G开始

直接访问物理地址的劣势:
1.安全问题,能访问别人的进程
2.内存不够用的问题


虚拟内存

页表:存放在内存条中,进程加载生成页表

用户可能没有一下子将一个应用程序的全部功能都用到,应用程序活跃的功能只用到了一部分代码,很大一部分数据是没有用到的
内存分页管理,iOS中一页数据16Kb,映射到内存中的某个区,以页为单位划分
MachO文件在内存中分了很多页,启动时只加载用到的页数到内存条,读取MachO头文件,操作系统生成页表,读出头后,读main函数,开始执行,先访问虚拟的页表
CPU通过地址访问汇编代码去执行
一开始所有的应用程序数据都是没有被加载的

虚拟内存分页加载过程

虚拟内存没加载到物理内存会触发中断,让程序停下来
若第5页的代码没有加载到内存
会触发PageFault中断
操作系统从磁盘中将对应的这一页数据载入到物理内存条里面
去,让程序继续执行,不断通过地址翻译找到这一页数据的
物理内存
第一页第三页第五页在物理内存上到处随机分布的
两个进程的页在物理虚拟内存上不可能有交集

CPU上有两个硬件加速查表和地址翻译过程
MMU地址翻译,
高速缓存,不是每一次都去查表
缺页中断会真真实实影响速度,耗时,毫秒级别用户体会不到,程序停下来去加载数据,二进制重排是尽量减少缺页中断


image

物理内存都是满的,只会覆盖掉物理内存上最不活跃的那一页数据,分页的好处:之前空下来的物理内存空间是零散的,每次加载新的一页都要挪动活动的内存,整出一块足够的空间的大小
解决了内存不够用的问题:每一个应用可能只加载了几页,没有全部加载进物理内存,不用不加载,用了才加载

常驻进程

苹果给了特殊的权限,在物理内存中申请常驻进程,就不会被其他进程覆盖,比如将抖音放入常驻进程,抖音会一直饱和在后台

ASLR:添加ASLR(地址空间配置随机加载),虚拟内存本来以0开始,容易被篡改,添加ASLR后无法篡改,模拟之前在物理内存上随机分配的情况

新建工程验证ASLR和OffSet

image

0x5d58为文件的offSet偏移地址----File OffSet
0x100005d58位文件的虚拟内存地址----VM ADDRESS
求方法-(void)eatWithObject:(NSString *)objc的运行内存地址,并下断点
运行地址= ASLR(0x04910000)+PAGEZERO(0x100000000)+文件偏移地址offset(0x5d58)=0x0000000104910000 + 0x5d58 = 0x104915D58


image

根据此地址设置断点


image

验证数据在MachO文件中的Data段
a的虚拟内存地址0x0000000100999610 - (PAGEZERO+ASLR)0x0000000100990000 = 0x9610 Offset


image

在MachO文件中Data段查找0x9610对应的值


image

插件Chisel

1.安装步骤

I.安装chisel brew install chisel
II.在根目录中配置脚本vim .lldbinit
III.重新启动Xcode生效


image

之前查看视图层级,lldb执行命令po [self.view recursiveDescription]
安装插件后直接pviews self.view
查看上一级图层pviews -u self.view可以清晰看到图层结构层级
直接使用pviews也可以看到


image

2.通过chisel查看微信项目

图片.png
图片.png

查看导航控制器pvc


图片.png
查看父类和继承关系

pclass 地址
pmethods 类有哪些方法
pinternals 查看有哪些成员属性


image
通过按钮找到所属的控制器
image
fvc -v 0x153f12090
找到所有的类WCUITextField
fv WCUITextField
image

定位到某一个控件,比如注册按钮,就会闪一下
flicker 0x116582b80


image
进入控件调试模式
vs FixTitleColorButton
image
Use the following and (q) to quit.
(w) move to superview 移动到父控件
(s) move to first subview 移动到第一个子视图
(a) move to previous sibling 移动到父控件的subviews的前一个
(d) move to next sibling 移动到父控件的subviews的后一个
(p) print the hierarchy 打印图层
图片.png

官网中有超详细的命令使用说明,也可通过--help方式查看

image
(lldb) pviews --help
Usage:  [options]

Options:
  -h, --help            show this help message and exit
  -u, --up              Print only the hierarchy directly above the view, up
                        to its window.
  -d DEPTH, --depth=DEPTH
                        Print only to a given depth. 0 indicates infinite
                        depth.
  -w WINDOW, --window=WINDOW
                        Specify the window to print a description of. Check
                        which windows exist with "po (id)[[UIApplication
                        sharedApplication] windows]".
  -s, --short           Print a short description of the view
  -m, --medium          Print a medium description of the view

插件[LLDB] (https://github.com/DerekSelander/LLDB)

1.官网clone下来后,放入系统目录下的opt文件夹中

image
2.配置.lldbinit文件
command script import /opt/LLDB/lldb_commands/dslldb.py
image

重新运行微信项目
全局搜索UIView


图片.png

给WCAccountLoginControlLogic中方法onFirstViewRegister下断点,去符号了断点下不住


图片.png
通过地址下符号断点b -a 0x105ea0e9c
image
bt看不到符号,sbt能看到符号
image

以上通过View Debugger找到注册按钮的方法,其实完全可以通过pviews, vc view地址,一步一步通过w s a命令的执行一步一步找到注册按钮的方法的地址,search所在的类,执行methods 控制器类所在的地址,进而找到注册按钮响应方法

插件Cycript

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

1.下载直接执行若报错,将Monkey中的cycript拷贝过来替换,能成功执行

dyld: Library not loaded: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/libruby.2.0.0.dylib
  Referenced from: /Users/cloud/Downloads/cycript_0.9.594/./Cycript.lib/cycript-apl
  Reason: image not found
image

2.复制替换好的cycript_0.9.594文件夹到系统opt目录中

image
3.配置环境变量export CY=/opt/cycript_0.9.594,有Monkey就不用配置CY,Monkey中自带了CY,配置好后在任意路径下cycript即可进入,Ctrl + D退出
image

Monkey重签的App包中注入了libcycript.dylib,当前进程可以调用库里面的一些方法开启相应的端口,让别人监听,别人可通过端口连接当前进程,进入cy环境,hook当前进程里面的数据

1.连接手机Ip地址cycript -r 172.20.190.37:6666
应用切入前台自动进入cy环境,默认dylib监听的是6666的端口号,WiFi地址对应的设备的终端端口


image

2.常用语法

[UIApplication sharedApplication]
var keyWd = UIWindow.keyWindow()
keyWd.rootViewController
*keyWd 查询成员变量


图片.png

Cmd+K清屏
查看层级视图keyWd.recursiveDescription()


图片.png
keyWd.recursiveDescription().toString()查看层级关系
image
image
退出后重新进入cy,定义的变量keyWd还在,杀掉进程后变量就不在了,cy连接的是手机上当前活跃的进程。
上一篇下一篇

猜你喜欢

热点阅读