吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 15176|回复: 37
收起左侧

[MacOS逆向] 【Mac】Hopper Disassembler系列之Sublime Text3 爆破

  [复制链接]
云在天 发表于 2018-9-7 01:24
本帖最后由 云在天 于 2018-9-7 01:28 编辑

Hopper Disassembler系列之Sublime Text 3 爆破

吾爱破解论坛首发
作者:云在天(Harry)
未经许可,请勿转载

写在前面

看到PYG有大佬在出关于Hopper 的系列视频教程,之前我也有这种想法,苦于没有找到很合适的软件去出。前几天看到有人去改Sublime Text,电脑上的这个也已经提示很久要更新,所以天时地利人和出一期这软件的爆破,并不是大佬,轻喷。

另,这个系列会不定时更新,因为刚开学,比较忙,这篇还是趁着上午没课写的。

0X1

知己知彼,百战不殆。想要破解就要找到关键点就分析,这个软件是基于注册码注册的,那我们就随意输入后看他提示什么

WX20180906-095403@2x.png

如上图,提示license不可用,有了这个字符串,我们就可以从Hopper里搜索关键字【license】

0X2

具体步骤:

  1. 打开Hopper
  2. 打开软件的目录,找到MacOS下的Sublime Text
  3. 直接拖到Hopper的右侧窗口
  4. 等待反编译完成
  5. 完成后在左侧Search输入框中输入license,点击Strings这个标签,找到刚才提示的字符串
  6. 双击这个字符串,观察右侧窗口,如下图

WX20180906-095757@2x.png

000000010063498c         db         "Hello! Thanks for trying out Sublime Text.\n\nThis is an unregistered evaluation version, and although the trial is untimed, a license must be purchased for continued use.\n\nWould you like to purchase a license now?", 0 ; DATA XREF=__ZL13show_reminderPv+10
0000000100634a61         db         "Purchase", 0                               ; DATA XREF=__ZL13show_reminderPv+17
0000000100634a6a         db         "Enter your license key below. You can purchase one from https://www.sublimetext.com/buy", 0 ; DATA XREF=__Z19show_license_windowP24text_control_environmentP21secondary_window_listP14window_factoryP12license_infoRKNSt3__18functionIFvvEEE+254
0000000100634ac2         db         "Use License", 0                            ; DATA XREF=__Z19show_license_windowP24text_control_environmentP21secondary_window_listP14window_factoryP12license_infoRKNSt3__18functionIFvvEEE+476
0000000100634ace         db         "That license key has been invalidated, due to being shared.\n\nPlease email sales@sublimetext.com to get your license key reissued.", 0 ; DATA XREF=__ZL11show_sharedPv+4
0000000100634b50         db         "That license key is no longer valid.", 0   ; DATA XREF=__ZL12show_revokedPv+4
0000000100634b75         db         "That license key doesn't appear to be valid.\n\nPlease check that you have entered all lines from the license key, including the BEGIN LICENSE and END LICENSE lines.", 0 ; DATA XREF=__ZL16show_invalid_keyPv+4
0000000100634c19         db         "Thanks for purchasing!", 0                 ; DATA XREF=__ZL11show_thanksPv+4
0000000100634c30         db         "Hello! Thanks for trying out Sublime Text 3!\n\nSublime Text 3 is a paid upgrade from Sublime Text 2, and your license key is for Sublime Text 2.\n\nWould you like to upgrade your license now?", 0 ; DATA XREF=__ZL21show_upgrade_requiredPv+10
0000000100634ced         db         "Upgrade", 0                                ; DATA XREF=__ZL21show_upgrade_requiredPv+17
0000000100634cf5         db         "Unable to write license file: ", 0         ; DATA XREF=__ZL20show_unable_to_writePv+21
0000000100634d14         db         "license_check", 0                          ; DATA XREF=__Z28live_validate_license_threadPv+37
  1. 在这个字符串上点右键,点击Reference to翻译过来就是谁引用的他,会显示一些函数,这里只有一个,双击进入,如下图

WX20180906-100123@2x.png

  1. 然后我们看这个函数的伪代码,发现只是一个提示框
    int __ZL16show_invalid_keyPv(void * arg0) {
    rax = px_show_error("That license key doesn't appear to be valid.\n\nPlease check that you have entered all lines from the license key, including the BEGIN LICENSE and END LICENSE lines.", rsi);
    return rax;
    }

    然后我们继续右键找谁引用的这个函数,发现_ZN14license_window13on_ok_clickedEv()这是个按钮事件,我们双击进入这个事件

    int __ZN14license_window13on_ok_clickedEv() {
    r14 = rdi;
    var_30 = *___stack_chk_guard;
    TextBuffer::str();
    rax = var_90 & 0xff;
    rcx = 0x1 & rax;
    rsi = var_8C;
    if (rcx != 0x0) {
            rsi = var_80;
    }
    rax = rax >> 0x1;
    if (rcx != 0x0) {
            rax = var_88;
    }
    convert_utf32_to_utf8(var_78);
    if ((var_90 & 0x1) != 0x0) {
            operator delete(var_80);
    }
    r13 = *(r14 + 0x250);
    *r13 = 0x0;
    rbx = r13 + 0x8;
    if ((*(int8_t *)(r13 + 0x8) & 0x1) == 0x0) {
            *(int16_t *)rbx = 0x0;
    }
    else {
            *(int8_t *)*(r13 + 0x18) = 0x0;
            *(r13 + 0x10) = 0x0;
    }
    std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::reserve(rbx, 0x0);
    r15 = var_C0;
    *(rbx + 0x10) = *(r15 + 0x10);
    rax = *r15;
    *(rbx + 0x8) = *(r15 + 0x8);
    *rbx = rax;
    *(r15 + 0x10) = 0x0;
    *(r15 + 0x8) = 0x0;
    *r15 = 0x0;
    rbx = r13 + 0x20;
    if ((*(int8_t *)(r13 + 0x20) & 0x1) == 0x0) {
            *(int16_t *)rbx = 0x0;
    }
    else {
            *(int8_t *)*(r13 + 0x30) = 0x0;
            *(r13 + 0x28) = 0x0;
    }
    std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::reserve(rbx, 0x0);
    *(rbx + 0x10) = *(var_A8 + 0x10);
    rax = *var_A8;
    *(rbx + 0x8) = *(var_A8 + 0x8);
    *rbx = rax;
    *(var_A8 + 0x10) = 0x0;
    *(var_A8 + 0x8) = 0x0;
    *var_A8 = 0x0;
    std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string(var_A8);
    std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string(r15);
    rcx = (var_78 & 0xff) >> 0x1;
    if ((0x1 & var_78 & 0xff) != 0x0) {
            rcx = var_70;
    }
    if (rcx != 0x0) {
            rax = *(r14 + 0x250);
            rax = apple_fruit(var_78, rax + 0x8, rax + 0x4, var_CC, rax + 0x1);
            rdi = *(r14 + 0x250);
            *(int8_t *)rdi = COND_BYTE_SET(E);
            if (rax == 0x1) {
                    std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::operator=(rdi + 0x20, var_78);
                    std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(var_F0, var_78);
                    rax = operator new(0x28);
                    *rax = 0x1007169f8;
                    *(rax + 0x18) = 0x0;
                    *(rax + 0x10) = var_E8;
                    *(rax + 0x8) = var_F0;
                    var_F0 = intrinsic_movaps(var_F0, 0x0);
                    *(int32_t *)(rax + 0x20) = var_CC;
                    var_40 = rax;
                    work_queue::push_delayed(_g_work_queue, var_60);
                    rdi = var_40;
                    if (rdi != var_60) {
                            if (rdi != 0x0) {
                                    rax = *rdi;
                                    (*(rax + 0x28))();
                            }
                    }
                    else {
                            (*(var_60 + 0x20))(var_60);
                    }
                    std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string(var_F0);
                    encode_decode_license(var_78);
                    get_license_path();
                    rax = 0x1;
                    rdi = var_107;
                    if ((var_108 & rax) != 0x0) {
                            rdi = var_F8;
                    }
                    rdx = var_78 & 0xff;
                    rax = rax & rdx;
                    rsi = var_77;
                    if (rax != 0x0) {
                            rsi = var_68;
                    }
                    rdx = rdx >> 0x1;
                    if (rax != 0x0) {
                            rdx = var_70;
                    }
                    rbx = write_file(rdi, rsi, rdx, 0x1);
                    std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string(var_108);
                    if (rbx == 0x0) {
                            rax = operator new(0x18);
                            *rax = 0x100731948;
                            *(rax + 0x8) = show_unable_to_write(void*);
                            *(rax + 0x10) = 0x0;
                            work_queue::push_delayed(_g_work_queue, rax);
                    }
                    rax = create_thread(notify_license_entered_thread(void*), sign_extend_64(var_CC));
                    pthread_detach(rax);
                    if (*(int8_t *)(*(r14 + 0x250) + 0x1) != 0x0) {
                            rax = operator new(0x18);
                            *rax = 0x100731948;
                            *(rax + 0x8) = show_upgrade_required(void*);
                            *(rax + 0x10) = 0x0;
                            work_queue::push_delayed(_g_work_queue, rax);
                    }
                    else {
                            rax = operator new(0x18);
                            *rax = 0x100731948;
                            *(rax + 0x8) = show_thanks(void*);
                            *(rax + 0x10) = 0x0;
                            work_queue::push_delayed(_g_work_queue, rax);
                    }
            }
            else {
                    if (rax != 0x4) {
                            if (rax != 0x3) {
                                    if (rax == 0x2) {
                                            rax = operator new(0x18);
                                            *rax = 0x100731948;
                                            *(rax + 0x8) = show_invalid_key(void*);
                                            *(rax + 0x10) = 0x0;
                                            work_queue::push_delayed(_g_work_queue, rax);
                                    }
                            }
                            else {
                                    rax = operator new(0x18);
                                    *rax = 0x100731948;
                                    *(rax + 0x8) = show_revoked(void*);
                                    *(rax + 0x10) = 0x0;
                                    work_queue::push_delayed(_g_work_queue, rax);
                            }
                    }
                    else {
                            rax = operator new(0x18);
                            *rax = 0x100731948;
                            *(rax + 0x8) = show_shared(void*);
                            *(rax + 0x10) = 0x0;
                            work_queue::push_delayed(_g_work_queue, rax);
                    }
            }
    }
    else {
            get_license_path();
            rdi = var_11F;
            if ((var_120 & 0x1) != 0x0) {
                    rdi = var_110;
            }
            unlink(rdi);
            std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string(var_120);
    }
    if (*(r14 + 0x2a0) != 0x0) {
            std::__1::function<void (r14 + 0x280);
    }
    r12 = *___stack_chk_guard;
    rdi = *(r14 + 0x28);
    rax = *rdi;
    rax = *(rax + 0x18);
    (rax)(rdi);
    rax = std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::~basic_string(var_78);
    if (r12 != var_30) {
            rax = __stack_chk_fail();
    }
    return rax;
    }

    代码在上面,我们大体看一看,前面都是些数据处理,我们找到刚才提示错误的那个函数,往上回溯,看

    if (rax == 0x1)
    {
        //注册成功
    }
    else
    {
        //错误代码
    }

    那这个rax怎么被赋值的呢,在往上面找

    if (rcx != 0x0) {//这个地方不需要再往上看了,因为输入错误注册码后直接跳到了错误代码那个区域,所以这个判断一定是true
            rax = *(r14 + 0x250);
            rax = apple_fruit(var_78, rax + 0x8, rax + 0x4, var_CC, rax + 0x1);//这个是rax最终的值,是一个函数返回的,那我们只要把这个rax赋值成1或者直接把这个函数的返回值设置成1就好了
            rdi = *(r14 + 0x250);
            *(int8_t *)rdi = COND_BYTE_SET(E);

    那我们继续双击这个apple_fruit进入

    //这里是个文本加密解密hash值的处理,无奈太长了,这里也不算码直接爆破,所以直接让这个函数返回1
    //这样改
    mov rax,0x1
    ret
    //只需要在函数开始处这样改就好了

    这样就改完了,怎么保存,点击File---Produce New executable 他会提示你去除签名,然后保存就好了

    写在最后

    这里只是简单的介绍了Hopper的用法,主要还是找关键字,关键Call,然后修改。还是靠逻辑。

当参数少于7个时, 参数从左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9。
当参数为7个以上时, 前 6 个与前面一样, 但后面的依次从 “右向左” 放入栈中,即和32位汇编一样。
参数个数大于 7 个的时候
H(a, b, c, d, e, f, g, h);
a->%rdi, b->%rsi, c->%rdx, d->%rcx, e->%r8, f->%r9
h->8(%esp)
g->(%esp)
call H

附上一些寄存器的值,供大家和x86对比


免费评分

参与人数 15威望 +1 吾爱币 +23 热心值 +15 收起 理由
billytoe + 1 + 1 &amp;lt;font style=&amp;quot;vertical-align: inherit;&amp;quot;&amp;gt;&amp;lt;font style=
轻狂小路 + 1 + 1 我很赞同!
ymgaoski + 1 + 1 666~~学习了
RoB1n_Ho0d + 1 热心回复!
fsrank + 1 + 1 谢谢@Thanks!
jgs + 1 + 1 谢谢@Thanks!
CcCody + 1 + 1 用心讨论,共获提升!
610100 + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
957320193 + 1 + 1 用心讨论,共获提升!
cbx5304 + 1 + 1 用心讨论,共获提升!
Hmily + 1 + 8 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
hexiaomo + 1 + 1 emmm,感谢
h080294 + 1 + 1 真棒,最近正好要开始学习maxOS
Ps出来的小赵 + 1 + 1 云姐姐又开学啦?
世夕 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

头像被屏蔽
ymgaoski 发表于 2018-9-18 16:17
提示: 作者被禁止或删除 内容自动屏蔽
世夕 发表于 2018-9-7 01:45
冰浪 发表于 2018-9-7 04:16
冰浪 发表于 2018-9-7 04:20
好东西。。
shenbl201 发表于 2018-9-7 08:13
厉害呢。
xieyao0111 发表于 2018-9-7 08:15
66666666
rebort0628 发表于 2018-9-7 08:36
这个有点意思~~~先回帖插个眼再仔细看看~~
小小学生 发表于 2018-9-7 08:48
咋一看这贴非常的耀眼 原来是版主
lovelw17 发表于 2018-9-7 09:05

感谢分享
yssun 发表于 2018-9-7 09:19
好厉害,  感谢分享。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-23 22:12

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表