macOS逆向之超级右键无限期试用
- 注意事项:此文仅限于技术交流,请不要做违法的事情。对于那些居心叵测的人根据此文造成违法的事情与本人无关。此文章不得转载!!!如果APP方需要删除,请发邮件
[email protected]
,谢谢。 - 推荐先阅读 macOS逆向之跳过XtraFinder试用界面 ,这篇文章各种工具的使用介绍的更详细。
- 开发环境:macOS11.2.3、Xcode11.7、IDA7.0、class-dump、超级右键2.1.9(写这篇文章时的最新版)
- 具备技能:X64汇编基础、OC基础知识、iOS逆向基础知识
- 为什么使用:
- macOS系统本身并不支持右键新建文件,本人每次通过
iTerm2
,使用touch
命令新建文件,这样就很麻烦,效率很低。cd 目标目录 touch test.txt touch test.md
- 如果要用
VSCode
打开一个文件夹,需要首先打开VSCode
,然后再从里面选取对应的文件夹。一两次操作还行,次数多了,真的是浪费时间。 - 超级右键是macOS上最强大的右键菜单管理工具,拥有丰富的功能,可以提升使用体验。针对上面两个问题,超级右键一键解决,看下图是不是很爽。
- macOS系统本身并不支持右键新建文件,本人每次通过
- 目标结果:使用了一段时间,正爽的时候,突然给你来个弹框,提示你试用到期了,让你付费使用。作为一个技术,难道还能被技术难住了,于是走向了逆向之路。
分析界面
- 新建一个macOS App项目,用来调试超级右键界面。如下图所示,发现购买弹框是一个
NSWindow
类对象,名字叫BuyWindows
- 从
/Applications/iRightMouse.app/Contents/MacOS
拷贝出二进制文件iRightMouse
,拖到IDA里面进行分析。看来已经适配了M1
机型,本人还是老式处理器,所以直接选择x86_64
架构进行分析。
- 分析完毕后,打开
Strings window
窗口,搜索buy
时,已经出现了如下结果
- 双击
buyProWindow
进去后,使用x
查看引用关系,发现购买窗口其实是AppDelegate
的一个成员变量__objc2_ivar <offset _OBJC_IVAR_$_AppDelegate_buyProWindow, \ ; NSWindow *buyProWindow;
- 在IDA里面搜索
buyProWindow
并没有搜索到,用class-dump
导出iRightMouse
头文件,找到AppDelegate.h
发现有这个成员变量,没有深究原因。分析到这里后,可以确定弹框操作就是在AppDelegate
里面执行的。整个弹框过程应该是这样的:当新建某个文件或要把某个目录在VSCode
中打开时,会首先判断试用到期了没有,如果到期了,就[self->buyProWindow showMethod]
显示弹框。
分析弹框
- 为了不让购买弹框显示出来,我们需要判断哪里进行了弹框操作。
if (!isOutOfDate) { // 如果试用没有到期 // 正常使用,不弹框 } else { // 弹框 }
- 显示弹框就是显示一个window,在iOS中是需要调用
makeKeyAndVisible
方法的,而本人并没有做过macOS开发,不知道在macOS显示window,需要探究一下。[self.window makeKeyAndVisible]
- macOS中不是用
UIWindow
,而是用NSWindow
。使用刚才新建的项目,进入NSWindow.h
文件,发现三个与显示window有关的方法。makeKeyAndOrderFront: makeKeyWindow makeMainWindow
- 使用LLDB连接上iRightMouse,对
NSWindow
上面的三个方法进行断点,猜想会调用某个方法显示弹窗。$ lldb (lldb) attach -n iRightMouse ... (lldb) br set -n makeKeyWindow Breakpoint 2: 5 locations. (lldb) br set -n makeMainWindow Breakpoint 4: 3 locations. (lldb) br set -n makeKeyAndOrderFront: Breakpoint 5: 6 locations.
- 随意进入一个目录,然后在目录里面
右键
->进入 VSCode
或新建文件
,这个时候会命中断点。按c
后,购买弹窗就会显示出来,说明makeKeyAndOrderFront:
就是显示弹框的方法。Process 11199 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x00007fff22f7c275 AppKit` -[NSWindow makeKeyAndOrderFront:] AppKit`-[NSWindow makeKeyAndOrderFront:]: -> 0x7fff22f7c275 <+0>: push rbp 0x7fff22f7c276 <+1>: mov rbp, rsp 0x7fff22f7c279 <+4>: push r14 0x7fff22f7c27b <+6>: push rbx 0x7fff22f7c27c <+7>: mov rbx, rdi 0x7fff22f7c27f <+10>: mov rsi, qword ptr [rip + 0x65cddfca] ; "_resolveAutomaticEnterFullScreenFlags" 0x7fff22f7c286 <+17>: mov r14, qword ptr [rip + 0x5d7b1d53] ; (void *)0x00007fff203c5d00: objc_msgSend 0x7fff22f7c28d <+24>: call r14 Target 0: (iRightMouse) stopped. (lldb)
- 重复上面的步骤,当命中断点后,执行
bt
打印调用堆栈。(lldb) bt * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 * frame #0: 0x00007fff22f7c275 AppKit` -[NSWindow makeKeyAndOrderFront:] frame #1: 0x00000001026ff9c0 iRightMouse` ___lldb_unnamed_symbol423$$iRightMouse + 135 ... (lldb)
- 很明显在
0x00000001026ff9c0
调用了显示弹框的方法,这个地址是在内存中的地址,我们需要的是在Mach-O中的地址,使用如下命令打印出我们需要的地址0x000000010001f9c0
。(lldb) image lookup -a 0x00000001026ff9c0 Address: iRightMouse[0x000000010001f9c0] (iRightMouse.__TEXT.__text + 124128) Summary: iRightMouse`___lldb_unnamed_symbol423$$iRightMouse + 135 (lldb)
- 进入IDA,输入
G
,在弹框内输入0x000000010001f9c0
,点击确定后,会到以下代码出,这不正是我们需要的。LABEL_11: v14 = v8; v15 = 0LL; goto LABEL_12; } objc_msgSend((void *)self->buyProWindow, "makeKeyAndOrderFront:", self); objc_msgSend(NSApp, "activateIgnoringOtherApps:", 1LL); v9 = 0; LABEL_14: objc_release(v8); return v9; }
- 上面显示的是伪代码界面,需要按空格键切换到流程图界面,方便定位哪里进行了
判断是否过期
的操作。沿着上一步弹窗代码
一直往上找,直到遇到某个判断跳转方法的分支就停下来,最终会来到如下图所示的代码处。如果执行左边红线的代码,就会到上一步显示弹框的代码处;如果执行右边绿线的代码,就会直接执行相应的操作。
- 可以很明显发现弹窗操作是在
-[AppDelegate application:openFile:]
方法中进行的,这不正印证了上面所说的弹窗操作是在AppDelegate
里面执行的
汇编代码分析
- 上图汇编指令解析
- 指令
cmp
的意思是对两个数执行减法。当运算结果为0时,把ZF
(零标志位)置1,否则置0。 - 指令
jz
的意思是根据cmp
运算结果的值,判断执行的逻辑。如果结果为0就执行short loc_10001F9E0
,否则执行弹框操作。 - 指令
lea
是地址赋值的意思,就是把byte_100038940
这个地址值赋值给rax
.
- 指令
- 经过上面几步的分析,我们已经知道了目前是走左边红色线条的逻辑(也就是说会进行购买弹框操作),可以得出结论:
- 此时的
cmp byte ptr [rax], 0
运算结果不为0 - 此时的
byte ptr [rax]
不为0,也就是说[rax]
不为0。
- 此时的
- 我们可以使用LLDB在地址
000000010001F9A9
打断点验证一下上面的猜想- 因为并没有恢复Mach-O的符号,所以只能使用地址断点,
$ lldb (lldb) attach -n iRightMouse Executable module set to "/Applications/iRightMouse.app/Contents/MacOS/iRightMouse". ...省略很多... Architecture set to: x86_64h-apple-macosx-. (lldb) image list -o -f | grep iRightMouse [ 0] 0x0000000004560000 /Applications/iRightMouse.app/Contents/MacOS/iRightMouse (lldb) br set -a 0x0000000004560000+0x000000010001F9A9 Breakpoint 1: where = iRightMouse`___lldb_unnamed_symbol423$$iRightMouse + 112, address = 0x000000010457f9a9 (lldb) c
- 当执行相应的操作后,会命中断点,然后打印
[rax]
的值,发现此时的值为1,这不正验证了上一步我们的猜想Process 50188 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x000000010457f9a9 iRightMouse` ___lldb_unnamed_symbol423$$iRightMouse + 112 iRightMouse`___lldb_unnamed_symbol423$$iRightMouse: -> 0x10457f9a9 <+112>: cmp byte ptr [rax], 0x0 0x10457f9ac <+115>: je 0x10457f9e0 ; <+167> 0x10457f9ae <+117>: mov rdi, qword ptr [r12 + 0x8] 0x10457f9b3 <+122>: mov rsi, qword ptr [rip + 0x1b15e] ; "makeKeyAndOrderFront:" 0x10457f9ba <+129>: mov rdx, r12 0x10457f9bd <+132>: call r13 0x10457f9c0 <+135>: mov rax, qword ptr [rip + 0x10651] ; (void *)0x00007fff88569260: NSApp 0x10457f9c7 <+142>: mov rdi, qword ptr [rax] Target 0: (iRightMouse) stopped. (lldb) memory read $rax 0x10459b940: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x10459b950: 65 df 58 04 01 00 00 00 88 4c 59 04 01 00 00 00 e�X......LY..... (lldb)
- 因为并没有恢复Mach-O的符号,所以只能使用地址断点,
- 怎样让代码走右边绿色线条的逻辑(也就是说不会出现购买弹框,直接进行相应的操作)呢?上面已经分析了很多,到这里已经很简单了,让
cmp byte ptr [rax], 0
运算结果为0就可以了。从上面可以知道此时byte ptr [rax]
的值为1,所以把cmp byte ptr [rax], 0
中0更改为1,就能都达到让整个运算结尾为0的效果。
「其他文章」
- macOS逆向之超级右键无限期试用
- 破案了....
- 《kafka问答100例 -2》 创建Topic的时候 什么时候在Broker磁盘上创建的日志文件
- 钢琴入门 - 基础乐理
- Yarn管理放置规则
- Yarn在全局级别配置调度程序属性
- 使用YARN Web UI和CLI
- CDP中的Hive3系列之管理Hive的工作负载
- CDP中的Hive3系列之启动Apache Hive3
- 手机厂商和他们的“杂货铺”
- Hive on Tez 简介
- CDP私有云基础7.1.7发行说明
- CDP的Hive Metastore简介
- 【kafka运维】你真的懂数据迁移吗?(附教学视频)
- FAQ系列之Impala
- 【kafka实战】分区重分配可能出现的问题和排查问题思路(生产环境实战,干货!!!非常干!!!建议收藏)
- sync.Map实现
- WebRTC 编译指南
- 帮助小型杂货铺打通线上渠道,美国初创公司Mercato获2600万美元A轮融资
- CDP私有云基础版7.1.6版本概要