攔截所有app的網(wǎng)絡(luò)請求

前提 : 有時會遇到這樣的需求:將一些別人app上比較優(yōu)質(zhì)的內(nèi)容,用到自己產(chǎn)品中.由于別人的app做了大量的參數(shù)加密, 我們獲取不到加密規(guī)則,所以使用接口直接調(diào)用的方法就走不通.

本文就是要介紹使用逆向技術(shù)攔截目標(biāo)app的所有網(wǎng)絡(luò)請求.對于我們需要的接口數(shù)據(jù)上傳到我們自己的服務(wù)器中

工具:
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]];
    //如果還有其他的監(jiān)控protocol悍赢,也可以在這里加進(jìn)去
}

@end

PPSURLProtocol.h

@interface PPSURLProtocol : NSURLProtocol

+ (void)start;

+ (void)end;

@end

PPSURLProtocol.m

#import "PPSURLSessionConfiguration.h"

static NSString *const PPSHTTP = @"PPSHTTP";//為了避免canInitWithRequest和canonicalRequestForRequest的死循環(huán)

@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 是否需要監(jiān)控
 */
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
    
    if (![request.URL.scheme isEqualToString:@"http"] &&
        ![request.URL.scheme isEqualToString:@"https"]) {
        return NO;
    }
    //如果是已經(jīng)攔截過的  就放行
    if ([NSURLProtocol propertyForKey:PPSHTTP inRequest:request] ) {
        return NO;
    }
    return YES;
}

/**
 設(shè)置我們自己的自定義請求
 可以在這里統(tǒng)一加上頭之類的
 
 @param request 應(yīng)用的此次請求
 @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]);
    }

    //獲取請求結(jié)果
   // 上傳攔截結(jié)果到我們自己服務(wù)器上
    NSString *string = [self responseJSONFromData:self.pps_data];
    NSLog(@"請求結(jié)果:%@",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];
}

//轉(zhuǎn)換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

如上兩個文件導(dǎo)入MonkeyDev中 就會在如下方法中

- (void)stopLoading {...}

攔截你所導(dǎo)入的目標(biāo)ipa的所有網(wǎng)絡(luò)請求 .

根據(jù)抓包地址確定你需要的接口數(shù)據(jù)進(jìn)行過濾

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

好了 到此為止攔擊所有app的網(wǎng)絡(luò)請求就完成了, 如果有不明白或者工具不會使用的留言,看到就會回答. 感謝大家!!!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末室琢,一起剝皮案震驚了整個濱河市治专,隨后出現(xiàn)的幾起案子潜支,更是在濱河造成了極大的恐慌毛俏,老刑警劉巖奔则,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件技即,死亡現(xiàn)場離奇詭異腌闯,居然都是意外死亡绳瘟,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進(jìn)店門姿骏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來糖声,“玉大人,你說我怎么就攤上這事≌盒海” “怎么了琉苇?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長悦施。 經(jīng)常有香客問我并扇,道長,這世上最難降的妖魔是什么抡诞? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任穷蛹,我火速辦了婚禮,結(jié)果婚禮上昼汗,老公的妹妹穿的比我還像新娘肴熏。我一直安慰自己,他們只是感情好顷窒,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布蛙吏。 她就那樣靜靜地躺著,像睡著了一般鞋吉。 火紅的嫁衣襯著肌膚如雪鸦做。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天坯辩,我揣著相機(jī)與錄音馁龟,去河邊找鬼。 笑死漆魔,一個胖子當(dāng)著我的面吹牛坷檩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播改抡,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼矢炼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了阿纤?” 一聲冷哼從身側(cè)響起句灌,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎欠拾,沒想到半個月后胰锌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡藐窄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年资昧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荆忍。...
    茶點(diǎn)故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡格带,死狀恐怖撤缴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情叽唱,我是刑警寧澤屈呕,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站棺亭,受9級特大地震影響虎眨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜镶摘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一专甩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧钉稍,春花似錦、人聲如沸棺耍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蒙袍。三九已至俊卤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間害幅,已是汗流浹背消恍。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留以现,地道東北人狠怨。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像邑遏,于是被迫代替她去往敵國和親佣赖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,089評論 1 32
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,868評論 6 13
  • AFHTTPRequestOperationManager 網(wǎng)絡(luò)傳輸協(xié)議UDP记盒、TCP憎蛤、Http、Socket纪吮、X...
    Carden閱讀 4,319評論 0 12
  • iOS網(wǎng)絡(luò)架構(gòu)討論梳理整理中俩檬。。碾盟。 其實(shí)如果沒有APIManager這一層是沒法使用delegate的棚辽,畢竟多個單...
    yhtang閱讀 5,165評論 1 23
  • 記憶中的他們都是日常的樣子 神態(tài)自若,平淡安詳 直到有一天突然意識到他們老了 是的… 直到他們老的躺在醫(yī)院病床上再...
    舊城xu閱讀 302評論 0 0