最简单的 Hopper Disassembler 玩转 Mac 逆向(简单又易理解、轻松get)

2024-06-10 16:48

本文主要是介绍最简单的 Hopper Disassembler 玩转 Mac 逆向(简单又易理解、轻松get),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

老衲看了那么多篇文章、这个不错 get一下、学习学习~

准备工作

工具下载

以下工具包括 Folx 都打包好上传网盘了,这里下载。

  • Folx 
    一个 mac 上挺好用的下载工具,本文逆向破解的对象。直接把 Folx.app 拖到 Applications 文件夹中即可。

  • mySIMBL 
    扩展包 (plug in) 管理软件,本文将要给 Folx 软件写扩展包达到破解的目的,因此使用 mySIMBL 进行扩展包管理,图形界面方便的删除、开启等功能。
    直接把 mySIMBL.app 拖到 Applications 文件夹中即可。

  • EasySIMBL-Bundle-Template 
    一个扩展包 XCode 模板,类似于开发 iOS 在 XCode 新建工程时选的 Single View App
    把 EasySIMBL Bundle.xctemplate 文件夹拖到 ~/Library/Developer/Xcode/Templates/Project Templates 目录下即可,如图所示。

EasySIMBL 安放地址

  • class-dump 
    iOS/Mac 逆向必须介绍的软件,从可执行文件中导出头文件,然而本文用不上,不做介绍。

  • Hopper Disassembler 
    超级强大的反编译软件,不仅可以把机器码解析成汇编,还能解析出相似与 Objc 的伪代码。总之就是太强大了,强大到我们几乎连 class-dump 都用不上了。本文提供了史蒂芬周的破解版本,把 Hopper Disassembler v4.app 拖进 HopperV4Patcher 即可破解,如图所示。

破解 Hopper

问题分析

Folx 有个很方便的功能下载 Youtube 视频,只要把 Youtube 视频的 URL 输入就可以下载(而且速度还不错,暂时没验证需不需要科学上网)。然而这是个付费功能,只要点下 OK 按钮就会跳出讨钱页。

Folx

Folx 叫你交保护费

听说有小伙伴因为种种原因弄不到 Youtube 的 URL?下面提供一个。

https://www.youtube.com/watch?v=QFH747sK200

逆向分析

打开 Hopper,选择 File-Read Executable to Disassemble 直接粗暴读取二进制可执行文件来破解,如图所示。

Hopper 界面

选择 Applications 文件夹中的 Folx,右键显示包内容,并找到可执行文件,类似于 win 平台的.exe 文件,在这里:

打开 Folx![Uploading 7_151717.png . . .] 可执行文件

等 Hopper 缓过神来,界面就差不多长这样。由于个人使用习惯,隐藏了底部和右边栏,可以在右上角的三个按钮选择是否开启。
左边栏是导航,可以看到使用 Objc 的方框语法列出了许多方法,还要啥 class-dump?
中间区域是汉莫拉比法典,记载了一些上古语言,讲述了一些你不需要了解的事,直接无视就行。

Hopper 界面

OK 我们的目的是要破解 YouTube 下载功能,那么把 Youtube 当做关键词来搜索应该不会错,所以在左边栏的搜索框中输入 youtube,可以得到许多和 Youtube 相关的类和方法:

搜索 Youtube

我们来猜一下这都是些什么东西。(十秒逆向九秒猜)

  • FolxYouTubeHelper:看上去没有什么特别的东西,应该不是我们要找的。
  • AppDelegate:看上去也只是一个干杂货的,负责弹框之类,应该也不是我们要找的。
  • SDUrl:看上去像是个下载辅助的东西,应该还不是我们要找的。
  • FolxNewEditTask:看上去是负责新建下载任务相关的类,估计会包含验证之类的东西,我们可以尝试从这个入手。

在搜索栏中查找 FolxNewEditTask,可以得到一整列表,这东西有点肥,看上去方法很多,其实基本每个 @Property 都有 get 和 set 两个方法。

此处无图

在 FolxNewEditTask 的方法中看到一个 done: 方法,应该是新建任务完成的方法,也就是 OK按钮的点击方法。选中该方法,一探究竟。

done 方法

在顶部栏点击伪代码按钮可以把上古语言翻译成类似于 Objc 的代码,极大提高可阅读性。代码中还保留了许多汇编的特征,例如 rbxr14 之类的寄存器,可以简单理解为变量。如果你认可我葬爱家族,那么这样的代码对你来说应该没有任何阅读压力。

伪代码按钮

得到 [FolxNewEditTask purchased] 的伪代码:

伪代码

在方法的开头就是一个判断语句,由 && 区分出两个判断条件。
前一条件首先是一个 Objc 下消息机制的方法调用,由前一句 r14 = @selector(addTaskType); 可以猜测应该是判断当前的下载类型,记得 Folx 提供了三个下载类型,而 Youtube 是第三个类型,就是 ==0x2 成立。

下载类型

后一个条件的关键词在于 purchased,这就很明显了。purchase 的消息对象是 rbx,前两句 rbx=self 可以知道 FolxNewEditTask 对象应该有个 purchased 方法,判断交没交保护费,如果交了就走 else 语句,没交的话就弹出交钱框,就是底下的 @selector(showFreeYouTubeAlert:)
不过我们的重点在于判断交保护费的方法,在左侧栏搜索,果然 FolxNewEditTask 是有这个方法,而且还有setPurchased 方法,可以推知 purchased` 应该是一个成员属性。

purchased 方法

这样我们就不用管它判断的机制是什么,只要这个方法返回 YES 就对了,办法就是把 FolxNewEditTask 的 purchased 方法换成我们自己的 purchased 方法,这样不仅是 YES,要返回大象都可以。

Hook

打开 XCode,新建一个 EasySIMBL模板工程

新建工程

工程名无所谓,最重要的是 Target App Bundle Id,也就是我们要破解的 App 的 Bundle ID,在 Folx.app 的包内容中可以找到 info.plist 文件,然后找到 Folx 的 Bundle ID。
我一般用如下结构存放文件,其中 Sources 组下存放原 App 中类的头文件,而 HookClasses 组下存放我们自制的对应类。

思维僵化的项目结构

首先在 Sources 下创建 FolxNewEditTask.h 文件,然后把里面的代码都删了,填入如下内容。

 
  1. @interface FolxNewEditTask

  2.  
  3. - (BOOL)purchased;

  4.  
  5. @end

  6.  

虽然我们创建了 FolxNewEditTask.h,假装我们知道 FolxNewEditTask 的一切,其实我们只需要知道 FolxNewEditTask 有 purchased 这么一个方法,但这就够了,因为我们只需要一个 flag。当然正经点的做法是使用 class-dump 导出.h 头文件来使用,学习 class-dump。

接着在 HookClasses 中创建 FolxNewEditTask+Hook 的.h 和.m 文件。在 FolxNewEditTask+Hook.h 文件中填入代码如下:

 
  1.  
  2. #import <Foundation/Foundation.h>

  3. #import "FolxNewEditTask.h"

  4.  
  5. @interface NSObject(FolxNewEditTaskHook)

  6.  
  7. + (void)hookFolxNewEditTask;

  8.  
  9. @end

  10.  

在 FolxNewEditTask+Hook.m 文件中填入如下代码:

 
  1. #import "FolxNewEditTask+Hook.h"

  2.  
  3. @implementation NSObject(FolxNewEditTaskHook)

  4.  
  5. + (void)hookFolxNewEditTask {

  6. NSError *error;

  7. [self jr_swizzleMethod:@selector(purchased)

  8. withMethod:@selector(banana_purchased)

  9. error:&error];

  10. if (error) {

  11. NSLog(@"+++++hookFolxNewEditTask error: %@", error);

  12. }

  13. }

  14.  
  15. - (BOOL)banana_purchased {

  16. return YES;

  17. }

  18.  
  19. @end

  20.  
  • banana_purchased 方法是我们自制的保护费管理员,不管什么情况下都会返回 YES。
  • hookFolxNewEditTask 中我们调用 jr_swizzleMethod: 方法把 FolxNewEditTask 原本的 purchased 方法和我们自制的 purchased 方法交换。

接着就是要在 Folx 程序启动的时候调用偷天换日大法。找到 Banana.m 或者你的项目名.m,里面已经提供好了 load 方法,搞 Objc 开发的都应该知道 load 方法是在类载入内存的时候调用,也是偷换方法的最佳时机。
首先得导入我们的头文件:

 
  1. #import "FolxNewEditTask+Hook.h"

  2.  

其次在 load 方法后加上一行来调用偷换方法。

[NSClassFromString(@"FolxNewEditTask") hookFolxNewEditTask];

用 command+B 来编译一下,显示 build succeeded 这样扩展就已经安装好了。我们可以打开 mySIMBL 来管理扩展。

mySIMBL 管理扩展界面

因为在扩展的方法中我们打印了一些信息,因此可以打开 Console.app 来查看,这个是系统自带程序,在 Launchpad 里找找。在 Consolo 里搜索 ++++ 来过滤其他不必要信息。

然后就是见证奇迹了,运行 Folx 吧。

在 Console 中接收到这么一条消息就表示扩展已经成功执行:

Console 接收 NSLog 信息

接下来去测试一下 Youtube 功能是不是能使用。
点击 OK 之后讨厌的讨钱窗口没有跳出来,而是直接开始下载了,那么就算破解成功了:

Folx 开始下载 Youtube 视频

根据我的猜测也有可能因为某些科学原因没法下载,因为公司都是科学上网的,所以我才不会开 4G 去验证呢。

更暴力的方法

正如标题所说,Hopper玩转Mac逆向,而没说 Mac 和 XCode 玩转 Mac 逆向。
Hopper 掌握了机器码,就拥有了生杀大权,所谓汇编、伪代码都是解析给程序员看的,虽然说使用 Hook 方法替换原方法可以自定返回值,甚至可以返回大象!但是我们不需要大象,如果只是一个 BOOL 的事,汇编的修改是不是就够了呢?
当然,首先我们在 mySIMBL 里把方才所写的 Folx 扩展禁用掉,然后把 Folx 关了,回到 Hopper 中。
依旧在左侧栏中搜索找到 [FolxNewEditTask purchased] 方法,并选择汇编代码。

选择汇编代码

其实 [FolxNewEditTask purchased] 的 Objc 代码只有一两行,对应的汇编代码其实也不长,就 7 行:

 
  1. 1. push rbp

  2. 2. mov rbp, rsp

  3. 3. mov rax, qword [objc_ivar_offset_FolxNewEditTask__purchased]

  4. 4. mov al, byte [rdi+rax]

  5. 5. movsx eax, al

  6. 6. pop rbp

  7. 7. ret

  8.  

rax 寄存器是返回值寄存器,相当于被放在 rax 里的值最后都会被 return rax;
rax 在第 3 行出现过一次,mov 指令可以理解为赋值语句,意义是将 qword [objc_ivar_offset_FolxNewEditTask__purchased] 的值赋予 rax
我们不用管 qword [objc_ivar_offset_FolxNewEditTask__purchased] 是什么,我们要的结果是 return YES,也就是 return 0x01,只需要确保在 ret 指令的时候 rax 的值是 0x01 即可。
因此选中 mov rax, qword [objc_ivar_offset_FolxNewEditTask__purchased] 一行,选择 Modify-Assemble Instruction,输入如下指令:

mov rax, 0x01  

回车

修改汇编代码

选择 File-Produce New Executable 来生成新的可执行文件 Folx,替换掉原来的文件即可。

结尾

没有结尾。



作者:喂草
链接:https://www.jianshu.com/p/c04ac36c6641
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

这篇关于最简单的 Hopper Disassembler 玩转 Mac 逆向(简单又易理解、轻松get)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1048715

相关文章

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

Python get()函数用法案例详解

《Pythonget()函数用法案例详解》在Python中,get()是字典(dict)类型的内置方法,用于安全地获取字典中指定键对应的值,它的核心作用是避免因访问不存在的键而引发KeyError错... 目录简介基本语法一、用法二、案例:安全访问未知键三、案例:配置参数默认值简介python是一种高级编

如何在Mac上彻底删除Edge账户? 手动卸载Edge浏览器并清理残留文件技巧

《如何在Mac上彻底删除Edge账户?手动卸载Edge浏览器并清理残留文件技巧》Mac上的Edge账户里存了不少网站密码和个人信息,结果同事一不小心打开了,简直尴尬到爆炸,想要卸载edge浏览器并清... 如果你遇到 Microsoft Edge 浏览器运行迟缓、频繁崩溃或网页加载异常等问题,可以尝试多种方

Mac系统下卸载JAVA和JDK的步骤

《Mac系统下卸载JAVA和JDK的步骤》JDK是Java语言的软件开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源,:本文主要介绍Mac系统下卸载JAVA和JDK的相关资料,需... 目录1. 卸载系统自带的 Java 版本检查当前 Java 版本通过命令卸载系统 Java2. 卸载自定

基于Python实现一个简单的题库与在线考试系统

《基于Python实现一个简单的题库与在线考试系统》在当今信息化教育时代,在线学习与考试系统已成为教育技术领域的重要组成部分,本文就来介绍一下如何使用Python和PyQt5框架开发一个名为白泽题库系... 目录概述功能特点界面展示系统架构设计类结构图Excel题库填写格式模板题库题目填写格式表核心数据结构

C/C++ chrono简单使用场景示例详解

《C/C++chrono简单使用场景示例详解》:本文主要介绍C/C++chrono简单使用场景示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录chrono使用场景举例1 输出格式化字符串chrono使用场景China编程举例1 输出格式化字符串示

如何确定哪些软件是Mac系统自带的? Mac系统内置应用查看技巧

《如何确定哪些软件是Mac系统自带的?Mac系统内置应用查看技巧》如何确定哪些软件是Mac系统自带的?mac系统中有很多自带的应用,想要看看哪些是系统自带,该怎么查看呢?下面我们就来看看Mac系统内... 在MAC电脑上,可以使用以下方法来确定哪些软件是系统自带的:1.应用程序文件夹打开应用程序文件夹

Mac备忘录怎么导出/备份和云同步? Mac备忘录使用技巧

《Mac备忘录怎么导出/备份和云同步?Mac备忘录使用技巧》备忘录作为iOS里简单而又不可或缺的一个系统应用,上手容易,可以满足我们日常生活中各种记录的需求,今天我们就来看看Mac备忘录的导出、... 「备忘录」是 MAC 上的一款常用应用,它可以帮助我们捕捉灵感、记录待办事项或保存重要信息。为了便于在不同

电脑蓝牙连不上怎么办? 5 招教你轻松修复Mac蓝牙连接问题的技巧

《电脑蓝牙连不上怎么办?5招教你轻松修复Mac蓝牙连接问题的技巧》蓝牙连接问题是一些Mac用户经常遇到的常见问题之一,在本文章中,我们将提供一些有用的提示和技巧,帮助您解决可能出现的蓝牙连接问... 蓝牙作为一种流行的无线技术,已经成为我们连接各种设备的重要工具。在 MAC 上,你可以根据自己的需求,轻松地

如何关闭Mac的Safari通知? 3招教你关闭Safari浏览器网站通知的技巧

《如何关闭Mac的Safari通知?3招教你关闭Safari浏览器网站通知的技巧》当我们在使用Mac电脑专注做一件事情的时候,总是会被一些消息推送通知所打扰,这时候,我们就希望关闭这些烦人的Mac通... Safari 浏览器的「通知」功能本意是为了方便用户及时获取最新资讯,但很容易被一些网站滥用,导致我们