iOS逆向

前言:想必大家都知道了维苔,新浪閱讀整個(gè)業(yè)務(wù)線砍掉的事情,是的茫负,朕的大清亡了蕉鸳,不過賠償很到位,也有了幸福感忍法。從北京回到鄭州休息好一陣子,思考了一下未來的工作方向榕吼,業(yè)余時(shí)間總結(jié)一下所學(xué)知識(shí)吧饿序。

以下就是學(xué)習(xí)過程中的筆記!

  • 函數(shù)的本質(zhì)
    寄存器:64位:x0-x30,XZR(零寄存器)
    32位:W0-W30,WZR(零寄存器)
    PC寄存器:用來確定CPU即將執(zhí)行的地址羹蚣;
    改變PC寄存器:使用bl跳轉(zhuǎn)值指令

    • 棧:是一種具有特殊的訪問方式的存儲(chǔ)空間(后進(jìn)先出)
      sp寄存器在任一時(shí)刻都會(huì)保存棧頂?shù)牡刂罚?br> 只要調(diào)用函數(shù)就會(huì)開辟椩剑空間;系統(tǒng)通過操作SP寄存器顽素,SP往高地址走時(shí)都屬于棧區(qū)域咽弦,SP往低地址走時(shí)這塊區(qū)域是沒有用的。

    • 對(duì)內(nèi)存的操作就是讀和寫胁出,

    • ldr 把內(nèi)存數(shù)據(jù)讀到寄存器型型,str把寄存器寫到內(nèi)存;

    • 函數(shù)調(diào)用完畢全蝶,要做棧平衡闹蒜。

    • fp寄存器也稱為x29寄存器屬于通用寄存器,在某一時(shí)刻我們可以利用它保存棧底地址抑淫。

    • bl和ret指令
      bl標(biāo)號(hào):

      • 將下一條指令的地址放到lr(x30)寄存器绷落;
      • 轉(zhuǎn)到標(biāo)號(hào)處執(zhí)行。

      ret指令:

      • 默認(rèn)使用x30中的值始苇,x30放的是回去的路砌烁。

解讀一下:
stp x29, x30, [sp, #-0x10]!

  • 將x29,x30放到sp減去0x10的位置并且sp減去0x10

什么條件才能這樣寫催式?

  • 椇恚空間只需要保護(hù)29和30,沒有額外的椥钛酰空間函似;也就是函數(shù)里面只是一個(gè)簡單的調(diào)用,沒有局部變量喉童。

ldr x30, [sp], #0x10

  • [sp]表示:把它當(dāng)作內(nèi)存地址撇寞,取出其中的值

函數(shù)的參數(shù)與返回值:
什么時(shí)候節(jié)約內(nèi)存:寫入到棧區(qū)顿天,寫入到內(nèi)存時(shí)。
寄存器不存在節(jié)約內(nèi)存蔑担。
寄存器里面有個(gè)運(yùn)算器

  • 參數(shù) x0-x7牌废,w0-w7
    補(bǔ)充:
    返回值 x0
    補(bǔ)充:
    sp棧頂
    x29棧底
    orr = mov

為什么參數(shù)最好8個(gè)?

  • 通過寄存器的訪問是最高效的

還原高級(jí)代碼
函數(shù)調(diào)用棧
eg:main函數(shù)參數(shù)入棧:保護(hù)現(xiàn)場啤握;
當(dāng)函數(shù)參數(shù)多的時(shí)候x0-x7放到棧區(qū)域進(jìn)行保護(hù)
先放參數(shù)鸟缕、再放局部變量

  • 棧里面存在野指針?
    eg1:用4個(gè)字節(jié)去訪問8字節(jié)的地址排抬;
    eg2:一個(gè)指針指向垃圾地址懂从。
    棧里面一般不存放真實(shí)的結(jié)構(gòu)體數(shù)據(jù)(不過在函數(shù)內(nèi)部也可能有純粹的結(jié)構(gòu)體,一般我們使用的第三方框架都是使用malloc開辟內(nèi)存區(qū)域蹲蒲,再去創(chuàng)建結(jié)構(gòu)體放到里面)番甩,一般存放簡單的引用型數(shù)據(jù)(指針)。

  • 什么時(shí)候29届搁、30需要保護(hù)缘薛?
    有嵌套調(diào)用的時(shí)候。

  • 什么時(shí)候用到更多的棧卡睦?
    當(dāng)有參數(shù)和局部變量的時(shí)候宴胧。

  • 狀態(tài)寄存器(又稱:標(biāo)記寄存器):當(dāng)前執(zhí)行方法的狀態(tài)
    32位寄存器的最高4位

    • N:記錄相關(guān)的指令執(zhí)行結(jié)束后,結(jié)果是否位負(fù)表锻,如果為負(fù)
    • N=1
    • Z:計(jì)算結(jié)果如果為0恕齐,Z=1
    • C:無符號(hào)加法進(jìn)位,C=1;無符號(hào)減法有借位C=0;
    • V:有符號(hào)溢出標(biāo)記浩嫌,有溢出V=1;
      正+正=負(fù) v=1
      負(fù)-負(fù)=正 v=1
  • if指令可以改變標(biāo)志寄存器
    add sub orr 會(huì)影響標(biāo)志寄存器

  • 內(nèi)存:

    • 代碼區(qū):存放代碼檐迟、可讀可寫
    • 棧區(qū):放參數(shù)、局部變量码耐、臨時(shí)數(shù)據(jù)
    • 堆區(qū):動(dòng)態(tài)申請
    • 常量區(qū):只讀

帶#就是立即數(shù)(數(shù)字)

解讀:adrp x0, 1

  • 1追迟、將pc寄存器的值低12位清0
  • 2、將1左移12位
  • 3骚腥、將整兩個(gè)值相加敦间,賦值給x0寄存器

方法編號(hào):是個(gè)字符串常量存放在MackO文件里面

虛擬內(nèi)存和物理內(nèi)存
虛擬內(nèi)存:
物理內(nèi)存:
adrp x0, #0x1
adrp里面要么是全局變量要么是局部變量要么就是一個(gè)對(duì)象的屬性。

image.png

  • 全局變量和常量

    • 一般內(nèi)存中獲取全局變量和常量時(shí)束铭,出現(xiàn)adrp和add兩條指令獲得一個(gè)地址的情況廓块。
    • ADRP(Address Page)
      • adrp x0, 1

        • 將1的值,左移12位契沫!16進(jìn)制就是0x1000
        • 將當(dāng)前PC寄存器低12位清0
        • 將以上兩個(gè)結(jié)果相加带猴,存放到x0寄存器
      • 通過ADD指令,獲取這頁內(nèi)存中的偏移懈万。-
        image.png
      • image.png

        使用hopper還原高級(jí)代碼:

    • 一句一句還原成高級(jí)代碼拴清。
      先看main函數(shù)在bl調(diào)用func時(shí)有木有把參數(shù)傳進(jìn)去靶病,有說明有參數(shù)。再看func函數(shù)體內(nèi)有木有對(duì)x0做操作口予,一般情況下如果有說明有返回值(可能會(huì)在棧里面)但是不能確定返回值類型娄周,可以確定方法編號(hào),從中確定返回值類型沪停。
    • 由下到上簡化
  • CMP比較指令:把一個(gè)寄存器的內(nèi)容和另一個(gè)寄存器的內(nèi)容或立即數(shù)進(jìn)行比較煤辨,但不存儲(chǔ)結(jié)果,只是正確的更改標(biāo)志寄存器木张,底層做的是減法運(yùn)算众辨。

    • B.LE標(biāo)號(hào): 標(biāo)記結(jié)果是小于等于,執(zhí)行標(biāo)號(hào)舷礼,否則不跳轉(zhuǎn)
    • B.LT標(biāo)號(hào): 標(biāo)記結(jié)果是小于泻轰,執(zhí)行標(biāo)號(hào),否則不跳轉(zhuǎn)
    • B.GE標(biāo)號(hào): 標(biāo)記結(jié)果是大于等于且轨,執(zhí)行標(biāo)號(hào),否則不跳轉(zhuǎn)
    • B.GT標(biāo)號(hào): 標(biāo)記結(jié)果是大于虚婿,執(zhí)行標(biāo)號(hào)旋奢,否則不跳轉(zhuǎn)
    • B.EQ標(biāo)號(hào): 標(biāo)記結(jié)果是等于,執(zhí)行標(biāo)號(hào)然痊,否則不跳轉(zhuǎn)
    • B.NQ標(biāo)號(hào): 標(biāo)記結(jié)果是不等于至朗,執(zhí)行標(biāo)號(hào),否則不跳轉(zhuǎn)
    • B.HI標(biāo)號(hào): 標(biāo)記結(jié)果是無符號(hào)大于剧浸,執(zhí)行標(biāo)號(hào)锹引,否則不跳轉(zhuǎn)
    • 稍后補(bǔ)充....
  •  adrp x30, #0x100008000
     add x30, x30, #0xcf0
     還原成高級(jí)代碼為:int *x30 = &g;
    
  • 循環(huán)&選擇

    • cmp和subs區(qū)別?cmp不會(huì)保存結(jié)果唆香,subs會(huì)保存結(jié)果嫌变。
    • do while判斷條件在后面,滿足條件往前跳
    • while和for很像躬它,判斷條件在前面腾啥,滿足條件往前跳
  • switch

    • 分之少于3個(gè)沒有意義和if else很像
    • 各個(gè)分支常量差值比較大時(shí),編譯器會(huì)在內(nèi)存和效率之間取舍
    • 分支較多時(shí)冯吓,編譯器會(huì)生成一個(gè)表倘待,進(jìn)行跳轉(zhuǎn)
  • 代碼優(yōu)化

    • 非本文件的函數(shù)或代碼編譯器不會(huì)優(yōu)化
  • 指針

    • 指針可以做簡單的運(yùn)算。如:自增/自減
  • block反匯編:最主要的是找到invoke(實(shí)現(xiàn)地址)组贺、signature(類型)凸舵,進(jìn)而重寫block,hook別人的block失尖。

    • 先看一下block源碼
      #define BLOCK_DESCRIPTOR_1 1
      struct Block_descriptor_1 {
      uintptr_t reserved;
      uintptr_t size;
      };
    
      #define BLOCK_DESCRIPTOR_2 1
      struct Block_descriptor_2 {
      // requires BLOCK_HAS_COPY_DISPOSE
      BlockCopyFunction copy;
      BlockDisposeFunction dispose;
      };
      struct Block_descriptor_3 {
        // requires BLOCK_HAS_SIGNATURE
        const char *signature;
        const char *layout;   // contents depend on 
         BLOCK_HAS_EXTENDED_LAYOUT
        };
       struct Block_layout {
        void *isa;
        volatile int32_t flags; // contains ref count
        int32_t reserved;
        BlockInvokeFunction invoke;//實(shí)現(xiàn)地址!
        struct Block_descriptor_1 *descriptor;
       // imported variables
       };
    
    • 尋找invoke和signature
      實(shí)例一: 高級(jí)代碼如下:
     int main(int argc, char * argv[]) {
         void (^block)(void) = ^(){
             NSLog(@"nslog");
          };
          block();
          return 0;
      }
    

    匯編代碼如下:

     0x1000ba2a0 <+12>: adrp   x8, 2
     0x1000ba2a4 <+16>: add    x8, x8, #0x70             ; =0x70 
     0x1000ba2a8 <+20>: stur   wzr, [x29, #-0x4]
     0x1000ba2ac <+24>: stur   w0, [x29, #-0x8]
     0x1000ba2b0 <+28>: str    x1, [sp, #0x10]
     ->  0x1000ba2b4 <+32>: mov    x0, x8
     0x1000ba2b8 <+36>: bl     0x1000ba5fc               ; symbol 
    stub for: objc_retainBlock
     0x1000ba2bc <+40>: str    x0, [sp, #0x8]
     0x1000ba2c0 <+44>: ldr    x8, [sp, #0x8]
     0x1000ba2c4 <+48>: mov    x0, x8
     0x1000ba2c8 <+52>: ldr    x8, [x8, #0x10]
     0x1000ba2cc <+56>: blr    x8
    
    (lldb) x 0x1000bc070 
    0x1000bc070: 18 86 f9 9f 01 00 00 00 00 00 00 50 00 00 
    00 00  ...........P....
    0x1000bc080: f8 a2 0b 00 01 00 00 00 50 c0 0b 00 01 00 
    00 00  ........P.......
    
    (lldb) dis -s 0x01000ba2f8
    反匯編`__main_block_invoke:
    0x1000ba2f8 <+0>:  sub    sp, sp, #0x20             ; =0x20 
    0x1000ba2fc <+4>:  stp    x29, x30, [sp, #0x10]
    0x1000ba300 <+8>:  add    x29, sp, #0x10            ; =0x10 
    0x1000ba304 <+12>: str    x0, [sp, #0x8]
    0x1000ba308 <+16>: str    x0, [sp]
    0x1000ba30c <+20>: adrp   x0, 2
    0x1000ba310 <+24>: add    x0, x0, #0xb0             ; =0xb0 
    0x1000ba314 <+28>: bl     0x1000ba5a8               ; symbol stub for: NSLog
    

    實(shí)例二: 高級(jí)代碼如下:

     int main(int argc, char * argv[]) {
         int a = 10;
         void (^block)(void) = ^(){
            NSLog(@"nslog--%d", a);
         };
         block();
         return 0;
    }
    

    匯編代碼如下:

      0x10004a24c <+12>:  adrp   x8, 2
      0x10004a250 <+16>:  add    x8, x8, #0x58             ; =0x58 
      0x100082254 <+20>:  adrp   x9, 0
      0x100082258 <+24>:  add    x9, x9, #0x2e0            ; 
      =0x2e0 
    
    (lldb) x 0x100084058
     0x100084058: 00 00 00 00 00 00 00 00 24 00 00 00 00 00 
     00 00  ........$.......
     0x100084068: 8c 3f 08 00 01 00 00 00 fb 33 08 00 01 00 
     00 00  .?.......3......
    
    (lldb) x 0x1000822e0
     0x10004a2e0: ff c3 00 d1 fd 7b 02 a9 fd 83 00 91 a0 83 1f 
     f8  .....{..........
     0x10004a2f0: e8 03 00 aa e8 0b 00 f9 09 20 40 b9 e0 03 
     09 aa  ......... @.....
    
     (lldb) p (char *)0x0100083f8c
     (char *) $1 = 0x0000000100083f8c "v8@?0"
    
     dis -s 0x1000822e0
     反匯編`__main_block_invoke:
     0x1000822e0 <+0>:  sub    sp, sp, #0x30             ; =0x30 
     0x1000822e4 <+4>:  stp    x29, x30, [sp, #0x20]
     0x1000822e8 <+8>:  add    x29, sp, #0x20            ; =0x20 
     0x1000822ec <+12>: stur   x0, [x29, #-0x8]
     0x1000822f0 <+16>: mov    x8, x0
     0x1000822f4 <+20>: str    x8, [sp, #0x10]
     0x1000822f8 <+24>: ldr    w9, [x0, #0x20]
     0x1000822fc <+28>: mov    x0, x9
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末啊奄,一起剝皮案震驚了整個(gè)濱河市渐苏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌增热,老刑警劉巖整以,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異峻仇,居然都是意外死亡公黑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門摄咆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凡蚜,“玉大人,你說我怎么就攤上這事吭从〕” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵涩金,是天一觀的道長谱醇。 經(jīng)常有香客問我,道長步做,這世上最難降的妖魔是什么副渴? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮全度,結(jié)果婚禮上煮剧,老公的妹妹穿的比我還像新娘。我一直安慰自己将鸵,他們只是感情好勉盅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著顶掉,像睡著了一般草娜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上一喘,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天驱还,我揣著相機(jī)與錄音,去河邊找鬼凸克。 笑死议蟆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的萎战。 我是一名探鬼主播咐容,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蚂维!你這毒婦竟也來了戳粒?” 一聲冷哼從身側(cè)響起路狮,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蔚约,沒想到半個(gè)月后奄妨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苹祟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年砸抛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片树枫。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡直焙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砂轻,到底是詐尸還是另有隱情奔誓,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布搔涝,位于F島的核電站厨喂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏庄呈。R本人自食惡果不足惜杯聚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望抒痒。 院中可真熱鬧,春花似錦颁褂、人聲如沸故响。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彩届。三九已至,卻和暖如春誓酒,著一層夾襖步出監(jiān)牢的瞬間樟蠕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工靠柑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留寨辩,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓歼冰,卻偏偏與公主長得像靡狞,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子隔嫡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355