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

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 15326|回复: 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

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

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

0X2

具体步骤:

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

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翻译过来就是谁引用的他,会显示一些函数,这里只有一个,双击进入,如下图

  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
3#
冰浪 发表于 2018-9-7 04:16
4#
冰浪 发表于 2018-9-7 04:20
好东西。。
5#
shenbl201 发表于 2018-9-7 08:13
厉害呢。
6#
xieyao0111 发表于 2018-9-7 08:15
66666666
7#
rebort0628 发表于 2018-9-7 08:36
这个有点意思~~~先回帖插个眼再仔细看看~~
8#
小小学生 发表于 2018-9-7 08:48
咋一看这贴非常的耀眼 原来是版主
9#
lovelw17 发表于 2018-9-7 09:05

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

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

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

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

GMT+8, 2024-5-15 15:24

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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