如何符號(hào)化Objective-C調(diào)用棧

本文講述的是符號(hào)化“殘破”的棧,如果你有一個(gè)系統(tǒng)生成的crash日志限府,請(qǐng)交給Xcode自帶的symbolicatecrash腳本。

Symbolicatecrash腳本的核心也是通過(guò)atos功能逐行符號(hào)化,但人家封裝好了时捌,比自己手動(dòng)一行一行做快很多掂之。

示例棧:

    0   XSQSymbolicateDemo                  0x00000001000ba530 XSQSymbolicateDemo + 25904
    1   XSQSymbolicateDemo                  0x00000001000ba4f0 XSQSymbolicateDemo + 25840
    2   XSQSymbolicateDemo                  0x00000001000ba4bc XSQSymbolicateDemo + 25788
    3   XSQSymbolicateDemo                  0x00000001000ba478 XSQSymbolicateDemo + 25720
    4   UIKit                               0x00000001966870ec <redacted> + 96
    5   UIKit                               0x000000019668706c <redacted> + 80
    6   UIKit                               0x00000001966715e0 <redacted> + 440
    7   UIKit                               0x0000000196686950 <redacted> + 576
    8   UIKit                               0x000000019668646c <redacted> + 2480
    9   UIKit                               0x0000000196681804 <redacted> + 3192
    10  UIKit                               0x0000000196652418 <redacted> + 340
    11  UIKit                               0x0000000196e4bf64 <redacted> + 2400

這是我寫(xiě)的一個(gè)demo app抗俄,并且在編譯后期濾去了符號(hào)表,所以僅能看到一些奇怪的地址世舰。

如何符號(hào)化第三方app內(nèi)的符號(hào)

以第一行:

0   XSQSymbolicateDemo                  0x00000001000ba530 XSQSymbolicateDemo + 25904

為例

需要條件:

(1)atos工具(Xcode安裝時(shí)一般會(huì)自帶)

(2)確認(rèn)app運(yùn)行的架構(gòu)(armv7动雹、arm64)

(3)app對(duì)應(yīng)的dSYM文件(出包時(shí)獲得)

(4)app代碼載入到內(nèi)存的基地址(后文詳細(xì)介紹)

方法:

在命令行中輸入:

xcrun atos -arch arm64 -o ./XSQSymbolicateDemo.app.dSYM/Contents/Resources/DWARF/XSQSymbolicateDemo  -l  0x1000b4000 0x00000001000ba530

即可得到符號(hào)化后的結(jié)果:

-[ViewController helloWorld2] (in XSQSymbolicateDemo) (ViewController.m:100)
如何符號(hào)化系統(tǒng)動(dòng)態(tài)庫(kù)中的符號(hào)

以這一行為例:

4   UIKit                               0x00000001966870ec <redacted> + 96

需要條件:

(1)atos工具(Xcode安裝時(shí)一般會(huì)自帶)

(2)確認(rèn)app運(yùn)行的架構(gòu)(armv7、arm64)

(2)該OS版本跟压、該動(dòng)態(tài)庫(kù)的符號(hào)文件(將該手機(jī)連接到電腦的Xcode上胰蝠,會(huì)自動(dòng)同步系統(tǒng)符號(hào)文件)

(3)該動(dòng)態(tài)庫(kù)載入到內(nèi)存的基地址(后文詳細(xì)介紹)

方法:

在命令行中輸入:

xcrun atos -arch arm64 -o ~/Library/Developer/Xcode/iOS\ DeviceSupport/10.3.1\ \(14E304\)/Symbols/System/Library/Frameworks/UIKit.framework/UIKit -l  0x196642000 0x00000001966870ec
-[UIApplication sendAction:to:from:forEvent:] (in UIKit) + 96

即可得到符號(hào)化后的結(jié)果:

-[UIApplication sendAction:to:from:forEvent:] (in UIKit) + 96
如何獲取基地址

注意:基地址在進(jìn)程每次啟動(dòng)時(shí)決定,所以重啟進(jìn)程后,符號(hào)化時(shí)必須使用當(dāng)次啟動(dòng)的基地址

方案一:從iOS生成的crash日志中獲取

在iOS系統(tǒng)生成的crash日志中的下半部分姊氓,有這樣的一些信息:

藍(lán)色框圈出來(lái)的部分丐怯,即為app代碼載入到內(nèi)存的基地址

紅色框圈出來(lái)的部分,即為各個(gè)動(dòng)態(tài)庫(kù)載入到內(nèi)存的基地址

方案二:在app運(yùn)行時(shí)打印

可以在app中調(diào)用如下代碼獲取各個(gè)image的基地址:

void printAllImage()
{
    for (int i = 0; i < _dyld_image_count(); i++) {
        char *image_name = (char *)_dyld_get_image_name(i);
        const struct mach_header *mh = _dyld_get_image_header(i);
        intptr_t vmaddr_slide = _dyld_get_image_vmaddr_slide(i);
        
        NSLog(@"Image name %s at address 0x%llx and ASLR slide 0x%lx.\n",
               image_name, (mach_vm_address_t)mh, vmaddr_slide);
    }
}

得到如下輸出:

Image name /var/containers/Bundle/Application/351121C8-CFE4-49AD-ACC0-A70C5BF1C4A6/XSQSymbolicateDemo.app/XSQSymbolicateDemo at address 0x1000b4000 and ASLR slide 0xb4000.
 Image name /System/Library/Frameworks/Foundation.framework/Foundation at address 0x190f0c000 and ASLR slide 0xeedc000.
 Image name /usr/lib/libarchive.2.dylib at address 0x190ee0000 and ASLR slide 0xeedc000.
 Image name /usr/lib/libbz2.1.0.dylib at address 0x190e9e000 and ASLR slide 0xeedc000.
 Image name /usr/lib/libSystem.B.dylib at address 0x18ef04000 and ASLR slide 0xeedc000.
 Image name /usr/lib/system/libcache.dylib at address 0x18f35a000 and ASLR slide 0xeedc000.
......

可以看到第一行代表的是app自身翔横,之后的每一行是app載入的動(dòng)態(tài)庫(kù)們读跷。

介紹加載和ASLR

大致理解:

在進(jìn)程啟動(dòng)的時(shí)候,內(nèi)核加載器或者dyld會(huì)將指令加載到內(nèi)存中禾唁。

ASLR全名Address Space Layout Randomization效览,地址空間布局隨機(jī)化,用于防范惡意程序?qū)σ阎刂愤M(jìn)行攻擊

在ASLR引入之前荡短,由于加載的規(guī)則是固定的丐枉,所以理論上,一個(gè)進(jìn)程不管重啟多少次掘托,每條指令對(duì)應(yīng)的內(nèi)存中的地址都是一樣的瘦锹。而每條指令對(duì)應(yīng)到內(nèi)存中的哪個(gè)地址,可以通過(guò)分析Mach-O文件分析出來(lái)闪盔。這就容易產(chǎn)生安全漏洞弯院。

ASLR引入后,在進(jìn)程啟動(dòng)前期的加載階段泪掀,會(huì)生成一個(gè)隨機(jī)數(shù)offset听绳,讓加載形成的內(nèi)存整體偏移一個(gè)offset。

這樣一個(gè)進(jìn)程多次啟動(dòng)异赫,每次行程的內(nèi)存空間布局都不完全一致椅挣。同一個(gè)指令,經(jīng)過(guò)多次啟動(dòng)塔拳,每次都會(huì)被布局到一個(gè)新計(jì)算出來(lái)的地址鼠证。

所以僅僅憑借“一個(gè)指令在內(nèi)存中的地址”和dSYM文件,是無(wú)法進(jìn)行符號(hào)化的蝙斜,因?yàn)檫@個(gè)“地址”同時(shí)依賴于ASLR生成的offset名惩。

我理解其實(shí)只需要一個(gè)offset,配合已知的架構(gòu)孕荠、加載方式等信息娩鹉,應(yīng)該就能推測(cè)出app自身的基地址和各個(gè)庫(kù)的基地址。嘗試后也證明稚伍,各個(gè)庫(kù)的基地址-offset后的值在同個(gè)設(shè)備的多次啟動(dòng)上是一致的弯予。
但是為了圖省事,還是自己打印一下所有庫(kù)的基地址吧(′?ω?`)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末个曙,一起剝皮案震驚了整個(gè)濱河市锈嫩,隨后出現(xiàn)的幾起案子受楼,更是在濱河造成了極大的恐慌,老刑警劉巖呼寸,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件艳汽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡对雪,警方通過(guò)查閱死者的電腦和手機(jī)河狐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)瑟捣,“玉大人馋艺,你說(shuō)我怎么就攤上這事÷跆祝” “怎么了捐祠?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)桑李。 經(jīng)常有香客問(wèn)我踱蛀,道長(zhǎng),這世上最難降的妖魔是什么贵白? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任星岗,我火速辦了婚禮,結(jié)果婚禮上戒洼,老公的妹妹穿的比我還像新娘。我一直安慰自己允华,他們只是感情好圈浇,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著靴寂,像睡著了一般磷蜀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上百炬,一...
    開(kāi)封第一講書(shū)人閱讀 52,255評(píng)論 1 308
  • 那天褐隆,我揣著相機(jī)與錄音,去河邊找鬼剖踊。 笑死庶弃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的德澈。 我是一名探鬼主播歇攻,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼梆造!你這毒婦竟也來(lái)了缴守?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屡穗,沒(méi)想到半個(gè)月后贴捡,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡村砂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年烂斋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片箍镜。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡源祈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出色迂,到底是詐尸還是另有隱情香缺,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布歇僧,位于F島的核電站图张,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏诈悍。R本人自食惡果不足惜祸轮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望侥钳。 院中可真熱鬧适袜,春花似錦、人聲如沸舷夺。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)给猾。三九已至疫萤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間敢伸,已是汗流浹背扯饶。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留池颈,地道東北人尾序。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像躯砰,于是被迫代替她去往敵國(guó)和親蹲诀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,283評(píng)論 25 707
  • 一弃揽、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡(jiǎn)單分配策略的問(wèn)題地址空間不隔離內(nèi)存使用效率低程序運(yùn)行的地址不確定 關(guān)于...
    SeanCST閱讀 7,818評(píng)論 0 27
  • 村上春樹(shù)堅(jiān)持每天跑步脯爪,近30年则北,出了一本書(shū),告訴大家他跑步的時(shí)候在想什么痕慢,我就不行尚揣。 從三月份到現(xiàn)在,斷斷續(xù)續(xù)的掖举。...
    月光海兒閱讀 563評(píng)論 0 1
  • 樓上的大叔開(kāi)門(mén)大喊快骗,誰(shuí)家的死孩子放的鞭炮,在外頭不放塔次,在樓道里放什么鞭炮方篮。我們聽(tīng)見(jiàn)不好趕緊撒腿就跑。一口氣我們跑到...
    陶醉海的湛藍(lán)閱讀 215評(píng)論 0 0
  • %%百分號(hào)標(biāo)記%c字符及其ASCII碼%s字符串%d有符號(hào)整數(shù)(十進(jìn)制)%u無(wú)符號(hào)整數(shù)(十進(jìn)制)%o無(wú)符號(hào)整數(shù)(八...
    Nothing_lu閱讀 585評(píng)論 0 1