tree_fly 发表于 2016-10-22 00:56:54

Moom 分析记录之一(爆破篇 )- tree_fly

本帖最后由 tree_fly 于 2016-10-22 20:47 编辑

Moom 分析记录之一 爆破篇
         by   tree_fly/P.Y.G


Moom 小工具挺实用,测试地址:https://www.chinapyg.com/thread-87211-1-1.html

今天来简单的分析这款软件,首先看下未注册时状态:

这里有三点需要关注:

[*]主程序的右上角有100次的试用标记:Demo: 100 Mooms remainning
[*]注册窗口内主体文本是:this license could be yours
[*]菜单栏有Buy字样
基于这些信息,我们启动Hopper调试工具,载入app后常规查询字符串。



点击 Demo: %lu Mooms remaining此行,查看字符串调用信息,注意一些细节,比如此处有2处调用:


双击右侧边栏中第一个地址:0x100016b67,并于此处下断点:


接下来,启动hopper的调试器,开始动态分析app。

运行程序,尝试使用功能,直到中断在(RIP指向)刚才设置的断点处。
中间可能出现这样的画面,忽略,继续运行即可。


调试器的左下角已显示目前的调用栈内容,除此之外,也可以用lldb的bt命令来显示:



bt
* thread #1: tid = 0x527df, 0x0000000100016b67 Moom`- + 1042, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x0000000100016b67 Moom`- + 1042
    frame #1: 0x00007fffb3d8303d libsystem_trace.dylib`_os_activity_initiate + 61
    frame #2: 0x00007fff9cebb4e7 AppKit`- + 456
    frame #3: 0x00007fff9ca0b245 AppKit`- + 86
    frame #4: 0x00007fff9ca0b16d AppKit`__26-_block_invoke + 136
    frame #5: 0x00007fffb3d8303d libsystem_trace.dylib`_os_activity_initiate + 61
    frame #6: 0x00007fff9ca0b0c5 AppKit`- + 128
    frame #7: 0x00007fff9ca4d92a AppKit`- + 98
    frame #8: 0x00007fffb3d8303d libsystem_trace.dylib`_os_activity_initiate + 61
    frame #9: 0x00007fff9ca09a58 AppKit`- + 2481
    frame #10: 0x00007fff9ca4d667 AppKit`- + 785
    frame #11: 0x00007fff9ca084c8 AppKit`- + 832
    frame #12: 0x00007fff9d01b73d AppKit`- + 6341
    frame #13: 0x00007fff9d017f8c AppKit`- + 1942
    frame #14: 0x00007fff9d01742a AppKit`- + 541
    frame #15: 0x00007fff9ceb7bf5 AppKit`- + 1145
    frame #16: 0x0000000100022412 Moom`- + 630
    frame #17: 0x00007fff9c79e009 AppKit`- + 1002
    frame #18: 0x00007fff9c768a8a AppKit`NSApplicationMain + 1237
    frame #19: 0x00000001000012b8 Moom`start + 52

根据堆栈信息, frame #0 以下的都没有什么好分析的,重点分析PMMainController updateReminder...,
粗略分析发现:
char -

    if (_PMHasValidCertificate(var_29, var_38, sign_extend_64(r14), var_40, r13) != 0x0) {
            r15->numberOfTrialRunsLeft = 0xffffffffffffffff;
            ;
            rbx = r15->licenseBottomStatusField;
            var_60 = @selector(mainBundle);
            var_68 = @selector(localizedStringForKey:value:table:);
            rcx = @"";
            r8 = 0x0;
            rdx = [ localizedStringForKey:@"Thank You" value:rcx table:r8];
            ;
            if (var_50 != 0x0) {
                  r8 = 0x0
                  ;
                  var_54 = r12;
                  r12 = ;
                  rbx = [[[[@"~/Library/Preferences" stringByExpandingTildeInPath] stringByAppendingString:@"/.byhost.spo", rcx, r8] stringByAppendingString:@"tli", rcx, r8] stringByAppendingString:@"ght.mdquery", rcx, r8];
                  rdx = rbx;
                  if ( != 0x0) {
                            rcx = 0x0;
                            rdx = rbx;
                            ;
                  }
                  rbx = r15->licenseMainStatusField;
                  rax = var_40;
                  if ( != 0x0) {
                            r13 = rax;
                  }
                  ;
                  rbx = r15->licenseTopStatusField;
                  rax = ;
                  rax = ;
                  ;
                  rax = ;
                  ;
            }
    }
    else {

            if (r13 != 0x0) {
                  r14 = r13;
                  r13 = r15->licenseMainStatusField;
                  rax = _objc_msgSend(@class(NSBundle), var_60, rdx);
                  rax = _objc_msgSend(rax, var_68, @"This license could be yours", @"", 0x0);
                  rdi = r13;
                  r13 = r14;
                  _objc_msgSend(rdi, r12, rax);
                  _objc_msgSend(r15->licenseTopStatusField, r12, @"Moom");
                  rax = ;
                  ;
            }
    }
   



发现一个关键跳转,取决于函数_PMHasValidCertificate返回值。
继续分析:


首先,第一个要注意的函数:
int _PMSimulateExpiredDemo() {
    rax = [ boolForKey:@"PMDebugSimulateExpiredManyTricksDemo"];
    return rax;
}
检测试用是否过期,那么简单修改返回值为0(False)是否就可以了呢?想想要操作100次,还是算了。
第二个关键的函数:_PMValidPersistentCertificateDictionary
字面意是检测本地证书是否有效,如果有效,读取用户名和邮箱地址等信息,否则就是试用情况了。
那么先来看看是如何处理试用100次的问题。
loc_10000257d:
    r14 = [[[[@"~/Library/Preferences" stringByExpandingTildeInPath]
      stringByAppendingString:@"/.byhost.spo"] stringByAppendingString:@"tli"]
         stringByAppendingString:@"ght.mdquery"];
    rax = ;
    rax = ;
    rax = ;
    r12 = 0x0;
    if (rax >= 0x0) { r12 = rax;}
    if (var_34 != 0x0) {
            r12 = r12 + 0x1;
            rax = ;
            rax = ;
            ;
    }
    goto loc_10000265f;
很显然是读和写本地配置文件,简单提取一下文件的路径:
~/Library/Preferences/.byhost.spotlight.mdquery
动态调试验证,在地址00000001000025cc处下断点,中断后,输入lldb命令:po $rax 可读出路径信息:
文件内容是什么?Last login: Fri Oct 21 21:57:44 on ttys000
➜~ cat ~/Library/Preferences/.byhost.spotlight.mdquery
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
      <key>c</key>
      <integer>2</integer>
</dict>
</plist>
➜~ 这里的c就是count的意思喽,2是已使用的次数。

就目前已获取的信息,可以采用“清零递增值”的方法来固定使用次数,达到无次数限制。
如何patch呢?这里有一种方法:


inc r12
//改成
mov r12,r12

如果手动修改了配置文件,使得c>=100,会如何?


app弹窗提醒了!

综上,所以修改计步器初始值0,递增值0,并补一刀设置检测过期函数返回值为0,即可爆破成功!


将修改后的主程序,替换原主程序,重新打开App。


弹窗提醒出错,看来有程序自校验,根据字符串搜索定位到关键位置:



继续搜索applicationDidFinishLaunching方法,



分析这几段代码,可以发现这个关键函数:_PMCheckBundleSignature


他的伪代码是这样的:


这里调用了这些相关函数:
SecStaticCodeCreateWithPath()
SecStaticCodeCheckValidity();
SecCodeCopySelf()
SecRequirementCreateWithString()
SecCodeCheckValidity()


可以不用处理这些子函数,直接修改_PMCheckBundleSignature的返回值为 1 即可。
再次测试弹窗消失。

以上是Moom的爆破方案,先写到这里。
下一篇将从分析Moom的注册证书采用的RSA、SHA1加密等细节以及伪造数据和如何HOOK关键函数优雅破解等讲起,欢迎阅读哦~




cxj98 发表于 2016-10-22 05:50:16

不懂啊,这是啥?

飘云 发表于 2016-10-22 08:30:51

不错!精华了!

[PYG]版务督察 发表于 2016-10-22 08:38:43

赞。
如果inc变成Dec,应该也可以吧。这样与100就成南辕北辙了。
不过用mov感觉更简单,更安全!

飘云 发表于 2016-10-22 08:40:25

版务督察 发表于 2016-10-22 08:38
赞。
如果inc变成Dec,应该也可以吧。这样与100就成南辕北辙了。
不过用mov感觉更简单,更安全!

dec会变成负数。取决于作者用了有符号还是无符号来处理返回值!

[PYG]版务督察 发表于 2016-10-22 09:05:52

飘云 发表于 2016-10-22 08:40
dec会变成负数。取决于作者用了有符号还是无符号来处理返回值!

对。
所以还是Mov的用法更安全!

qq939595 发表于 2016-10-22 10:29:23

支持飞树大神!

0xcb 发表于 2016-10-23 00:21:02

赞,还是伪代码读着舒服

lhglhg 发表于 2016-10-23 08:53:12

区待下一篇文章、、、

不一样的烟火 发表于 2016-10-23 21:25:18

谢谢分享,学习了!!!
页: [1] 2 3
查看完整版本: Moom 分析记录之一(爆破篇 )- tree_fly