美文网首页
iOS打包教程

iOS打包教程

作者: 一直在路上66 | 来源:发表于2023-04-18 09:52 被阅读0次

    iOS逆向知识掌握

    • 通过脱壳、运行时分析、静态分析、动态调试、Hook、注入等一系列技术手段,推导出目标文件的结构、流程、算法、代码等,称为“iOS应用逆向工程”(后续简称为“iOS逆向工程”)
    • 了解Objective-C、Swift的基本特性以及Xcode的使用方法,等熟练之后,还需要了解一些底层知识,例如Mach-O文件结构、Runtime机制等。
    • 推荐阅读 《iOS应用逆向工程》 《iOS应用逆向与安全之道》

    越狱手机

    • 需要一台越狱手机 安装爱思助手

    应用脱壳

    • iOS端App在上线之前会由苹果商店进行FairPlayDRM数字版权加密保护(称为“加壳”)otool可以看到二进制文件的信息里有一个cryptid字段,cryptid=1表示已加壳,cryptid=0表示未加壳。具体如下。
    • 使用 Frida-ios-dump工具脱壳 frida-ios-dump

    工具之IDA

    • 下载安装ida ida地址
    • 加载文件并分析完成之后,用户便可以根据需求进行逆向分析。在进行逆向分析前有必要了解IDA界面的各种组件,IDA分析完成后的默认界面如下所示。 image.png
    • 主要分析每个类里面主要有哪些方法 例如PFSDManger集成brsdk的一些方法在hook时 hook这些方法就可以了 image.png

    越狱开发工具之Theos

    • Theos是一个跨平台的越狱开发工具包,可以在Windows、Linux、macOS甚至iOS下工作。Theos无论是下载安装还是编译发布都比较简单,它为开发者准备好了一些代码模板、预置了一些基本的Makefile脚本,这样开发一个插件就会变得方便很多,其Logos语法也是相当优雅,让开发者可以更专注于功能开发。Theos相当于对Cydia Substrate的封装,因而能实现对Objective-C运行时的Hook,也能实现对C语言函数的Hook

    Theos安装

    • 在Theos开发中,iOS文件的签名由ldid工具来完成,ldid取代了Xcode自带的codesign。使用brew安装即可
    brew install ldid
    
    • 2.安装xz、lzma
      xz、lzma是两种压缩模块,为了后面“make package”能够顺利通过,需要安装它们。安装方法如下:
    $ brew install xz
    $ sudo cpan IO::Compress::Lzm
    
    • 3.添加$THEOS环境变量
      读者可以使用任何编辑工具打开.bash_profile文件,添加下面的环境变量:
    export THEOS=/opt/theos
    export PATH=$PATH:$THEOS/bin
    
    • 4.安装Theos
    sudo git clone --recursive https://github.com/theos/theos.git $THEOS
    
    • 5.设置$THEOS的用户组权限
    sudo chown -R $(id -u):$(id -g) $THEOS
    
    • 更多关于theos知识可以查询资料 掌握如何创建工程 如何书写Tweak.xm文件
    • %hook
      指定需要Hook的类名,接着就是需要Hook的函数,最后必须以%end结尾
    • (2)%log
      该命令在%hook内部使用,将类名、函数名、参数信息打印出来,非常实用。需要注意的是只在DEBUG模式下才会输出信息。
    • (3)%orig
    • (4)%new
      该命令在%hook内部使用,为现有类增加新的方法,功能与class_addMethod相同。示例如下:

    工具之monkeydev

    • Theos使用Makefile基于命令行方式编译生成deb文件,习惯使用Xcode的开发者可能不太适应这种方式,于是有了后来的iOSOpenDev。它基于Xcode模板开发,在很长一段时间内都是越狱开发者的福音,但是该项目不再维护,因此在新的Xcode版本中不能很好地工作。国内安全研究员在此基础上进行了修改,推出了一个全新的集成框架,名为“MonkeyDev”,它不仅能完美支持新版Xcode和新版Theos,还增加了一些非常实用的功能
    • MonkeyDev安装
    brew install https://raw.githubusercontent.com/kadwanev/bigboybrew/
    master/Library/Formula/sshpass.r
    
    • 选择xcode 版本
    sudo xcode-select -s /Applications/Xcode9.
    
    *新建项目选择Monkeyapp image.png
    • 选择Logos Tweak模板之后,会自动生成基础代码,由于Xcode无法识别*.xm文件,导致代码没有高亮效果,这时需要在Xcode界面右侧设置“Type”为“Objective-C++Source”,然后重新打开工程。完成后如图8-13所示。
    • 把IPA放到这里


      image.png
    • 在monkeyDemoDylib.xm 编写hook代码


      image.png

    开始集成SDK

    将sdk拖入到工程中

    image.png image.png

    添加依赖库

    image.png

    支付宝添加回调

    #pragma mark - 支付回调,必接
    
    - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
        [WCmsSDK application:application handleOpenURL:url];
        return %orig;
    }
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options {
        [WCmsSDK application:application openURL:url options:options];
        return  %orig;
    }
    
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
        [WCmsSDK application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
        return %orig;
    }
    

    wansdk初始化代码

    %hook AppDelegate
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // sdk初始化
        [WCmsSDK didFinishLaunching];
        return %orig;
    }
    

    接入登录

    %hook   BRSDKApi
    
    - (void)login{
        %log;
    //    %orig;
        [self wanlogin];
    }
    %new
    - (void)wanlogin{
        [WCmsSDK loadLoginViewResultSuccess:^(NSString *logintime, NSString *userName, NSString *sign, NSString *rzStatus) {
            NSLog(@"WCmsSDK____%@%@%@%@",logintime,userName,sign,rzStatus);
            NSString* openId = [NSString stringWithFormat:@"%@_%@", @"brsyp", userName];
            dispatch_async(dispatch_get_main_queue(), ^{
                [BoRanSDK thirdLoginWithOpenId:openId];
            });
        } failed:^(NSInteger code, NSString *message) {
    
        }];
    }
    
    %end
    

    接入支付

    -(void)pay_param:(NSDictionary *)param{
            %log;
            %orig;
        [BoRanSDK tradeOrderNum:param];
    //    [self wanPay:param];
    }
    
    +(void)tradeOrderNum:(NSDictionary*)param{
        
        BRSDKOrderInfo* orderInfo = [[BRSDKOrderInfo alloc] init];
        orderInfo.productId = param[@"product_id"];
        orderInfo.productName = param[@"product_name"];
        orderInfo.productDesc = param[@"product_name"];
        NSString *amount =  param[@"amount"];
        orderInfo.productPrice = [NSString stringWithFormat:@"%ld",amount.integerValue*100];
        orderInfo.roleId = param[@"role_id"];
        orderInfo.roleName = param[@"role_name"];
        orderInfo.serverId = param[@"server_id"];
        orderInfo.serverName = param[@"server_name"];
        orderInfo.extInfo = param[@"extend"];
        NSMutableDictionary *resDict = [[NSMutableDictionary alloc]init];
        resDict[@"productId"] = orderInfo.productId;
        resDict[@"product"] = orderInfo.productName;
        resDict[@"orderMoneyFen"] = orderInfo.productPrice;
        resDict[@"roleId"] = orderInfo.roleId;
        resDict[@"roleName"] = orderInfo.roleName;
        resDict[@"serverId"] = orderInfo.serverId;
        resDict[@"serverName"] = orderInfo.serverName;
        resDict[@"extInfo"] = orderInfo.extInfo;
        [YouRequestManager requtForPouWayWithParams:resDict Block:^(NSDictionary *dic) {
            NSLog(@"requtForPouWayWithParams === %@",dic);
        } withFail:^(NSError *error) {
            
        }];
    }
    

    上传角色

    -(void)upLoadRoleType:(NSString *)type Uid:(NSString *)user_id serverID:(NSString *)server_id serverName:(NSString *)server_name role_ID:(NSString *)role_id roleName:(NSString *)role_name level:(NSString *)level balanceID:(NSString *)balanceid balanceName:(NSString *)balancename balanceNum:(NSString *)balancenum vip:(NSString *)vip power:(NSString *)power gender:(NSString *)gender professionid:(NSString *)professionid profession:(NSString *)profession turn_level:(NSString *)turn_level partyId:(NSString *)partyid partyName:(NSString *)partyname{
        %orig;
        [WCmsSDK SetUserInfoDataWithRoleId:role_id
                                  roleName:role_name
                                 roleLevel:level
                                    zoneId:server_id
                                  zoneName:server_name
                                    attach:@"无"
                                     block:^(NSInteger code) {
                                         if (code == 1) {
    //                                         [YGMessage showMessage:@"上传成功"];
                                             NSLog(@"角色上传成功");
                                         };
                                     }];
        
        GameRoleInfo *roleInfo =  [[GameRoleInfo alloc]init];
        roleInfo.uploadType = UploadRoleInfoTypeCreateRole;
        roleInfo.serverId = server_id;
        roleInfo.serverName = server_name;
        roleInfo.roleId = role_id;
        roleInfo.roleName = role_name;
        roleInfo.roleLevel = level;
        roleInfo.partyName = @"无";
        roleInfo.roleCTime = [self gs_getCurrentTimeBySecond];
        roleInfo.balance = 20.0;
        roleInfo.fightingCapacity = @"10";
        roleInfo.reincarnation = @"0";
        roleInfo.roleVip = @"0";
        [BoRanSDK  sendGameRoleInfo:roleInfo];
    }
    
    
    #pragma mark - 角色上报
    
    + (void)sendGameRoleInfo:(GameRoleInfo *)roleInfo
    {
        NSMutableDictionary* infoDict = [NSMutableDictionary dictionary];
        [infoDict setValue:@(roleInfo.uploadType) forKey:@"uploadType"];
        [infoDict setValue:roleInfo.serverId forKey:@"serverId"];
        [infoDict setValue:roleInfo.serverName forKey:@"serverName"];
        [infoDict setValue:roleInfo.roleId forKey:@"roleId"];
        [infoDict setValue:roleInfo.roleName forKey:@"roleName"];
        [infoDict setValue:roleInfo.roleLevel forKey:@"roleLevel"];
        [infoDict setValue:roleInfo.roleVip forKey:@"roleVip"];
        [infoDict setValue:@(roleInfo.balance) forKey:@"balance"];
        [infoDict setValue:roleInfo.partyName forKey:@"partyName"];
        [infoDict setValue:roleInfo.fightingCapacity forKey:@"fightingCapacity"];
        [infoDict setValue:roleInfo.reincarnation forKey:@"reincarnation"];
        [infoDict setValue:@(roleInfo.roleCTime) forKey:@"roleCTime"];
        
        //1.上报渠道角色信息
    #if HAS_INCLUDE_CHANNEL
        if ([[sdkTools shareTool].loginMode intValue] != (int)LOGIN_MODE_BORAN) {
            
            int nType = 1;
            switch (roleInfo.uploadType) {
                case UploadRoleInfoTypeEnterGame:
                    nType = 1;
                    break;
                case UploadRoleInfoTypeCreateRole:
                    nType = 2;
                    break;
                case UploadRoleInfoTypeRoleLevelUp:
                    nType = 3;
                    break;
                case UploadRoleInfoTypeExitGame:
                    nType = 4;
                    break;
                default:
                    break;
            }
            
            [infoDict setValue:@(nType) forKey:@"dataType"];
            [infoDict setValue:roleInfo.roleVip forKey:@"roleVipLevel"];
            [infoDict setValue:@(roleInfo.balance) forKey:@"roleBalence"];
            [infoDict setValue:@(roleInfo.roleCTime) forKey:@"rolelevelCtime"];
            [[BoranChannel sharedInstance] SendRoleInfo:infoDict];
        }
    #endif
        
        //2.上报官方角色信息
        [YouRequestManager sendFforRole:infoDict WithBlock:^(NSDictionary *dic) {
            
            NSLog(@"send roleInfoDict = %@", infoDict);
            
            NSString *stuats = [[dic objectForKey:@"status"]stringValue];
            if ([stuats isEqualToString:@"1"]) {
                NSDictionary *succ = [[NSDictionary alloc]initWithObjectsAndKeys:@"401",@"code", nil];
                [[NSNotificationCenter defaultCenter]postNotificationName:kBRSDKSendRoleNotification object:nil userInfo:succ];
            }else{
                NSDictionary *succ = [[NSDictionary alloc]initWithObjectsAndKeys:@"402",@"code", nil];
                [[NSNotificationCenter defaultCenter]postNotificationName:kBRSDKSendRoleNotification object:nil userInfo:succ];
            }
        } withFail:^(NSError *error) {
            NSDictionary *succ = [[NSDictionary alloc]initWithObjectsAndKeys:@"403",@"code", nil];
            [[NSNotificationCenter defaultCenter]postNotificationName:kBRSDKSendRoleNotification object:nil userInfo:succ];
        }];
    }
    

    相关文章

      网友评论

          本文标题:iOS打包教程

          本文链接:https://www.haomeiwen.com/subject/iyyhjdtx.html