Imrazor's Blog

Stay Hungry, Stay Foolish

使用lldb和Hopper破解Reveal的试用限制

本文仅供学习和交流,如有侵权或不妥,请联系我删除

之前写了篇lldb联机调试的文章,恰好Reveal的试用到期了,于是拿来练练手。本文参考了“[原创]破解Reveal购买提示框”,但是去掉了“Free trial has ended” :),并假设你已经了解了一些lldb的基本调试命令

首先用Hopper分析Reveal源程序,搜索关键字trial,首先发现了IBATrialModeReminderPresenter

用lldb调试下,断点在图中内存地址中

(lldb) target create "/Applications/Reveal.app"
Current executable set to '/Applications/Reveal.app' (x86_64).
(lldb) b -a 0000000100094180
Breakpoint 1: address = 0x0000000100094180
(lldb) r
Process 4255 launched: '/Applications/Reveal.app/Contents/MacOS/Reveal' (x86_64)
2014-10-20 19:40:37.548 Reveal[4255:d0b] Unknown class          IBAViewHierarchyCanvasSharingMenu in Interface Builder file at path /Applications/  Reveal.app/Contents/Resources/en.lproj/MainMenu.nib.
2014-10-20 19:40:37.554 Reveal[4255:d0b]  INFO: Log Level Enabled
2014-10-20 19:40:37.554 Reveal[4255:d0b]  WARN: Log Level Enabled
2014-10-20 19:40:37.554 Reveal[4255:d0b] ERROR: Log Level Enabled
2014-10-20 19:40:37.574 Reveal[4255:d0b]  INFO: Reveal Automatic Updates are    enabled!
2014-10-20 19:40:37.862 Reveal[4255:d0b] [HockeySDK] WARNING: Detecting crashes is  NOT enabled due to running the app with a debugger attached.
2014-10-20 19:40:37.863 Reveal[4255:d0b]  INFO: Reveal Crash Reporting is enabled!
Process 4255 stopped
* thread #1: tid = 0x3abbf, 0x0000000100094180  Reveal`___lldb_unnamed_function3544$$Reveal, queue = 'com.apple.main-thread', stop reason   = breakpoint 1.1
    frame #0: 0x0000000100094180 Reveal`___lldb_unnamed_function3544$$Reveal
Reveal`___lldb_unnamed_function3544$$Reveal:
-> 0x100094180:  pushq  %rbp
   0x100094181:  movq   %rsp, %rbp
   0x100094184:  leaq   0xa05c5(%rip), %rsi       ; { /usr/lib/ libobjc.A.dylib`objc_msgSend_fixedup, "alloc" }
   0x10009418b:  callq  *0xa05bf(%rip)            ; { /usr/lib/ libobjc.A.dylib`objc_msgSend_fixedup, "alloc" }

至此Reveal启动,并进入了断点,si和ni都是一步步调试,直接finish单步跳出,第一次的内存地址100095f96中没什么太有用的信息,但是所在的类是IBATrialModReminderPresenter中,说明我们很进了…

(lldb) finish
Process 4255 stopped
* thread #1: tid = 0x3abbf, 0x0000000100095f96  Reveal`___lldb_unnamed_function3586$$Reveal + 94, queue = 'com.apple.main-thread', stop     reason = step out
    frame #0: 0x0000000100095f96 Reveal`___lldb_unnamed_function3586$$Reveal + 94
Reveal`___lldb_unnamed_function3586$$Reveal + 94:
-> 0x100095f96:  movq   %rbx, %r13
   0x100095f99:  movq   %rax, %rdi
   0x100095f9c:  callq  0x1000a0596               ; symbol stub for:    objc_retainAutoreleasedReturnValue
   0x100095fa1:  movq   0x67400(%rip), %r15       ; (void *)0x00007fff8f6d10d0:     objc_release
(lldb) finish
Process 4255 stopped
* thread #1: tid = 0x3abbf, 0x000000010009614e  Reveal`___lldb_unnamed_function3588$$Reveal + 66, queue = 'com.apple.main-thread', stop     reason = step out
    frame #0: 0x000000010009614e Reveal`___lldb_unnamed_function3588$$Reveal + 66
Reveal`___lldb_unnamed_function3588$$Reveal + 66:
-> 0x10009614e:  movq   %r14, %rdi
   0x100096151:  popq   %rbx
   0x100096152:  popq   %r14
   0x100096154:  popq   %rbp

再次finish,查看内存地址10009614e,这次发现了关键方法@selector(shouldShowTrialModeSheet):

不得不感慨老外起的方法名实在是太好了…进入到shouldShowTrialModeSheet方法中,处理下代码,会看到是这样的:

看代码,应该是通过日期进行了各种判断,来检测用户的试用是否过期了,关键变量rax如果要是为true,那么就不会进第一个if中,而rbx的又是0x0,那到最后rax一定会是0x0,也就是NO了,这个函数返回NO,那么启动时,过期提示框必然不会显示了

于是问题的关键集中在rax的第一次赋值,rax = sub_10009403c();搜索此方法并处理,看到是这样的:

我的汇编水平可以说是战斗力不到5的渣渣,然是还是看出来cmp这行是判断var_8与0x0是不是相等,那么如果三目运算符是真,rbx必然是0xff,rax也必然是真了。看来,只需要将这行的0x0改成0x1即可

使用UltraEdit在16进制下打开源码,找到对应的位置,即内存地址94060这里,然后查看这行对应的16进制编码:

找到E8后面的00,改成01,保存后重启Reveal,过期提示就去掉了

因为我也是刚用lldb没多久,汇编又比较渣,如有错误,欢迎大家指正

Comments