美文网首页
拦截所有app的网络请求

拦截所有app的网络请求

作者: Andyzhao | 来源:发表于2019-08-04 20:05 被阅读0次

    前提 : 有时会遇到这样的需求:将一些别人app上比较优质的内容,用到自己产品中.由于别人的app做了大量的参数加密, 我们获取不到加密规则,所以使用接口直接调用的方法就走不通.

    本文就是要介绍使用逆向技术拦截目标app的所有网络请求.对于我们需要的接口数据上传到我们自己的服务器中

    工具:
    monkeyDev
    PPSNetworkMonitor开源库中的代码

    代码如下:

    PPSURLSessionConfiguration.h

    @interface PPSURLSessionConfiguration : NSObject
    
    @property (nonatomic,assign) BOOL isSwizzle;
    
    + (PPSURLSessionConfiguration *)defaultConfiguration;
    
    /**
     *  swizzle NSURLSessionConfiguration's protocolClasses method
     */
    - (void)load;
    
    /**
     *  make NSURLSessionConfiguration's protocolClasses method is normal
     */
    - (void)unload;
    
    @end
    

    PPSURLSessionConfiguration.m

    #import "PPSURLSessionConfiguration.h"
    #import <objc/runtime.h>
    #import "PPSURLProtocol.h"
    
    @implementation PPSURLSessionConfiguration
    
    
    + (PPSURLSessionConfiguration *)defaultConfiguration {
        
        static PPSURLSessionConfiguration *staticConfiguration;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            staticConfiguration=[[PPSURLSessionConfiguration alloc] init];
        });
        return staticConfiguration;
        
    }
    - (instancetype)init {
        self = [super init];
        if (self) {
            self.isSwizzle=NO;
        }
        return self;
    }
    
    - (void)load {
        
        self.isSwizzle=YES;
        Class cls = NSClassFromString(@"__NSCFURLSessionConfiguration") ?: NSClassFromString(@"NSURLSessionConfiguration");
        [self swizzleSelector:@selector(protocolClasses) fromClass:cls toClass:[self class]];
        
    }
    
    - (void)unload {
        
        self.isSwizzle=NO;
        Class cls = NSClassFromString(@"__NSCFURLSessionConfiguration") ?: NSClassFromString(@"NSURLSessionConfiguration");
        [self swizzleSelector:@selector(protocolClasses) fromClass:cls toClass:[self class]];
        
    }
    
    - (void)swizzleSelector:(SEL)selector fromClass:(Class)original toClass:(Class)stub {
        
        Method originalMethod = class_getInstanceMethod(original, selector);
        Method stubMethod = class_getInstanceMethod(stub, selector);
        if (!originalMethod || !stubMethod) {
            [NSException raise:NSInternalInconsistencyException format:@"Couldn't load NEURLSessionConfiguration."];
        }
        method_exchangeImplementations(originalMethod, stubMethod);
    }
    
    - (NSArray *)protocolClasses {
        
        return @[[PPSURLProtocol class]];
        //如果还有其他的监控protocol,也可以在这里加进去
    }
    
    @end
    
    

    PPSURLProtocol.h

    @interface PPSURLProtocol : NSURLProtocol
    
    + (void)start;
    
    + (void)end;
    
    @end
    

    PPSURLProtocol.m

    #import "PPSURLSessionConfiguration.h"
    
    static NSString *const PPSHTTP = @"PPSHTTP";//为了避免canInitWithRequest和canonicalRequestForRequest的死循环
    
    @interface PPSURLProtocol()<NSURLConnectionDelegate,NSURLConnectionDataDelegate>
    
    @property (nonatomic, strong) NSURLConnection *connection;
    @property (nonatomic, strong) NSURLRequest *pps_request;
    @property (nonatomic, strong) NSURLResponse *pps_response;
    @property (nonatomic, strong) NSMutableData *pps_data;
    
    
    @end
    
    @implementation PPSURLProtocol
    
    #pragma mark - init
    - (instancetype)init {
        self = [super init];
        if (self) {
        }
        return self;
    }
    
    + (void)load {
        
    }
    
    + (void)start {
        PPSURLSessionConfiguration *sessionConfiguration = [PPSURLSessionConfiguration defaultConfiguration];
        [NSURLProtocol registerClass:[PPSURLProtocol class]];
        if (![sessionConfiguration isSwizzle]) {
            [sessionConfiguration load];
        }
    }
    
    + (void)end {
        PPSURLSessionConfiguration *sessionConfiguration = [PPSURLSessionConfiguration defaultConfiguration];
        [NSURLProtocol unregisterClass:[PPSURLProtocol class]];
        if ([sessionConfiguration isSwizzle]) {
            [sessionConfiguration unload];
        }
    }
    
    
    /**
     需要控制的请求
    
     @param request 此次请求
     @return 是否需要监控
     */
    + (BOOL)canInitWithRequest:(NSURLRequest *)request {
        
        if (![request.URL.scheme isEqualToString:@"http"] &&
            ![request.URL.scheme isEqualToString:@"https"]) {
            return NO;
        }
        //如果是已经拦截过的  就放行
        if ([NSURLProtocol propertyForKey:PPSHTTP inRequest:request] ) {
            return NO;
        }
        return YES;
    }
    
    /**
     设置我们自己的自定义请求
     可以在这里统一加上头之类的
     
     @param request 应用的此次请求
     @return 我们自定义的请求
     */
    + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
        NSMutableURLRequest *mutableReqeust = [request mutableCopy];
        [NSURLProtocol setProperty:@YES
                            forKey:PPSHTTP
                         inRequest:mutableReqeust];
        return [mutableReqeust copy];
    }
    
    - (void)startLoading {
        NSURLRequest *request = [[self class] canonicalRequestForRequest:self.request];
        self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
        self.pps_request = self.request;
    }
    
    - (void)stopLoading {
        [self.connection cancel];
    
        //获取请求方法
        NSString *requestMethod = self.pps_request.HTTPMethod;
        NSLog(@"请求方法:%@\n",requestMethod);
        
        //获取请求头
        NSDictionary *headers = self.pps_request.allHTTPHeaderFields;
        NSLog(@"请求头:\n");
        for (NSString *key in headers.allKeys) {
            NSLog(@"%@ : %@",key,headers[key]);
        }
    
        //获取请求结果
       // 上传拦截结果到我们自己服务器上
        NSString *string = [self responseJSONFromData:self.pps_data];
        NSLog(@"请求结果:%@",string);
        if ([[self.request.URL absoluteString] containsString:@"liked"]) {
            NSURLSession *session = [NSURLSession sharedSession];
            NSURL *url = [NSURL URLWithString:@"xxxx"];
            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
            request.HTTPMethod = @"POST";
            request.HTTPBody = [[NSString stringWithFormat:@"json_data=%@", string] dataUsingEncoding:NSUTF8StringEncoding];
            
            NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            }];
            [dataTask resume];
        }
        
    }
    
    #pragma mark - NSURLConnectionDelegate
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
        [self.client URLProtocol:self didFailWithError:error];
    }
    
    - (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection{
        return YES;
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
        [self.client URLProtocol:self didReceiveAuthenticationChallenge:challenge];
    }
    
    - (void)connection:(NSURLConnection *)connection
    didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
        [self.client URLProtocol:self didCancelAuthenticationChallenge:challenge];
    }
    
    #pragma mark - NSURLConnectionDataDelegate
    -(NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response{
        
        if (response != nil) {
            self.pps_response = response;
            [self.client URLProtocol:self wasRedirectedToRequest:request redirectResponse:response];
        }
        return request;
    }
    
    - (void)connection:(NSURLConnection *)connection
    didReceiveResponse:(NSURLResponse *)response {
        [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
        self.pps_response = response;
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
        [self.client URLProtocol:self didLoadData:data];
        [self.pps_data appendData:data];
        NSLog(@"receiveData");
    }
    
    - (NSCachedURLResponse *)connection:(NSURLConnection *)connection
                      willCacheResponse:(NSCachedURLResponse *)cachedResponse {
        return cachedResponse;
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
        [[self client] URLProtocolDidFinishLoading:self];
    }
    
    //转换json
    -(id)responseJSONFromData:(NSData *)data {
        if(data == nil) return nil;
        NSError *error = nil;
        id returnValue = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
        if(error) {
            NSLog(@"JSON Parsing Error: %@", error);
            //https://github.com/coderyi/NetworkEye/issues/3
            return nil;
        }
        //https://github.com/coderyi/NetworkEye/issues/1
        if (!returnValue || returnValue == [NSNull null]) {
            return nil;
        }
        
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:returnValue options:NSJSONWritingPrettyPrinted error:nil];
        NSString *jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
        return jsonString;
    }
    
    - (NSMutableData *)pps_data {
        if (!_pps_data) {
            _pps_data = [NSMutableData data];
        }
        return _pps_data;
    }
    
    @end
    
    

    如上两个文件导入MonkeyDev中 就会在如下方法中

    - (void)stopLoading {...}
    

    拦截你所导入的目标ipa的所有网络请求 .

    根据抓包地址确定你需要的接口数据进行过滤

    // 例如我需要的接口xxx
     if ([[self.request.URL absoluteString] containsString:@"xxxx"]){}
    

    好了 到此为止拦击所有app的网络请求就完成了, 如果有不明白或者工具不会使用的留言,看到就会回答. 感谢大家!!!

    相关文章

      网友评论

          本文标题:拦截所有app的网络请求

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