需求最终效果bfinject对正在运行的APP脱壳打包成.ipa
创始人
2025-09-10 21:07:34
0

网上很多教程都讲了很多,但最终不知道他们想要达到什么功能和疗效。 我想,一开始就把要求和最终的疗效展示出来,让读者了解大概情况,引起兴趣,不至于不知其所以然。

我会按照这些文章的思路来分享,先呈现结果,然后详细描述过程。 我认为分享是个好主意。

要求和最终效果

bfinject 将正在运行的APP解压成.ipa

教程脱壳电脑软件免费_电脑软件脱壳工具_电脑脱壳软件教程

注入你自己的动态框架

电脑软件脱壳工具_电脑脱壳软件教程_教程脱壳电脑软件免费

脚本的使用

电脑脱壳软件教程_教程脱壳电脑软件免费_电脑软件脱壳工具

环境要求和正式使用的工具

之前我的MacOSX版本是10.10,只能安装xcode7以下的版本。 xcode7以下的版本没有真机调试功能,所以我将版本升级到MacOSXCatalina10.15.4并安装了最新版本的xcode。 不过这个版本太卡了,存在一些问题。 很多软件不兼容,后来想降级。

电脑脱壳软件教程_教程脱壳电脑软件免费_电脑软件脱壳工具

工具介绍

bfinject是一个注入工具,安装后有很多陷阱。 可以注入到xcode开发的框架中,也可以注入到iOS10中人们使用的cycript工具中。 由于iOS11已经不支持使用cycript,所以所有的cycript命令都只能通过这个工具执行,然后使用笔记本的cycript连接手机。 端口进行操作。

笔记本上的cycript安装教程可以参考这篇文章:安装完这个东西,有很多坑要一一填,但是官网打不开很慢。

Cycript是一个动态注入工具,可以动态执行cy代码,常用于复制ui界面并调试。

iOS11 无法使用 ssh。 我从cydia安装了openssh,用命令行执行ssh,报中文错误,无法打开补码文件。 我不知道为什么。 谁能在iOS11上运行ssh但是笔记本电脑连接手机ssh的麻烦可以告诉我非常感谢。

实施流程

bfinject 将正在运行的APP解压成.ipa

安装bfinject

首先从笔记本上下载bfinject,然后使用手机助手等工具将二进制补码文件bfinject复制到iPhone上的任意位置。 我把它放在/User/Media/目录中。 bfinject下载和安装教程请参考github。

这个bfinject还是有很多坑的,安装后会报很多错误。 比如electra和bootstrap目录问题的坑; 还有md5:commandnotfound的错误报告。 我的做法是复制md5sum命令,改成md5执行,不报错。 网上有填坑的例子。 如果你遇到它,你就能看到它。

另外,这个bfinject的实现需要关闭Tweaks才能成功运行:打开越狱工具Electra,禁用Tweaks选项,然后重启。

这个bfinject的执行需要关闭Tweaks才能成功运行:打开越狱工具Electra,禁用Tweaks选项,然后重新启动。

这个bfinject的执行需要关闭Tweaks才能成功运行:打开越狱工具Electra,禁用Tweaks选项,然后重新启动。

使用 bfinject 的手机

以下所有手机命令均由root用户操作。

打开终端,进入/User/Media/目录执行:

portant;overflow-wrap: break-word !important;">bash bfinject -P test1.app -L test

上面界面中的应用程序是我随意编写的一个演示应用程序,安装在iPhone中,我用它来调试。 该应用程序称为 test1.app,此处用于演示。 -Ltest是指调用bfinject外部框架进行注入。 用于判断bfinject是否安装成功并生效。 成功界面如下:

电脑脱壳软件教程_教程脱壳电脑软件免费_电脑软件脱壳工具

电脑脱壳软件教程_电脑软件脱壳工具_教程脱壳电脑软件免费

拿出来用这个命令导入ipa

portant;overflow-wrap: break-word !important;">bash bfinject -P test1.app -L decrypt

返回应用界面

教程脱壳电脑软件免费_电脑软件脱壳工具_电脑脱壳软件教程

打包! 我们选择否,它会将包保存到应用程序的文档目录中。

我们找到这个包:

portant;overflow-wrap: break-word !important;">find /var/mobile/Containers/Data/Application/ -name decrypted-app.ipafind /var/mobile/Containers/Data/Application/ -name decrypted-app.ipa

电脑脱壳软件教程_教程脱壳电脑软件免费_电脑软件脱壳工具

其中decrypted-app.ipa就是我们打包的路径。 将这个包放到/User/Media/目录下,然后使用笔记本手机助手工具获取。 下一步是提取头文件。

注入你自己的动态框架

提取头文件

class-dump的安装比较简单,我就不讲了,它是一个提取match-o格式文件的工具,它可以导入iOS开发的app的头文件,可以知道类、技能、以及应用程序上的变量名称。 使用它来注入指定的方法。

笔记本命令:

portant;overflow-wrap: break-word !important;">class-dump -H test1 -o test1Headers

test1就是上面我解压decrypted-app.ipa后的match-o文件,test1Headers指的是输出所有头文件到这个文件夹。

好吧,我打开其中一个头文件。

电脑脱壳软件教程_教程脱壳电脑软件免费_电脑软件脱壳工具

因为这个app是我自己写的,所以我知道down是点击其中一个Button按钮后输出弹窗的功能。 我会用这个方法来演示注入,就是点击Button按钮后注入一个弹窗。 其实其他app需要凭经验来分析,可以用hooper等反编译工具来分析。

编译注入代码

打开xcode,新建一个项目,在iOS framework&Library中选择framework。

请您自行填写产品名称等信息。 我的名字是snakeGameHacker。

创建项目目录后,snakeGameHacker.h是头文件,我的这样写:

portant;overflow-wrap: break-word !important;">#import  //! Project version number for snakeGameHacker.FOUNDATION_EXPORT double snakeGameHackerVersionNumber; //! Project version string for snakeGameHacker.FOUNDATION_EXPORT const unsigned char snakeGameHackerVersionString[]; // In this header, you should import all the public headers of your framework using statements like #import#import #import 

然后创建CocoaTouchclass文件HackerLoader,它将手动生成HackerLoader.h和HackerLoader.m文件。

黑客加载器.h

portant;overflow-wrap: break-word !important;">#import portant;overflow-wrap: break-word !important;">#import portant;overflow-wrap: break-word !important;">@interface HackerLoader : NSObjectportant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;">@end

黑客加载器.m

portant;overflow-wrap: break-word !important;">#import "HackerLoader.h"portant;overflow-wrap: break-word !important;">#import "NSObject+Hacker.h"portant;overflow-wrap: break-word !important;">#import portant;overflow-wrap: break-word !important;">@implementation HackerLoaderportant;overflow-wrap: break-word !important;">static void __attribute__((constructor)) entry(void) {portant;overflow-wrap: break-word !important;"> NSLog(@">>>>> Code Injected 哈哈哈3哈<<<<<"); portant;overflow-wrap: break-word !important;"> NSObject *obj = [[NSObject alloc] init];portant;overflow-wrap: break-word !important;"> [obj hack];portant;overflow-wrap: break-word !important;">}portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;">@end

然后创建一个objective-cFile文件,类型选择Category,命名为Hacker

最终形式:NSObject+Hacker.h 和 NSObject+Hacker.m

NSObject+Hacker.h

portant;overflow-wrap: break-word !important;">#import portant;overflow-wrap: break-word !important;">#import portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;">@interface NSObject (Hacker)portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;">- (void)hack;portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;">@end

NSObject+Hacker.m

这是我们的核心文件

portant;overflow-wrap: break-word !important;">#import "NSObject+Hacker.h"portant;overflow-wrap: break-word !important;">#import portant;overflow-wrap: break-word !important;">@implementation NSObject (Hacker)portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;">- (void)hack {portant;overflow-wrap: break-word !important;"> NSLog(@">>>>> Code Injected powerby maimai <<<<<");portant;overflow-wrap: break-word !important;"> NSString *className = @"ViewController";portant;overflow-wrap: break-word !important;"> [self hookMethod:@"down" ofClass:className hookMethodName:@"down2"];portant;overflow-wrap: break-word !important;">}portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;">// 封装方法挂载函数portant;overflow-wrap: break-word !important;">- (void)hookMethod:(NSString *)oriMethodName ofClass:(NSString *)ClassName hookMethodName:(NSString *)hookMethodName {portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> NSLog(@"挂载方法。。。。");portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> static dispatch_once_t onceToken;portant;overflow-wrap: break-word !important;"> dispatch_once(&onceToken, ^{portant;overflow-wrap: break-word !important;"> Class oriMethodClass = NSClassFromString(ClassName);portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> Class class = [self class];portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> SEL originalSelector = NSSelectorFromString([oriMethodName stringByAppendingString:@":"]);portant;overflow-wrap: break-word !important;"> SEL swizzledSelector = NSSelectorFromString([hookMethodName stringByAppendingString:@":"]);portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> Method originalMethod = class_getInstanceMethod(oriMethodClass, originalSelector);portant;overflow-wrap: break-word !important;"> Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> BOOL didAddMethod = class_addMethod(oriMethodClass,originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod));portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> if (didAddMethod) {// 判断是否已经有这个方法了portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> class_replaceMethod(oriMethodClass,swizzledSelector,method_getImplementation(originalMethod),method_getTypeEncoding(originalMethod));portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> } else {portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> method_exchangeImplementations(originalMethod, swizzledMethod);portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> }portant;overflow-wrap: break-word !important;"> });portant;overflow-wrap: break-word !important;">}portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;">// 按钮按下portant;overflow-wrap: break-word !important;">- (void)down2:(id)sender{portant;overflow-wrap: break-word !important;"> NSLog(@"----down2----weirui3----");portant;overflow-wrap: break-word !important;"> [self showError:@"我在app的方法里注入自己的代码啦!"];portant;overflow-wrap: break-word !important;"> return [self down2:sender];portant;overflow-wrap: break-word !important;">}portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;">- (UIViewController *)_topViewController:(UIViewController *)vc {portant;overflow-wrap: break-word !important;"> if ([vc isKindOfClass:[UINavigationController class]]) {portant;overflow-wrap: break-word !important;"> return [self _topViewController:[(UINavigationController *)vc topViewController]];portant;overflow-wrap: break-word !important;"> } else if ([vc isKindOfClass:[UITabBarController class]]) {portant;overflow-wrap: break-word !important;"> return [self _topViewController:[(UITabBarController *)vc selectedViewController]];portant;overflow-wrap: break-word !important;"> } else {portant;overflow-wrap: break-word !important;"> return vc;portant;overflow-wrap: break-word !important;"> }portant;overflow-wrap: break-word !important;"> return nil;portant;overflow-wrap: break-word !important;">}portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;">- (UIViewController *)topViewController {portant;overflow-wrap: break-word !important;"> UIViewController *resultVC;portant;overflow-wrap: break-word !important;"> resultVC = [self _topViewController:[[UIApplication sharedApplication].keyWindow rootViewController]];portant;overflow-wrap: break-word !important;"> while (resultVC.presentedViewController) {portant;overflow-wrap: break-word !important;"> resultVC = [self _topViewController:resultVC.presentedViewController];portant;overflow-wrap: break-word !important;"> }portant;overflow-wrap: break-word !important;"> return resultVC;portant;overflow-wrap: break-word !important;">}portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;">- (void)showError:(NSString *)errorMsg {portant;overflow-wrap: break-word !important;"> UIViewController *uvc = [self topViewController];portant;overflow-wrap: break-word !important;"> NSLog(@"----weirui3----当前vc%@", NSStringFromClass([uvc class]));portant;overflow-wrap: break-word !important;"> // 1.弹框提醒portant;overflow-wrap: break-word !important;"> // 初始化对话框portant;overflow-wrap: break-word !important;"> UIalertController *alert = [UIalertController alertControllerWithTitle:@"提示" message:errorMsg preferredStyle:UIalertControllerStylealert];portant;overflow-wrap: break-word !important;"> [alert addAction:[UIalertAction actionWithTitle:@"确定" style:UIalertActionStyleDefault handler:nil]];portant;overflow-wrap: break-word !important;"> // 弹出对话框portant;overflow-wrap: break-word !important;"> [uvc presentViewController:alert animated:true completion:nil];portant;overflow-wrap: break-word !important;"> NSLog(@"uvc show");portant;overflow-wrap: break-word !important;">}portant;overflow-wrap: break-word !important;"> portant;overflow-wrap: break-word !important;">@end

代码解释

静态 voidattribute((构造函数))entry(void){}

当进程注入时,这个技巧将在这里执行。 我们实例化一个 NSObject 来执行 NSObject+Hacker.m.hack() 方法。 hack方法上面有一段:

portant;overflow-wrap: break-word !important;">NSString *className = @"ViewController";portant;overflow-wrap: break-word !important;"> [self hookMethod:@"down" ofClass:className hookMethodName:@"down2"];

HookMethod是我封装好的函数调用钩子方法,用OC语言中的swizzledMethod实现方法替换注入。 theos中tweak的%orig原理是使用swizzledMethod来实现hook。

前面我会分享tweak注入的教程,我认为它比bfinject更稳定可靠。

意思是ViewController类下的down()方法挂载了一个我们指定的down2()方法

然后我们编译down2技能。

portant;overflow-wrap: break-word !important;">// 按钮按下portant;overflow-wrap: break-word !important;">- (void)down2:(id)sender{portant;overflow-wrap: break-word !important;"> NSLog(@"----down2----weirui3----");portant;overflow-wrap: break-word !important;"> [self showError:@"我在app的方法里注入自己的代码啦!"];portant;overflow-wrap: break-word !important;"> return [self down2:sender];portant;overflow-wrap: break-word !important;">}

拦截了down的执行并插入了一段代码[selfshowError:@"我在app方法中注入了自己的代码!";

这是弹出窗口的代码。 本页面弹窗的实现请自行查看弹窗实现代码。 网上有很多类似的代码。 然后返回[selfdown2:sender];

是%orig的真实代码,看似是递归调用,其实不然。

编译

我们先测试一下是否有错误。

如果要使用单例测试,将编译目标改为iOSSimulators电脑脱壳软件教程,我选择iOS8,然后按command+U运行,拒绝不报错,运行到hack()方法:

教程脱壳电脑软件免费_电脑软件脱壳工具_电脑脱壳软件教程

其实down2方法不会被执行,因为down2是动态执行的,需要注入bfinject来启动对应的app来触发down方法执行。

我们编译代码。

请注意,编译目标已切换为 GenericiOSDevice。

将其他与证书相关的配置更改为“无”,将目标版本更改为您的手机可以执行的版本,然后等待一些过程。

然后按Command+B进行编译。

Products/目录下形成snakeGameHacker.framework目录电脑脱壳软件教程,用finder打开,进去找到上面snakeGameHacker的Unix可执行文件,就是我们注入的对象。

注射

将snakeGameHacker上传到手机目录。

在手机中执行

portant;overflow-wrap: break-word !important;">bash bfinject -P test1.app -l snakeGameHacker  

注意这里的-l和前面的不一样,这里是大写的。

执行完后,返回app,按下Button按钮(down模式下执行触发)

结果注入成功:

电脑软件脱壳工具_电脑脱壳软件教程_教程脱壳电脑软件免费

至此,框架注入就解释完了。

脚本的使用

手机执行:

portant;overflow-wrap: break-word !important;">bash bfinject -P test1.app -L cycript

电脑脱壳软件教程_电脑软件脱壳工具_教程脱壳电脑软件免费

之后笔记本打开终端,输入对应的地址:

portant;overflow-wrap: break-word !important;">cycript -r 192.168.0.101:1337

不过我经常连接很久或者失败,感觉不太好用。 需要几次尝试才能成功。

本来想写几个命令,现在连接不上,算了~

-结尾-

教程脱壳电脑软件免费_电脑脱壳软件教程_电脑软件脱壳工具

看学ID:麦麦2020

*本文由看学峰会脉脉2020原创,转载请注明来自看学社区。

相关内容

热门资讯

手... 您是手机、车机互联的轻度用户吗? 买房的时候你是否坚持不买没有Carplay的汽车? 或者你还习惯用...
u... U盘在使用过程中很容易被误低格。 下面我们就来说说硬盘被删除或错误低格后如何恢复数据。 并教您如何使...
新... 心岛科技于1月3日暂停上市,次日停牌。 股价下跌38.06%。 这使得大部分2021年4月后建仓并持...
口... 目前以华为、小米、OPPO、vivo、联想为代表的主流手机品牌都提供了官方的多屏协同应用,但对于冷门...
听... 麦克风可以用来做什么? 很多人首先想到的是听音乐和请勿打扰吗? iFLYBUDSNano+,讯飞录...
百... 曾子说:操作在于坚持,点击《曾子操作笔记》关注我,我们一起成长。作为站长或者网站运营者,如果想让自己...
手... 用过Carlife的人都知道,它确实不好用。除了需要插上数据线连接之外,还需要安装百度Carlife...
手... 近年来,智能汽车和车机集成成为科技和汽车行业关注的焦点,并努力将汽车与其他智能设备友好连接。 8月...
荣... 11月22日14点30分,荣耀MagicOS发布暨开发者大会如期而至,为大众带来了全新的MagicO...
X... 联通办公已经成为一种趋势。 在联通办公场景中,平板笔记本成为不少用户的新选择。 为了进一步满足用户对...
国... 为了在录音和直播时获得更好的声音效果,窃听麦克风是必不可少的,但专业的窃听麦克风往往价格昂贵,而且不...
《... AI绘图特效具体操作教程及AI配音软件介绍随着人工智能技术的发展,越来越多的人开始利用AI技术来简化...
手... 过去,手机只是一种通讯工具,但现在,手机已经成为外出必备物品。 甚至有人调侃说手机互联软件,手机不但...
两... 你好! 大家好,这里是每天晚上分享一点办公方法的小F!作为一名资深“工人”,小F每天并不需要处理太多...
数... 一、系统特点●控制轴数:单轴;●指令特点:任意可编程(可实现各种复杂运算:定位控制和非定位控制);●...
如... 许多 Netgear 路由器产品仍然受第三方路由器固件支持。 从网上搜索,发现一位名叫孔大师()的日...
享... 我们每天行走在拥挤喧闹的人群中,有时真想逃离这喧嚣,去一个荒岛,享受孤独,融入大自然。 显然,大多数...
装... 1.酷家乐/爱芙窝操作难度:★★细度:★★酷家乐是门槛最低的家装软件,适合小白操作,有网页版kuji...
E... 毫无疑问,目前TWS无线蓝牙音箱市场已经非常成熟。 在电商平台上,可以以此为关键词搜索到相当多的产品...
小... 魅族粉丝的狂热从来都不是新闻,给我印象最深的还是我阿姨的。 我姐姐是魅族手机的忠实粉丝。 每一代红米...