本文仅供学习和交流,如有侵权或不妥,请联系我删除
之前写了篇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没多久,汇编又比较渣,如有错误,欢迎大家指正