有關(guān)QZone信息流逆向的一些總結(jié)

這個項(xiàng)目因時間成本過高最終沒有繼續(xù)推進(jìn)了,這里把已經(jīng)取得的一些進(jìn)展備注一下,有興趣的同學(xué)可以了參考下。

項(xiàng)目主要在這三個方向上進(jìn)行了探索:客戶端-服務(wù)器通信協(xié)議、客戶端發(fā)起通信流程、服務(wù)端返回數(shù)據(jù)的解析流程。前兩個流程在本項(xiàng)目中只進(jìn)行了一些簡單的探索。相比較來說,第三個流程探索的更為精細(xì)與深入。

客戶端-服務(wù)器通信

QZone這個APP沒有像普通的其它資訊類應(yīng)用采用常見的http/https協(xié)議進(jìn)行客戶端與服務(wù)器的通信。而是使用了TCP協(xié)議,這一點(diǎn)可以通過Wireshark來得到驗(yàn)證。整個TCP連接建立的入口位于[WnsSDK startWnsConnection]中。WnsSDK是騰訊云向開發(fā)者推出的一個通信方案,但就我在此次逆向經(jīng)驗(yàn)推測,QZone中使用的Wns應(yīng)該是經(jīng)過嘗試定制的版本或者說是內(nèi)部版本,其基本實(shí)現(xiàn)與開放給開發(fā)者的SDK版本有著很大的不同。當(dāng)然作為參考,SDK及其開發(fā)文檔還是有著很高的價值。

通信的過程中還使用了騰訊自己特有的JCE序列化協(xié)議(功能類似于protobuf),騰訊出身的同學(xué)也許知道該協(xié)議,QZone的同學(xué)很可能有該協(xié)議的生成工具。有了該協(xié)議的生成工具,那么就可以通過classdump導(dǎo)出的頭文件反寫出整個QZone使用的序列化文件。

網(wǎng)絡(luò)請求主要類結(jié)構(gòu)

WnsSDK只是負(fù)責(zé)一些中轉(zhuǎn)的工作,GRNetReqContext是網(wǎng)絡(luò)請求上下文的緩存類,GRNetworkEngine類是整個通信流程的核心類。下圖給出了整個網(wǎng)絡(luò)請求的大致流程:


網(wǎng)絡(luò)請求流程

hook sendBizData:與handleBizData:并打印傳入的參數(shù)能夠發(fā)現(xiàn):兩個流程的參數(shù)類型為WnsBizSendData/WnsBizRecvData,WnsBizSendData類有data與bizDelegate兩個屬性值,WnsBizRecvData也有一個屬性data,很自然地就會猜測data可能就是jce對象序列化后的二進(jìn)制數(shù)據(jù),而bizDelegate通過打印值獲悉其是GRNetworkEngine對象。

如此可以推測客戶端將JCE對象序列化成二進(jìn)制數(shù)據(jù)后通過TCP協(xié)議(socket實(shí)現(xiàn))發(fā)送到服務(wù)器,接收到服務(wù)器返回的數(shù)據(jù)后交由GRNetworkEngine處理,由其負(fù)責(zé)將二進(jìn)制數(shù)據(jù)反序列化為JCE對象。

客戶端發(fā)起通信請求

這個流程沒有深入探索,只能提供下入口與方向,具體細(xì)節(jié)還需要深入[WnsSDK sendBizData:]的實(shí)現(xiàn)。這里給出hook sendBizData:函數(shù)時的一些打印日志:


sendBizData打印日志

圖中command同樣也是WnsBizSendData中的屬性值,它應(yīng)該是標(biāo)識本次請求的數(shù)據(jù)結(jié)構(gòu),值QzoneNewService.getActiveFeeds猜測就是獲取當(dāng)前feeds流的請求。

服務(wù)器返回數(shù)據(jù)的解析

WnsBizRecvData的頭文件結(jié)構(gòu)如下:

@interface WnsBizRecvData : NSObject
@property(nonatomic) int webappChangeTime; 
@property(retain, nonatomic) NSString *webappIp; 
@property(nonatomic) int tlvIndex; 
@property(nonatomic) _Bool isFinish;
@property(nonatomic) _Bool isFirst; 
@property(nonatomic) _Bool isTlvMode; 
@property(nonatomic) long long seqno; 
@property(retain, nonatomic) NSData *data; 
@end

下面的解析過程中會用到的有data、seqno,毫無疑問data應(yīng)該就是從服務(wù)器返回的二進(jìn)制數(shù)據(jù),而seqno應(yīng)該是某一標(biāo)識,通過ida對handleBizData的數(shù)據(jù)處理過程進(jìn)行分析,將其轉(zhuǎn)換成OC語言后如下:

- (void)handleBizData:(WnsBizRecvData*)recvData
{
    ?long long seqno = [recvData seqno];
    NSData* data = [recvData data];
    NSInteger length = [data length];
    BOOL finish = [recvData isFinish];
    NSNumber* seqnoNum = [NSNumber numberWithLong:seqno];
    NSDictionary* ctxMap = [[GRNetworkEngine sharedInstance] requestCtxMap];
    GRNetReqContext* context = [ctxMap objectForKey:seqnoNum];
    NSDictionary* dictionary = [NSDictionary dictionaryWithObjects:]
    id request = [context request];
    id serviceCmd = [request serviceCmd];
    if (context) {
        [request setReqStatus:2];
        [request setRecvTimestamp:[NSData timeIntervalSinceReferenceData]];
        NSString* rspValue = [self rspNameFromReq:reqest];
        Class class = NSClassFromString(rspValue);
        if (class) {
            if ([class isSubclassOfClass:([JceObjectV2 class])]) {
                UniAttribute* attri = [UniAttribute fromData:data];
                NSNumber* number = [NSNumber intValueWithName:@"ret" inAttributes:attri];
                NSString* msg = [NSString stringWithName:@"msg" inAttributes:attri];
                if (number == nil && class != [WnsHttpProxyRsp ?class]) {
                    ?NSString* shortCmd = [self shortCmdWithReq:request];
                    ?id object = [JceObjectV2 objectWithName:shortCmd inAttributes:attri];
                    [object setErrorCode:nil];
                    [object setRequest:request];
//                    [object appendTraceStr:];
                    if (shortCmd) {
                        NSDictionary* elements = [request elementRequests];
                        if ([elements count] > 0) {
                            NSMutableDictionary* response = [NSMutableDictionary dictionary];
                            [elements enumeraterKeysAndObjectsUsingBlock:^(id key, id object, BOOL finish){
                                id temp = [object objectWithName:inAttributes:attri];
                                if(temp != nil){
                                    [response setObject:temp forKey:attri];
                                }
                            }];
                            [object setElementResponces:response];
                            [self notifyResponder:context response:object error:nil requestInfo:nil busiserverip:nil];
                        }
                    }
                }
            }
        }
    }
}

這個過程中最重要的一步是[JceObjectV2 objectWithName:inAttribute:],在這個過程里JCE對象的主體被解析出來,下面的流程只是對該對象的一些屬性進(jìn)行補(bǔ)充。debugserver-lldb打印的JCE類名如下圖:


Feeds流類名

WnsBizRecvData中的data被轉(zhuǎn)化成了UniAttribute對象,這個對象實(shí)質(zhì)上就是一個由string-data構(gòu)成的字典類型。通過debugserver-lldb能夠?qū)崟r的打印出該對象的內(nèi)容如下:


UniAttribute內(nèi)容

打印[requset elementRequests]內(nèi)容如下:
key-type鍵值對

可以猜測其實(shí)質(zhì)上就是通過key值來標(biāo)識數(shù)據(jù)對應(yīng)的JCE結(jié)構(gòu),通過遍歷將UniAttribute對象中的數(shù)據(jù)轉(zhuǎn)換成具體的JCE對象。當(dāng)然這些諸如ModeEntryContent/hostQboss/hostQzmall具體代表著什么,只能靠推測與進(jìn)一步驗(yàn)證了。
解析得到的對象會通過notifyResponder:response:error:requestInfo:busiserverip:接口發(fā)送出去。跟蹤該接口的實(shí)現(xiàn),能夠確定對象最終會進(jìn)入到QzoneNewFeedManager中的responseDicWithRsp:Req:Parameters:complete:作進(jìn)一步的處理。

最終傳入到QzoneNewFeedManager中處理的feed流數(shù)據(jù)類似于下圖,也就是說至此數(shù)據(jù)依然不可讀,而如何轉(zhuǎn)換成可讀的明文數(shù)據(jù),就需要參考responseDicWithRsp:Req:Parameters:complete:處理過程了。


末解密的feed信息

結(jié)尾

這里只是記錄自己在項(xiàng)目中所發(fā)現(xiàn)的一些東西,很遺憾不能從總體上給出一個完善的逆向結(jié)論。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 12,442評論 6 13
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,612評論 19 139
  • 簡介 用簡單的話來定義tcpdump,就是:dump the traffic on a network,根據(jù)使用者...
    保川閱讀 6,086評論 1 13
  • “真自由訓(xùn)練營”是由幸福進(jìn)化進(jìn)化俱樂部發(fā)起的元習(xí)慣提升類產(chǎn)品,活動具體內(nèi)容請詳見:http://blog.hidd...
    非凡說閱讀 495評論 2 0
  • 一年前的今天是我十九歲人生最記憶深刻的日子。高考成績出來的那一刻,其實(shí)我內(nèi)心是平靜的,我很清楚我高三那種行尸走肉...
    不愛說話的痞子閱讀 751評論 4 9

友情鏈接更多精彩內(nèi)容