放牧代码和思想
专注自然语言处理、机器学习算法

OSX app逆向入门

目录

换到OSX快两个月了,装了个Hopper,回忆起N年前破解某游戏的美好时光,不禁手痒难耐,忍不住拿了某常用Android模拟器试刀。在Windows下已经有人用各种手法干掉了它,OSX上估计还算首次吧。

该模拟器未注册时付费功能按钮是锁定的,且左下角有一个难看的水印。该app是用QT开发的,方便跨平台,也方便借鉴前人的思路。

解锁按钮

首先依然是找字符串,按钮锁定无非是enable之类的函数,丢进去看看:

找字符串.png

发现有个函数很可疑:

                     sub_1000ce0b0:
00000001000ce0b0         push       rbp                                         ; XREF=sub_1000ce0a0+5
00000001000ce0b1         mov        rbp, rsp
00000001000ce0b4         push       r14
00000001000ce0b6         push       rbx
00000001000ce0b7         sub        rsp, 0x30
00000001000ce0bb         mov        r14, rdx
00000001000ce0be         mov        rbx, rdi
00000001000ce0c1         mov        edx, ecx                                    ; argument #3 for method sub_1000d0900
00000001000ce0c3         call       sub_1000d0900
00000001000ce0c8         lea        rax, qword [ds:0x10080b9c0]
00000001000ce0cf         lea        rcx, qword [ds:rax+0x10]
00000001000ce0d3         mov        qword [ds:rbx], rcx
00000001000ce0d6         add        rax, 0x1d8
00000001000ce0dc         mov        qword [ds:rbx+0x10], rax
00000001000ce0e0         mov        qword [ds:rbx+0x50], r14
00000001000ce0e4         mov        esi, 0x1
00000001000ce0e9         mov        rdi, rbx
00000001000ce0ec         call       imp___stubs___ZN15QAbstractButton12setCheckableEb ; QAbstractButton::setCheckable(bool)
00000001000ce0f1         xor        esi, esi
00000001000ce0f3         mov        rdi, rbx
00000001000ce0f6         call       imp___stubs___ZN15QAbstractButton10setCheckedEb ; QAbstractButton::setChecked(bool)
00000001000ce0fb         lea        rdx, qword [ds:0x10077c5ce]                 ; "2activationChanged(bool)"
00000001000ce102         lea        r8, qword [ds:0x10077c5e7]                  ; "1widgetActivationChanged(bool)"
00000001000ce109         lea        rdi, qword [ss:rbp+var_18]
00000001000ce10d         xor        r9d, r9d
00000001000ce110         mov        rsi, r14
00000001000ce113         mov        rcx, rbx
00000001000ce116         call       imp___stubs___ZN7QObject7connectEPKS_PKcS1_S3_N2Qt14ConnectionTypeE ; QObject::connect(QObject const*, char const*, QObject const*, char const*, Qt::ConnectionType)
00000001000ce11b         lea        rdi, qword [ss:rbp+var_18]
00000001000ce11f         call       imp___stubs___ZN11QMetaObject10ConnectionD1Ev ; QMetaObject::Connection::~Connection()
00000001000ce124         xor        esi, esi                                    ; argument #2 for method sub_1000ce240
00000001000ce126         mov        rdi, rbx                                    ; argument #1 for method sub_1000ce240
00000001000ce129         call       sub_1000ce240
00000001000ce12e         lea        rdx, qword [ds:0x10077c454]                 ; "2toggled(bool)"
00000001000ce135         lea        r8, qword [ds:0x10077c606]                  ; "1buttonToggled(bool)"
00000001000ce13c         lea        rdi, qword [ss:rbp+var_20]
00000001000ce140         xor        r9d, r9d
00000001000ce143         mov        rsi, rbx
00000001000ce146         mov        rcx, rbx
00000001000ce149         call       imp___stubs___ZN7QObject7connectEPKS_PKcS1_S3_N2Qt14ConnectionTypeE ; QObject::connect(QObject const*, char const*, QObject const*, char const*, Qt::ConnectionType)
00000001000ce14e         lea        rdi, qword [ss:rbp+var_20]
00000001000ce152         call       imp___stubs___ZN11QMetaObject10ConnectionD1Ev ; QMetaObject::Connection::~Connection()
00000001000ce157         mov        rcx, qword [ds:rbx+0x50]
00000001000ce15b         lea        rdx, qword [ds:0x10077c61b]                 ; "2buttonEnabled(bool)"
00000001000ce162         lea        r8, qword [ds:0x10077c630]                  ; "1setEnabled(bool)"

这家伙在调用setEnable,八成不是好事。看看谁在调它:

hopper引用.png

跳转到这个函数:

================ B E G I N N I N G   O F   P R O C E D U R E ================



                     sub_1000ce0a0:
00000001000ce0a0         push       rbp                                         ; XREF=sub_1000d4e80+494, sub_1000d4e80+785, sub_1000d4e80+1103, sub_1000d4e80+1427, sub_1000d4e80+1751, sub_1000d4e80+2075, sub_1000d4e80+2399, sub_1000d4e80+2723
00000001000ce0a1         mov        rbp, rsp
00000001000ce0a4         pop        rbp
00000001000ce0a5         jmp        sub_1000ce0b0
                        ; endp
00000001000ce0aa         nop        word [ds:rax+rax]

发现好多地方都在调它:

调用者.png

看看它们都传了些什么参数,拿第一个举个例子:

00000001000d5030         lea        rdi, qword [ds:0x10077ca8f]                 ; "battery"
00000001000d5037         mov        esi, 0x7
00000001000d503c         call       imp___stubs___ZN7QString16fromAscii_helperEPKci ; QString::fromAscii_helper(char const*, int)
00000001000d5041         mov        qword [ss:rbp+0xffffffffffffff98], rax
00000001000d5045         mov        edi, 0xb8
00000001000d504a         call       imp___stubs___Znwm                          ; operator new(unsigned long)
00000001000d504f         mov        rbx, rax
00000001000d5052         xor        edx, edx
00000001000d5054         mov        rdi, rbx
00000001000d5057         mov        rsi, r15
00000001000d505a         call       sub_1000e93d0
00000001000d505f         lea        rsi, qword [ss:rbp+0xffffffffffffff98]
00000001000d5063         mov        ecx, 0x3
00000001000d5068         mov        rdi, r12
00000001000d506b         mov        rdx, rbx
00000001000d506e         call       sub_1000ce0a0

似乎是针对电池按钮的,这个参数很可疑:

00000001000d5063         mov        ecx, 0x3

改为0试试:

00000001000d5063         mov        ecx, 0x0

保存为executable,发现按钮果然解锁了。于是对剩下所有的调用,都将参数改为0,就能解锁这些功能了。

不过pixelperfect按钮还是灰的,查找这个String,又发现一个调用:

00000001000d2253         lea        rsi, qword [ss:rbp+0xffffffffffffff60]      ; argument #2 for method sub_1000cf9d0
00000001000d225a         mov        edx, 0x2
00000001000d225f         mov        rdi, rbx                                    ; argument #1 for method sub_1000cf9d0
00000001000d2262         call       sub_1000cf9d0

改为

00000001000d225a         mov        edx, 0x0

就行了,至此全部功能都被强制激活了。

去水印

不过美中不足的是,左下角还残留着一行水印:

free for personal use

直接搜索这个字符串找不到任何线索,变换思维,搜索watermark,找到一个字符串id:

去水印.png

倒是没看到对应的字符值,可能跟QT的国际化有关吧。

不过我找不到原文完全没关系,让它也找不到就行了。直接将这个id的第一个字符修改为0:

空白字符串.png

这样水印对应的id就变成了空白字符串,谁也找不到原文,所以就不会显示水印了。

至此完美拿下所有功能。

hopper逆向.png

心得

  1. 逆向玩得是耐心,前面踩点很枯燥,一旦找到突破口后面就很无趣了。

  2. 在软件开发中用明文字符串简直是作死。

知识共享许可协议 知识共享署名-非商业性使用-相同方式共享码农场 » OSX app逆向入门

分享到:更多 ()

评论 2

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #1

    关注。博主目前在哪里

    ReidHolmes9个月前 (09-17)回复

我的开源项目

HanLP自然语言处理包基于DoubleArrayTrie的Aho Corasick自动机