zoukankan      html  css  js  c++  java
  • App安全

      经常做的网络参数加密解密,以及防止数据重放之外,还提到了防范反编译的风险,其实Apple算比较安全的了,反编译过来也就看到.h文件....但把代码混淆还是会比较好些。

    一、iOS 中的网络加密

      公司的接口一般会两种协议的,一种HTTP,一种HTTPS的,HTTP 只要请求,服务器就会响应,如果我们不对请求和响应做出加密处理,所有信息都是会被检测劫持到的,是很不安全的,客户端加密可以使用我这套工具类进行处理:文章地址
      但是不论在任何时候,都应该将服务置于HTTPS上,因为它可以避免中间人攻击的问题,还自带了基于非对称密钥的加密通道!使用HTTPS后,可以省去各种加解密技术。

    介绍下HTTPS交互原理

    简答说,HTTPS 就是 HTTP协议加了一层SSL协议的加密处理,SSL 证书就是遵守 SSL协议,由受信任的数字证书颁发机构CA(如GlobalSign,wosign),在验证服务器身份后颁发,这是需要花钱滴,签发后的证书作为公钥一般放在服务器的根目录下,便于客户端请求返回给客户端,私钥在服务器的内部中心保存,用于解密公钥。

    HTTPS 客户端与服务器交互过程:

    1、客户端发送请求,服务器返回公钥给客户端;
    2、客户端生成对称加密秘钥,用公钥对其进行加密后,返回给服务器;
    3、服务器收到后,利用私钥解开得到对称加密秘钥,保存;
    4、之后的交互都使用对称加密后的数据进行交互。

    谈下证书
    简单说,证书有两种,一种是正经的:

    一种是不正经的:

    介绍下我们需要做什么

    如果遇到正经的证书,我们直接用AFNetworking 直接请求就好了,AFNetworking 内部帮我们封装了HTTPS的请求方式,但是大部分公司接口都是不正经的证书,这时需要我们做以下几步:
    1、将服务器的公钥证书拖到Xcode中
    2、修改验证模式

    manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];

    原理:
    简单来说,就是你本可以修改AFN这个设置来允许客户端接收服务器的任何证书,但是这么做有个问题,就是你无法验证证书是否是你的服务器后端的证书,给中间人攻击,即通过重定向路由来分析伪造你的服务器端打开了大门。

    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
    securityPolicy.allowInvalidCertificates = YES;
    解决方法:AFNetworking是允许内嵌证书的,通过内嵌证书,AFNetworking就通过比对服务器端证书、内嵌的证书、站点域名是否一致来验证连接的服务器是否正确。由于CA证书验证是通过站点域名进行验证的,如果你的服务器后端有绑定的域名,这是最方便的。将你的服务器端证书,如果是pem格式的,用下面的命令转成cer格式
    openssl x509 -in <你的服务器证书>.pem -outform der -out server.cer

    然后将生成的server.cer文件,如果有自建ca,再加上ca的cer格式证书,引入到app的bundle里,AFNetworking在

    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy AFSSLPinningModeCertificate];

    或者

    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy AFSSLPinningModePublicKey];

    情况下,会自动扫描bundle中.cer的文件,并引入,这样就可以通过自签证书来验证服务器唯一性了。

    AFSecurityPolicy分三种验证模式:

    AFSSLPinningModeNone

    这个模式表示不做SSL pinning,
    只跟浏览器一样在系统的信任机构列表里验证服务端返回的证书。若证书是信任机构签发的就会通过,若是自己服务器生成的证书就不会通过。

    AFSSLPinningModeCertificate

    这个模式表示用证书绑定方式验证证书,需要客户端保存有服务端的证书拷贝,这里验证分两步,第一步验证证书的域名有效期等信息,第二步是对比服务端返回的证书跟客户端返回的是否一致。

    AFSSLPinningModePublicKey

    这个模式同样是用证书绑定方式验证,客户端要有服务端的证书拷贝,
    只是验证时只验证证书里的公钥,不验证证书的有效期等信息。只要公钥是正确的,就能保证通信不会被窃听,因为中间人没有私钥,无法解开通过公钥加密的数据。

    除了证书加密:

      用 POST 请求提交用户的隐私数据,还是不能完全解决安全问题。因此:我们经常会用到加密技术,比如说在登录的时候,我们会先把密码用MD5加密再传输给服务器 或者 直接对所有的参数进行加密再POST到服务器。

    1.数据安全介绍
    • 最基础的是我们发送网络请求时,使用getpost方式发送请求。两者具体区别就不做解释了,只是引出相关安全性问题

      • get:将参数暴露在外,(绝对不安全-->明文请求或者傻瓜式请求)。
      • post:将参数放到请求体body中,(相对于get比较安全-->但是我们可以很容易用一些软件截获请求数据。比如说Charles(青花瓷)
    • Charles(大部分app的数据来源都使用该工具来抓包,并做网络测试)

      • 注意:Charles在使用中的乱码问题,可以显示包内容,然后打开info.plist文件,找到java目录下面的VMOptions,在后面添加一项:-Dfile.encoding=UTF-8
    • 数据安全的原则

      • 在网络上不允许传输用户隐私数据的明文,(即:App网络传输安全,指对数据从客户端传输到Server中间过程的加密,防止网络世界当中其他节点对数据的窃听)。
      • 在本地不允许保存用户隐私数据的明文,(即:App数据存储安全,主要指在磁盘做数据持久化的时候所做的加密)。
      • App代码安全,(即:包括代码混淆,加密或者app加壳)。
    • 要想非常安全的传输数据,建议使用https。抓包不可以,但是中间人攻击则有可能。建议双向验证防止中间人攻击,可以参考下文篇章。

    2、常用加密算法

    编码方案   Base64

    哈希(散列)函数 MD5(消息摘要算法)

                        SHA1

                        SHA256

    对称加密算法  DES

                        AES

    非对称加密算法  RSA

    HTTPS           HTTP+SSL协议

    3、常用加密方式

    1.通过简单 BASE64编码 防止数据明文传输

    2.对普通请求、返回数据,生成MD5校验(MD5中加入动态密钥),进行数据完整性(简单防篡改,安全性较低,优点:快速)校验

    3.对于重要数据,使用RSA进行数字签名,起到防篡改作

    4.对于比较敏感的数据,如用户信息(登陆、注册等),客户端发送使用RSA加密,服务器返回使用DES(AES)加密

    5.要想非常安全的传输数据,建议使用https。抓包不可以,但是中间人攻击则有可能。建议双向验证防止中间人攻击

    4.Base64编码方案
    1. Base64简单说明
      描述:Base64可以成为密码学的基石,非常重要。
      特点:可以将任意的二进制数据进行Base64编码
      结果:所有的数据都能被编码为并只用65个字符(A~Z a~z 0~9 + / =)就能表示的文本文件。
      注意:对文件进行base64编码后文件数据的变化:编码后的数据~=编码前数据的4/3,会大1/3左右。

    2. Base64编码原理和处理过程

    1. Base64实现代码
    // 对一个字符串进行base64编码,并且返回
    -(NSString *)base64EncodeString:(NSString *)string {
        // 1.先转换为二进制数据
        NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
        // 2.对二进制数据进行base64编码,完成之后返回字符串
        return [data base64EncodedStringWithOptions:0];
    }
    
    // 对base64编码之后的字符串解码,并且返回
    -(NSString *)base64DecodeString:(NSString *)string {
        // 注意:该字符串是base64编码后的字符串
        // 1.转换为二进制数据(完成了解码的过程)
        NSData *data = [[NSData alloc]initWithBase64EncodedString:string options:0];
    
        // 2.把二进制数据在转换为字符串
        return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    }
    
    //---------------------------<#我是分割线#>------------------------------//
    
    NSLog(@"%@",[self base64EncodeString:@"A"]);
    NSLog(@"%@",[self base64DecodeString:@"QQ=="]);

    PS.终端执行编码和解码

    如:
    编码:base64 123.png -o 123.txt
    解码:base64 123.txt -o test.png -D
    4.加密实现代码

    哈希(散列)函数
    特点:

    • 算法是公开的
    • 对相同的数据加密,得到的结果是一样的"
    • 对不同的数据加密,得到的结果是定长的,MD5对不同的数据进行加密,得到的结果都是 32 个字符长度的字符串
    • 信息摘要,信息"指纹",是用来做数据识别的!
    • 不能逆推反算(重要)

    用途:

    • 版权 对文件进行散列判断该文件是否是正版或原版的
    • 文件完整性验证 对整个文件进行散列,比较散列值判断文件是否完整或被篡改
    • 密码加密,服务器并不需要知道用户真实的密码!
    • 搜索:
      如:百度搜索-->老司机 皮皮虾 苍老师
      或是 【苍老师 老司机 皮皮虾 】
      上面两种方式搜索出来的内容是一样的
      • 如何判断:对搜索的每个关键字进行三列,得到三个相对应的结果,按位相加结果如果是一样的,那搜索的内容就是一样的!
    • 经典加密算法:MD5、SHA1、SHA512
    MD5消息摘要算法
    • 简单介绍:

      • MD5:全称是Message Digest Algorithm 5,译为“消息摘要算法第5版”(经MD2、MD3和MD4发展而来)
      • 效果:对输入信息生成唯一的128位散列值(32个字符),即 32个16进制的数字。
    • 特点:

      • 输入两个不同的明文不会得到相同的输出值
      • 根据输出值,不能得到原始的明文,即其过程不可逆(只能加密, 不能解密)
    • 应用:

      • 现在的MD5已不再是绝对安全(如:暴力破解的网站),对此,可以对MD5稍作改进,以增加解密的难度。
      • 解决:加盐(Salt):在明文的固定位置插入随机串,然后再进行MD5(先加密,后乱序:先对明文进行MD5,然后对加密得到的MD5串的字符进行乱序)
    • 注意点:

      • 开发中,一定要和后台开发人员约定好,MD5加密的位数是16位还是32位(大多数都是32位的),16位的可以通过32位的转换得到。
      • MD5加密区分 大小写,使用时要和后台约定好。
      • MD5公认被破解不代表其可逆,而是一段字符串加密后的密文,可以通过强大运算计算出字符串加密后的密文对应的原始字符串,但也不是绝对的被破解。
    • PS.暴力破解是指通过将明文和生成的密文进行配对,生成强大的数据库,在数据库中搜索,在这里就可以破解密码。破解网址 http://www.cmd5.com

    提升MD5加密安全性,解决办法

    • 1.先明文加盐,然后再进行MD5。即明文后拼接字符串(此时拼接的字符串要 足够长+足够咸+足够复杂),再进行MD5加密。如:#define salt @"1342*&%&shlfhs390(*^^6R%@@KFGKF"
    • 2.先加密+乱序

    • 3.乱序|加盐,多次MD5加密等

    • 4.使用消息认证机制HMAC:给定一个"秘钥",对明文进行加密,并且做"两次散列"!-> 得到的结果,还是 32 个字符,相对安全(KEY是服务器传给你的,不是你写死的)。

    消息认证机制(HMAC)简单说明

    • 原理
      • 消息的发送者和接收者有一个共享密钥
      • 发送者使用共享密钥对消息加密计算得到MAC值(消息认证码)
      • 消息接收者使用共享密钥对消息加密计算得到MAC值
      • 比较两个MAC值是否一致
    • 使用
      • 客户端需要在发送的时候把(消息)+(消息·HMAC)一起发送给服务器
      • 服务器接收到数据后,对拿到的消息用共享的KEY进行HMAC,比较是否一致,如果一致则信任

    简单示例

    #pragma mark - md5加密方法
    - (NSString *)md5String {
        const char *str = self.UTF8String;
        uint8_t buffer[CC_MD5_DIGEST_LENGTH];
        CC_MD5(str, (CC_LONG)strlen(str), buffer);
        return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
    }
    
    #pragma mark - HMACMD5加密方法
    - (NSString *)hmacMD5StringWithKey:(NSString *)key {
        const char *keyData = key.UTF8String;
        const char *strData = self.UTF8String;
        uint8_t buffer[CC_MD5_DIGEST_LENGTH];
        CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer);
        return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
    }
    
    /**
     *  返回二进制 Bytes 流的字符串表示形式
     *  @param bytes  二进制 Bytes 数组
     *  @param length 数组长度
     *  @return 字符串表示形式
     */
    - (NSString *)stringFromBytes:(uint8_t *)bytes length:(int)length {
        NSMutableString *strM = [NSMutableString string];
        for (int i = 0; i < length; i++) {
            [strM appendFormat:@"%02x", bytes[i]];
        }
        return [strM copy];
    }
    
    //---------------------------<#我是分割线#>------------------------------//
    
    // md5加密调用
    NSLog(@"%@",[@"520it" md5String]);
    
    // (明文+加盐)MD5加密调用
    NSLog(@"%@",[[@"520it" stringByAppendingString:salt] md5String]);
    
    // hmacMD5加密调用(先加密+乱序)
    NSLog(@"%@",[@"520it" hmacMD5StringWithKey:@"xiaomage"]);
    对称加密算法AES和DES
    • 对称加密的特点
      • 加密/解密使用相同的密钥
      • 加密和解密的过程是可逆的
    • 经典算法
      • DES 数据加密标准
      • AES 高级加密标准
    • 提示:
      • 加密过程是先加密,再base64编码
      • 解密过程是先base64解码,再解密

    简单示例

    /**
     *  加密字符串并返回base64编码字符串
     *
     *  @param string    要加密的字符串
     *  @param keyString 加密密钥
     *  @param iv        初始化向量(8个字节)
     *
     *  @return 返回加密后的base64编码字符串
     */
    - (NSString *)encryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;
    /**
     *  解密字符串
     *
     *  @param string    加密并base64编码后的字符串
     *  @param keyString 解密密钥
     *  @param iv        初始化向量(8个字节)
     *
     *  @return 返回解密后的字符串
     */
    - (NSString *)decryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;
    // 调用
    EncryptionTools *encrypt = [EncryptionTools sharedEncryptionTools];
    NSLog(@"%@",[encrypt encryptString:@"LN123" keyString:@"LN" iv:nil]);
    NSLog(@"%@",[encrypt decryptString:@"OPcTMDB5paivqtYo9Fj+hQ==" keyString:@"LN" iv:nil]);
    非对称加密RSA
    • 非对称加密的特点
      • 使用 公钥 加密,使用 私钥 解密
      • 使用 私钥 加密,使用 公钥 解密(私钥签名,公钥验签)
      • 公钥是公开的,私钥保密
      • 加密处理安全,但是性能极差
    • 经典算法-->RSA

    简单示例

    // 公钥加密时调用类方法:
    + (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey;
    + (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey;
    // 私钥解密时调用类方法
    + (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey;
    + (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privacy;
    
    /** 调用 */
    NSString *str = [RSAUtil encryptString: @"LN" publicKey:RSA_Public_key];
    NSLog(@"RSA公钥加密数据-->
    %@",str);
    
    NSString *str1 = [RSAUtil decryptString:str privateKey:RSA_Privite_key];
    NSLog(@"RSA私钥解密数据-->%@",str1);

    MAC上生成公钥、私钥的方法,及使用

     # MAC上生成公钥、私钥的方法
     @code
     1.打开终端,切换到自己想输出的文件夹下
     2.输入指令:openssl(openssl是生成各种秘钥的工具,mac已经嵌入)
     3.输入指令:genrsa -out rsa_private_key.pem 1024 (生成私钥,java端使用的)
     4.输入指令:rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout (生成公钥)
     5.输入指令:pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt(私钥转格式,在ios端使用私钥解密时用这个私钥)
     注意:在MAC上生成三个.pem格式的文件,一个公钥,两个私钥,都可以在终端通过指令vim xxx.pem 打开,里面是字符串,第三步生成的私钥是java端用来解密数据的,第五步转换格式的私钥iOS端可以用来调试公钥、私钥解密(因为私钥不留在客户端)
     iOS端公钥加密私钥解密、java端公钥加密私钥解密,java端私钥加密公钥解密都容易做到,iOS不能私钥加密公钥解密,只能用于验签
     @endcode
    5.HTTPS基本使用
    • https简单说明

      • HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。
      • 在HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。
      • HTTPS:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。
    • 注意

      • HTTPS的主要思想是在不安全的网络上创建一安全信道,并可在使用适当的加密包和服务器证书可被验证且可被信任时,对窃听和中间人攻击提供合理的保护。
      • HTTPS的信任继承基于预先安装在浏览器中的证书颁发机构(如VeriSign、Microsoft等)(意即“我信任证书颁发机构告诉我应该信任的”)。
      • 因此,一个到某网站的HTTPS连接可被信任,如果服务器搭建自己的https 也就是说采用自认证的方式来建立https信道,这样一般在客户端是不被信任的。
      • 所以我们一般在浏览器访问一些https站点的时候会有一个提示,问你是否继续。
    • HTTPS和HTTP区别

      • https协议需要到ca申请证书,一般免费证书很少,需要交费。
      • http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议
      • http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80后者是443
      • http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
    • 实现代码

    方案一:如果是自己使用NSURLSession来封装网络请求

    // 1.创建session
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    // 2.创建Task
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://kyfw.12306.cn/otn"]] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { 
        // 3.解析数据
        NSLog(@"%@---%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],error);
    }];
    // 4.执行task
    [dataTask resume];
    
    #pragma mark - 遵守<NSURLSessionDataDelegate>
    // 如果发送的请求是https的,那么才会调用该方法
    -(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
        /**
         判断服务器传给我们的信任的类型,只有是【服务器信任的时候,才安装证书】
         NSURLSessionAuthChallengeDisposition 如何处理证书
         NSURLAuthenticationMethodServerTrust 服务器信任
         */
        if(![challenge.protectionSpace.authenticationMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"]) {
            return;
        }
        NSLog(@"%@",challenge.protectionSpace);
        /*
         NSURLCredential 授权信息
         NSURLSessionAuthChallengeUseCredential = 0, 使用该证书 安装该证书
         NSURLSessionAuthChallengePerformDefaultHandling = 1, 默认采用的方式,该证书被忽略
         NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2, 取消请求,证书忽略
         NSURLSessionAuthChallengeRejectProtectionSpace = 3,          拒绝
         */
        NSURLCredential *credential = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
        completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
        // 注意:并不是所有的https的请求都需要安装证书(授权)的,请求一些大型的网站有的是强制安装的,如:苹果官网https://www.apple.com
    }

    方案二:如果使用AFN网络请求

    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    // 更改解析方式(请求网页源码应使用原始解析)
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    
    // 设置对证书的处理方式
    // 允许自签名证书,必须的
    manager.securityPolicy.allowInvalidCertificates = YES;
    // 是否验证域名的CN字段(不是必须的,但是如果写YES,则必须导入证书)
    manager.securityPolicy.validatesDomainName = NO;
    
    [manager GET:@"https://kyfw.12306.cn/otn" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    
        NSLog(@"success---%@",[[NSString alloc]initWithData:responseObject encoding:NSUTF8StringEncoding]);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    
        NSLog(@"error---%@",error);
    }];
    6.数据安全--加密解密效果

    二、如何有效防止API的重放攻击

      API重放攻击(Replay Attacks)又称重播攻击、回放攻击,这种攻击会不断恶意或欺诈性地重复一个有效的API请求。攻击者利用网络监听或者其他方式盗取API请求,进行一定的处理后,再把它重新发给认证服务器,是黑客常用的攻击方式之一。

      

    HTTPS数据加密是否可以防止重放攻击?

    否,加密可以有效防止明文数据被监听,但是却防止不了重放攻击。

    一般使用以时间戳作为传参,后台协商响应时间差范围,参考三次握手协议两边商量序列号,当发过来的序列号为服务器也存在的序列号则丢弃。

    使用签名防止重放攻击

      使用签名之后,可以对请求的身份进行验证。但不同阻止重放攻击,即攻击者截获请求后,不对请求进行任何调整。直接使用截获的内容重新高频率发送请求。

      API网关提供了一套有效防止重放攻击的方法。开启API网关的重放,需要您使用“阿里云APP”的认证方式。通过这种签名认证方式,每个请求只能被使用一次,从而防止重放。

      阿里云APP:是基于请求内容计算的数字签名,用于API网关识别用户身份。客户端调用API时,需要在请求中添加计算的签名。API网关在收到请求后会使用同样的方法计算签名,同用户计算的签名进行比较,相同则验证通过,不同则认证失败。这种认证的签名方式请参照:请求签名

      在API网关的签名中,提供X-Ca-Timestamp、X-Ca-Nonce两个可选HEADER,客户端调用API时一起使用这两个参数,可以达到防止重放攻击的目的。

      

    原理

    1. 请求所有的内容都被加入签名计算,所以请求的任何修改,都会造成签名失败。
    2. 不修改内容

      • X-Ca-Timestamp:发起请求的时间,可以取自机器的本地实现。当API网关收到请求时,会校验这个参数的有效性,误差不超过15分钟。

      • X-Ca-Nonce:这个是请求的唯一标识,一般使用UUID来标识。API网关收到这个参数后会校验这个参数的有效性,同样的值,15分内只能被使用一次。

     三、代码混淆

    一、在项目根目录下新建confuse.sh 和 gbFunc.list 文件

    说明:

    confuse.sh 文件在编译过程中会执行gbFunc.list 用于自动混淆代码时,存放过滤出来需要混淆的方法名

    touch confuse.sh

    touch gbFunc.list

     

    二、新建GBConfuse.h

    说明:

    GBConfuse.h 是在自动混淆代码时,将会把自动生成的字符串定义成宏,存放在此文件,也便于查看。

    注意:需要把.h文件移到项目文件外,因为放项目文件中,到时被反编译过来,还是能得到GBConfuse.h里面的东西的,就能通过比对,得到方法。(后面用class-dump反编译过来就明白了...)

    在confuse.sh中添加如下代码

    #!/usr/bin/env bash
    
    TABLENAME=symbols
    
    SYMBOL_DB_FILE="symbols"
    
    #func.list路径
    STRING_SYMBOL_FILE="$PROJECT_DIR/GBFunc.list"
    
    #项目文件路径
    CONFUSE_FILE="$PROJECT_DIR/Safedemo"
    
    #Confuse.h路径
    HEAD_FILE="$PROJECT_DIR/GBConfuse.h"
    
    export LC_CTYPE=C
    
    #取以.m或.h结尾的文件以+号或-号开头的行 |去掉所有+号或-号|用空格代替符号|n个空格跟着<号 替换成 <号|开头不能是IBAction|用空格split字串取第二部分|排序|去重复|删除空行|删掉以init开头的行>写进func.list
    grep -h -r -I  "^[-+]" $CONFUSE_FILE  --include '*.[mh]' |sed "s/[+-]//g"|sed "s/[();,: *^/{]/ /g"|sed "s/[ ]*</</"| sed "/^[ ]*IBAction/d"|awk '{split($0,b," "); print b[2]; }'| sort|uniq |sed "/^$/d"|sed -n "/^GBSAFE_/p" >$STRING_SYMBOL_FILE
    
    
    #维护数据库方便日后作排重,以下代码来自念茜的微博
    createTable()
    {
    echo "create table $TABLENAME(src text, des text);" | sqlite3 $SYMBOL_DB_FILE
    }
    
    insertValue()
    {
    echo "insert into $TABLENAME values('$1' ,'$2');" | sqlite3 $SYMBOL_DB_FILE
    }
    
    query()
    {
    echo "select * from $TABLENAME where src='$1';" | sqlite3 $SYMBOL_DB_FILE
    }
    
    ramdomString()
    {
    openssl rand -base64 64 | tr -cd 'a-zA-Z' |head -c 16
    
    }
    
    rm -f $SYMBOL_DB_FILE
    rm -f $HEAD_FILE
    createTable
    
    touch $HEAD_FILE
    #这里也要做修改
    echo '#ifndef GBConfuse_h
    #define CodeConfuse' >> $HEAD_FILE
    echo "//confuse string at `date`" >> $HEAD_FILE
    cat "$STRING_SYMBOL_FILE" | while read -ra line; do
    if [[ ! -z "$line" ]]; then
    ramdom=`ramdomString`
    echo $line $ramdom
    insertValue $line $ramdom
    echo "#define $line $ramdom" >> $HEAD_FILE
    fi
    done
    echo "#endif" >> $HEAD_FILE
    
    
    sqlite3 $SYMBOL_DB_FILE .dump

    需要修改的代码在于文件路径:

    添加 Run Script

    添加 PCH 文件

    在ViewController中添加以"GBSAFE_"为前缀的测试方法

    测试

    运行报错如下:

    原因是.sh文件没有权限,所以需要去开启权限。

    在confuse.sh文件目录下,执行命令:

    chmod 755 confuse.sh

    运行成功!

    先打包一个.ipa安装包进行测试!

    先不进行代码混淆:

    把.ipa文件类型改成.zip,解压得到.app文件

    新建Hear文件夹用于保存反编译后得到的文件:

    用class-dump进行反编译

    class-dump -H 要破解的可执行文件路径 -o 破解后的头文件存放路径

    得到没有进行代码混淆的文件:

    可以看到都是项目中一些.h文件,打开可以看到完整的方法名....

    然后客户说测试公司说不安全...

    需要进行代码混淆...

    在PCH文件中,引用GBConfuse.h:

     

    重新打包..就可以得到混淆后的.ipa..

    下面就是混淆后的结果。

    总结:

    其实,原理应该就是在编译过程中,把需要混淆的代码生成随机字符串进行替换....

     
     
  • 相关阅读:
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
    Learn Prolog Now 翻译
  • 原文地址:https://www.cnblogs.com/fengmin/p/8178217.html
Copyright © 2011-2022 走看看