欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

高手談AndroidNDKC++RTTI分析-創(chuàng)新互聯(lián)

本文意在說明Android NDK 在實(shí)現(xiàn)C++ RTTI時(shí)的相關(guān)數(shù)據(jù)結(jié)構(gòu),并從匯編角度分析其內(nèi)存布局,以幫助理解RTTI的實(shí)現(xiàn)原理,同時(shí),分析在逆向過程中如何利用RTTI恢復(fù)C++類名信息。
 高手談Android NDK C++ RTTI 分析
    用ndk-build編譯C++代碼時(shí),默認(rèn)的C++運(yùn)行時(shí)庫(libstdc++)是不支持RTTI的, 需要在Application.mk與Android.mk中進(jìn)行配置。其它可以選擇的C++運(yùn)行時(shí)庫有GAbi++、STLport、GNU STL、LLVM libc++, 各種庫又分靜態(tài)鏈接庫與動(dòng)態(tài)鏈接庫。其中中STLport的RTTI是借用了GAbi++中的實(shí)現(xiàn),另外GNU STL、LLVM libc++的實(shí)現(xiàn)也與GAbi++非常相似(相關(guān)數(shù)據(jù)結(jié)構(gòu)的命名、結(jié)構(gòu)都相似, 可能是因?yàn)槎际腔贗tanium C++ ABI(鏈接[3])?)。
     所以本文將選擇STLPort為C++運(yùn)行時(shí)庫, 在Application.mk中配置:
    APP_STL := stlport_static
    在Android.mk中配置:
    LOCAL_CPP_FEATURES := rtti
    另外,本文使用 Android NDK 10c編譯,編譯abi為armeabi,編譯32位代碼時(shí)其默認(rèn)使用GCC 4.8。若使用其它版本NDK或者其它編譯器,可能與本文分析結(jié)果有差異。

一、C++ RTTI 簡介
     RTTI是Runtime Type Identification的縮寫,即運(yùn)行時(shí)類型識(shí)別。程序能夠借此使用基類的指針或引用,來檢查這些指針或引用所指的對象的實(shí)際派生類型。C++通過typeid與dynamic_cast來提供RTTI。typeid返回一個(gè)typeinfo對象的引用,它記錄了與類型相關(guān)的信息,后文將詳細(xì)分析這個(gè)結(jié)構(gòu);dynamic_cast用于安全而有效地進(jìn)行向下轉(zhuǎn)型(down_cast),即安全地將一個(gè)基類指針轉(zhuǎn)換為一個(gè)派生類指針。
它們的基本使用方法如下:
classes.h文件:

class Base
{
   public:
   Base();
   virtual ~Base();
   virtual void Func();
   private:
   int mMember;
};

class Deriver1 : public Base
      {
public:
      Deriver1();
      virtual ~Deriver1();
       virtual void Func();
private:
      int mDeriver1Member;
      };

class Deriver2 : public Base
      {
public:
      Deriver2();
      virtual ~Deriver2();
      virtual void Func();
private:
       int mDeriver2Member;
      };

main.cpp文件:
int main()
{
   Base base;
   Deriver1 deriver1;
   Deriver2 deriver2;

   cout<<typeid(int).name()<<endl;
   cout<<typeid(Base).name()<<endl;
   cout<<typeid(base).name()<<endl;
   Base *pBase = &deriver1;
   cout<<typeid(pBase).name()<<endl;
   cout<<typeid(*pBase).name()<<endl;

   cout << pBase << endl;
   Driver1 *pDeriver1 = dynamic_cast<Deriver1*>(pBase);
   cout << pDeriver1 << endl;

   Driver2 *pDeriver2 = dynamic_cast<Deriver2*>(pBase); //正確,返回NULL
   cout << pDeriver2 << endl;

   pDeriver2 = (Deriver2*)pBase;//錯(cuò)誤
   cout << pDeriver2 << endl;

   pDeriver2 = static_cast<Deriver2*>(pBase); //錯(cuò)誤
   cout << pDeriver2 << endl;
   return 0;
}
編譯成可執(zhí)行文件,push到android 手機(jī)上運(yùn)行,輸出:
i <------- typeid(int).name(), 變量類型
4Base <------- typeid(Base).name(), 類名
4Base <------- typeid(base).name(), 變量
P4Base <------- typeid(pBase).name(), Base的指針類型
8Deriver1 <------- typeid(*pBase).name(), pBase實(shí)際指向一個(gè)Deriver1
0xbec87a20
0xbec87a20 <----- 正確的轉(zhuǎn)換,指向deriver1的基類指針可以轉(zhuǎn)換為Deriver1類型指針
0x00000000 <----- 正確的轉(zhuǎn)換,因?yàn)橹赶騞eriver1的基類指針并不能轉(zhuǎn)換為Deriver2類型指針
0xbec87a20 <----- 錯(cuò)誤,若繼續(xù)使用,可能會(huì)導(dǎo)致內(nèi)存訪問出錯(cuò),即將Dervier1當(dāng)Deriver2用
0xbec87a20 <----- 錯(cuò)誤,若繼續(xù)使用,可能會(huì)導(dǎo)致內(nèi)存訪問出錯(cuò)

P.S. 上面看到顯示的類名與我們定義的不完全一樣,是因?yàn)闉榱吮WC每個(gè)類名稱在程序中的唯一性,編譯器會(huì)通過一定的規(guī)則對原始類名進(jìn)行改寫,如想了解這一規(guī)則,可以以name mangling為關(guān)鍵詞進(jìn)行搜索。

二、RTTI 相關(guān)數(shù)據(jù)結(jié)構(gòu)
    上文說到typeid將返回一個(gè)typeinfo對象的const引用,RTTI就是依賴typeinfo類及其派生類來實(shí)現(xiàn)的,下面介紹下這些類。
在NDK路徑下\android-ndk-r10c\sources\cxx-stl\gabi++\include\typeinfo文件中有定義這個(gè)類:
class type_info
{
    public:
   virtual ~type_info();
//....
    private:
//....
       const char *__type_name; // 這個(gè)字段記錄改寫過后的類名
};
    在NDK路徑下\android-ndk-r10c\sources\cxx-stl\gabi++\src\cxxabi_defines.h有定義一些typeinfo的派生類,此處挑一些我們感興趣的類列舉:
class __shim_type_info : public std::type_info{....}

// 無基類的類的typeinfo類型
class __class_type_info : public __shim_type_info{.....}

//只有一個(gè)public非虛基類,且基類偏移為0的類的typeinfo
class __si_class_type_info : public __class_type_info{
public:
      virtual ~__si_class_type_info();
      const __class_type_info *__base_type;
//......
}

// 有基類但不滿足 __si_class_type_info 約束條件的其它類的typeinfo
class __vmi_class_type_info : public __class_type_info{
public:
      virtual ~__vmi_class_type_info();
      unsigned int __flags;
      unsigned int __base_count;
      __base_class_type_info __base_info[1];
//......
}

// Used in __vmi_class_type_info
      struct __base_class_type_info{
public:
      const __class_type_info *__base_type;
      long __offset_flags;
// .......
}
    以第1小節(jié)中的程序?yàn)槔?,Base、Driver1的對象的內(nèi)存布局如下:
高手談Android NDK C++ RTTI 分析

    deriver2的內(nèi)存布局與deriver1相似,這里沒有重復(fù)畫出。從上圖可以看到,每一個(gè)類的虛表索引為-1的位置存放著typeinfo的指針,并根據(jù)類的不同,該指針指向不同的typeinfo派生類實(shí)例。比如Base類無基類,所以其typeinfo指針指向__class_type_info的實(shí)例;而Deriver1繼承自Base, deriver1在其偏移為0的位置包含一個(gè)public非虛基類實(shí)例,所以它的typeinfo指針指向__si_class_type_info實(shí)例。使用dynamic_cast的時(shí)候,正是根據(jù)這些typeinfo指針來判斷一個(gè)基類指針是否可以轉(zhuǎn)換為一個(gè)派生類指針。而且由上可見,若一個(gè)待操作的類沒有虛函數(shù)表, typeid也只能返回其靜態(tài)類型。
下面我們通過反編譯代碼來驗(yàn)證上面的關(guān)系圖。

三、逆向過程中利用RTTI恢復(fù)類名
    將第1小節(jié)中生成的可執(zhí)行程序用IDA Pro打開,此處選用obj\local\armeabi\目錄下未經(jīng)過strip的程序,以方便分析。
根據(jù)相關(guān)字符串,可以很快定位各個(gè)類的typeinfo信息:
高手談Android NDK C++ RTTI 分析
各個(gè)類的虛函數(shù)表結(jié)構(gòu):
高手談Android NDK C++ RTTI 分析
    細(xì)心的朋友可能有疑問,為什么會(huì)產(chǎn)生兩個(gè)構(gòu)造函數(shù)?對于這個(gè)問題,可以參考鏈接[4]。
可見,從反編譯的代碼看,虛表、typeinfo信息關(guān)系與第3節(jié)中描述一致。
    對于通常的逆向分析,都沒有沒有上面的符號信息的。所以我們可以通過RTTI信息來恢復(fù)類名及其類間關(guān)系,為逆向工作提供便利。可以按以下步驟進(jìn)行:

成都創(chuàng)新互聯(lián)公司技術(shù)團(tuán)隊(duì)十載來致力于為客戶提供網(wǎng)站制作、成都網(wǎng)站建設(shè)、成都品牌網(wǎng)站建設(shè)、營銷型網(wǎng)站建設(shè)、搜索引擎SEO優(yōu)化等服務(wù)。經(jīng)過多年發(fā)展,公司擁有經(jīng)驗(yàn)豐富的技術(shù)團(tuán)隊(duì),先后服務(wù)、推廣了上1000家網(wǎng)站,包括各類中小企業(yè)、企事單位、高校等機(jī)構(gòu)單位。
  1. 定位__class_type_info, __si_class_type_info, __vmi_class_type_info虛函數(shù)表。

  2. 查找對這些虛函數(shù)表的引用,我們可以得到這些typeinfo派生類的實(shí)例地址。而這些實(shí)例中type_name字段就表示原始類名。

  3. 根據(jù)引用這些實(shí)例地址,就可以得到相關(guān)類的虛表地址,此處我們可以根據(jù)上一步得到的原始類名重命名虛表指針。

  4. 查找引用這些虛表指針的代碼,通過都是類的構(gòu)造函數(shù),于是我們又可以重命名這些構(gòu)造函數(shù)了。

以上步驟我們都可以通過IDAPython腳本自動(dòng)完成。

四、小結(jié)
    其實(shí)上面只是分析了最簡單的單繼承情景,還有諸如多繼承、虛繼承等情景待分析,由于相關(guān)typeinfo類已經(jīng)例出,相信分析難度不大。
    另外需要注意的一個(gè)地方,在反匯編后的代碼中,并不是直接引用虛表地址,而是引用虛表地址-8的位置,用這個(gè)位置+8寫入當(dāng)作虛擬指針。
    以上分析過程與結(jié)論都來自個(gè)人認(rèn)知,如有錯(cuò)誤,歡迎指正。

網(wǎng)易云捕-高效的APP質(zhì)量跟蹤平臺(tái)

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

當(dāng)前標(biāo)題:高手談AndroidNDKC++RTTI分析-創(chuàng)新互聯(lián)
文章源于:http://aaarwkj.com/article16/gddgg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、小程序開發(fā)定制開發(fā)品牌網(wǎng)站設(shè)計(jì)、移動(dòng)網(wǎng)站建設(shè)、App設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司
欧美日韩在线视频第三区| 中文字幕欧美精品日韩人妻| 97国产在线视频观看| 欧美一区二区三区情色| 国产亚洲欧美日韩精品| 久久精品国产久精国产爱| 亚洲美女高潮久久久久久久久| 特级特色生活片免费看| 91精品国产自产在线观看| 青青草原激情综合网| 天堂av影片在线观看| 日韩一区二区三精品| 国产精品一区二区三区专区| 日本av高清视频在线观看| 美国真人性做爰视频免费| 日韩精品中文字幕电影| 国产一区二区三区性色| 在线看片国产精品自拍| 国产一区二区精品不卡| 欧美一区二区三区人妻熟妇| 未满18禁止入内在线观看| 久久午夜av一区二区| 男人天堂在线视频网站| 国产亚洲欧美精品久久久久久| 五月婷婷丁香六月在线综合| 欧美国产日本日韩在线黄| 中文字幕乱码av一区二区| 哪里可以看日韩免费毛片| 麻豆视传媒官网免费观看| 亚州中文字幕久久一区| 色噜噜人妻av中文字幕| 日韩高清av一区二区三区| 欧美黄色一区二区三区精品| 人体蜜桃视频一区二区| 国产精品国产精品国产| 国产精品夫妇在线激情啪| 丰满人妻被猛烈进入中| 四虎精品视频在线免费| 日韩福利成人av在线| 日本精品在线亚洲国产欧美| 国产精品国产三级国产专区|