美文网首页iOS开发常用知识点iOS网络iOS-逆向
让别人的app变成自己的app — 砸壳,破解,逆向,拦截,重定

让别人的app变成自己的app — 砸壳,破解,逆向,拦截,重定

作者: 船长_Kevin | 来源:发表于2020-04-15 14:11 被阅读0次

    让别人的app变成自己的app系列 -- 拦截网络请求后进行网址或ip替换

    注: 本文仅用于学习研究,请勿用于非法用途 \color{#889008}{交流群 1060356414}

    破解APP的方法很多,如砸壳破解逆行等,或者修改Macho文件,但由于很多网站由于加了密,这些办法都不行.今天我们在这里讲一个终极办法拦截网络请求或者替换IP的方法.

    1:应用场景

    • \color{red}{除去设备锁,或时间锁}
      比如某些抢红包应用有设备锁或者时间锁,按设备或者按年付费,部分用户不想付费的话,我们可以通过拦截网络,mock data 来破解此类应用;

    • \color{red}{部署多套授权的系统}
      一些人买了一套系统, app端访问的接口是写死在打包好的二进制文件,想部署多套应用无法部署.这个时候可以通过拦截网络请求后进行服务器地址替换,完成多套部署.

    2:实现原理

    要想拦截,我们需要先弄懂IOS的网络请求原理,请看下图

    # 网络 <--> NSURLProtocol <--> 网络库
    

    大部分的网络请求都要通过一个叫NSURLProtocol 的抽象类,既然都要通过这个抽象类,那我们是不是通过重载NSURLProtocol的方式进行网络请求的拦截与过滤呢,答案当然是肯定的.但世界上没有银弹,NSURLProtocol不能解决所有的问题,为什么呢.因为NSURLProtocol可以拦截的网络请求包括NSURLSession,NSURLConnection。现在主流的iOS网络库,例如AFNetworking,Alamofire等网络库都是基于NSURLSession或NSURLConnection的,所以这些网络库的网络请求都可以被NSURLProtocol所拦截。

    PS:基于CFNetwork的网络请求,以及WKWebView的请求是无法拦截的。例如ASIHTTPRequest,MKNetwokit等网路库都是基于CFNetwork的,所以这些网络库的网络请求无法被NSURLProtocol拦截。

    3.实现步骤

    1、创建NSURLProtocol子类

    由于NSURLProtocol是一个抽象类,要使用它的时候需要创建它的一个子类。.m文件如下:

    #import "ReplaceURLProtocol.h"
    // 为了避免canInitWithRequest和canonicalRequestForRequest的死循环
    static NSString *const URLProtocolHandledKey = @"URLProtocolHandledKey";
    
    // 老url网址
    static NSString *const  old_url = @"baidu.com";
    // 新url网址
    static NSString *const  new_url = @"google.com";
    @interface ReplaceURLProtocol()<NSURLSessionDelegate>
    @property(nonatomic,strong)NSURLSession * session;
    @end
    
    @implementation ReplaceURLProtocol
    +(BOOL)canInitWithRequest:(NSURLRequest *)request
    {
      return YES;
    }
    //改变请求request
    +(NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
    {
     // 业务逻辑写这里
      return request;
    }
    
    //开始请求
    -(void)startLoading
    {
     //业务逻辑写这里
    }
    
    //停止请求
    -(void)stopLoading
    {
    }
    
    #pragma mark ---- NSURLSessionDelegate
    /*
      NSURLSessionDelegate接到数据后,通过URLProtocol传出去
     */
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    {
      if (error)
      {
        [self.client URLProtocol:self didFailWithError:error];
      }
      else
      {
        [self.client URLProtocolDidFinishLoading:self];
      }
    }
    
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
      
      [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
      completionHandler(NSURLSessionResponseAllow);
      
    }
    
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
    {
      [self.client URLProtocol:self didLoadData:data];
    }
    
    @end
    

    2、注册protocol

    基于NSURLConnection或[NSURLSession sharedSession]创建的网络请求,在AppDelegate的didFinishLaunchingWithOptions方法中调用registerClass方法即可。

    //注册protocol 
    [NSURLProtocol registerClass:[ReplaceURLProtocol class]];returnYES;}
    

    3、拦截用户的网络请求
    首先,在拦截到网络请求后会先调用+(BOOL)canInitWithRequest:(NSURLRequest *)request方法。我们可以在该方法里进行是否处理这个拦截的逻辑。如设置只对拦截到的http或https请求进行处理。

    +(BOOL)canInitWithRequest:(NSURLRequest *)request
    {
       // 不是网络请求,不处理
        if (![request.URL.scheme isEqualToString:@"http"] &&
            ![request.URL.scheme isEqualToString:@"https"]) {
            return NO;
        }
        
        //     指定拦截网络请求,如:www.baidu.com
        if ([request.URL.absoluteString containsString:old_url]) {
            return YES;
        }else {
            return NO;
        }
    }
    

    接着,会调用+(NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request在该方法中,我们可以对request进行处理。例如修改头部信息等。最后返回一个处理后的request实例。也可以在该方法里面将用户的请求域名替换成别的域名:

    /**
     设置我们自己的自定义请求
     可以在这里统一加上头之类的
     @param request 应用的此次请求
     @return 我们自定义的请求
     */
    + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
        NSMutableURLRequest *mutableReqeust = [request mutableCopy];
        // 设置已处理标志
        [NSURLProtocol setProperty:@(YES)
                            forKey:kProtocolHandledKey
                         inRequest:mutableReqeust];
        NSLog(@"************ 原始请求的url1 %@",request.URL);
        if ([request.URL host].length == 0)
        {
            return request;
        }
        
        NSString * originUrlStr = [request.URL absoluteString];
        NSString * originHostStr = [request.URL host];
        NSRange hostRange = [originUrlStr rangeOfString:originHostStr];
        
        if (hostRange.location == NSNotFound)
        {
            return request;
        }
        
        //指定拦截网络请求,如:www.baidu.com
        if ([request.URL.absoluteString containsString:old_url]) {
            //定向到百度搜索
            NSString * ip = new_url;
            NSString * urlStr = [originUrlStr stringByReplacingCharactersInRange:hostRange withString:ip];
            NSURL * url = [NSURL URLWithString:urlStr];
            mutableReqeust.URL = url;
            
            NSLog(@"************ 替换后的url 1 %@",mutableReqeust.URL);
            
            return [mutableReqeust copy];
        }
        else{
            return request;
        }
    
    

    4、转发

    -(void)startLoading将处理过的request重新发送出去。发送的形式,可以是基于NSURLConnection,NSURLSession甚至CFNetwork。我们也可以在该方法里面设置网络代理,如下我们设置一个代理后,重新创建一个NSURLSession将网络请求发送出去:

    // 重新父类的开始加载方法
    - (void)startLoading {
        
        NSMutableURLRequest * mutableRequest = [[self request] mutableCopy];
        NSLog(@"************ 开始请求 %@",mutableRequest.URL);
        NSURLSessionConfiguration * configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];//创建一个临时会话配置
        //网络请求
        self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
    // 注 这里也可以添加代理 捕获用户请求数据
        NSURLSessionTask * task = [self.session dataTaskWithRequest:self.request];
        [task  resume];//开始任务
    
    }
    

    5、回调

    上面使用的是NSURLSession请求,所以我们通过NSURLSessionDelegate来接收网络请求的数据(成功或失败等信息):

    #pragma mark ---- NSURLSessionDelegate
    /*
      NSURLSessionDelegate接到数据后,通过URLProtocol传出去
     */
    //失败
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    {
      if (error)
      {
        [self.client URLProtocol:self didFailWithError:error]; //请求错误
      }
      else
      {
        [self.client URLProtocolDidFinishLoading:self]; //完成加载
      }
    }
    //接收到响应
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
      
      [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; //创建一个响应(缓存策略:不缓存)
      completionHandler(NSURLSessionResponseAllow);
      
    }
    //接收到数据
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
    {
      [self.client URLProtocol:self didLoadData:data]; //接收到数据
    }
    

    6、结束

    在-(void)stopLoading完成网络请求的操作

    //结束请求
    -(void)stopLoading
    {
      [self.session invalidateAndCancel];
      self.session = nil;
    }
    

    相关文章

      网友评论

        本文标题:让别人的app变成自己的app — 砸壳,破解,逆向,拦截,重定

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