发布信息

需求最终效果bfinject对正在运行的APP脱壳打包成.ipa

作者:软荐小编      2023-07-09 01:06:38     199

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

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

要求和最终效果

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原创,转载请注明来自看学社区。

相关内容 查看全部