ARM匯編基礎(chǔ)(iOS逆向)

ARM匯編基礎(chǔ)

在逆向一個(gè)功能的時(shí)候,往往需要分析大量的匯編代碼,在iOS逆向中,ARM匯編是必須掌握的語(yǔ)言,本文總結(jié)了ARM匯編的基礎(chǔ)知識(shí),如果你想了解更多,請(qǐng)參考狗神的小黃書(shū)《iOS逆向逆向工程》或ARM官方手冊(cè).

寄存器,內(nèi)存和棧

在ARM匯編里,操作對(duì)象是寄存器,內(nèi)存和棧
ARM的棧遵循先進(jìn)后出,是滿遞減的,向下增長(zhǎng),也就是開(kāi)口向下,新的變量被存到棧底的位置;越靠近棧底,內(nèi)存地址越小
一個(gè)名為stackPointer的寄存器保存棧的棧底地址,成為棧地址.
可以把一個(gè)變量給入棧(push)以保存它的值,也可以讓它出棧(pop),恢復(fù)變量的原始值.在實(shí)際操作中,棧地址會(huì)不斷變化;但是在執(zhí)行一塊代碼的前后,棧地址應(yīng)該是不變的,不然程序就要出問(wèn)題,

特殊用途的寄存器

ARM處理器中的部分寄存器有特殊用途 如下所示:

寄存器 用途
R0-R3 傳遞參數(shù)與返回值
R7 幀指針,指向母函數(shù)與被調(diào)用子函數(shù)在棧中的交界
R9 在iOS3.0以前被系統(tǒng)保留
R12 內(nèi)部過(guò)程調(diào)用存儲(chǔ)器,dynamic linker會(huì)用到它
R13 sp寄存器
R14 LR寄存器,保存函數(shù)返回地址
R15 PC寄存器

分支跳轉(zhuǎn)與條件判斷

處理器名為”P(pán)rogram counter”(簡(jiǎn)稱PC)的寄存器用于存放下一條指令的地址.一般情況下,計(jì)算機(jī)一條接一條地順序執(zhí)行指令,處理器執(zhí)行完一條指令后將PC加1,讓它指向下一條指令.例如處理器順序執(zhí)行指令1到指令5,但是如果把PC的值變一變,指令執(zhí)行的順序就完全不同指令執(zhí)行順序被打亂,變成了指令1,指令5,指令4,指令2,指令3,指令6,這種亂序的學(xué)名叫做”分支”,或者”跳轉(zhuǎn)”,它使循環(huán)和subroutime(子程序)成為可能,例如:

// endless() 函數(shù)

在實(shí)際情況中,滿足一定條件才得以觸發(fā)的分支是最實(shí)用的,這種分支成為條件分支.if else 和 while都是基于條件分支實(shí)現(xiàn)的,在ARM匯編中,分支的條件一般有4種:

  • □ 操作結(jié)果為0(或不為0);

  • □ 操作結(jié)果為負(fù)數(shù);

  • □ 操作結(jié)果有進(jìn)位;

  • □ 運(yùn)算溢出(比如兩個(gè)正數(shù)相加得到的數(shù)超過(guò)了寄存器位數(shù)).

這些條件的判斷準(zhǔn)則(flag)存放在程序狀態(tài)寄存器(Program Status Register,PSR)中,數(shù)據(jù)處理相關(guān)指令會(huì)改變這些flag,分支指令再根據(jù)這些flag決定是否跳轉(zhuǎn).下面的偽代碼展示了一個(gè)for循環(huán)

for:

ARM/THUMB指令解讀

ARM處理器用到的指令集分為ARM和THUMB兩種:ARM指令長(zhǎng)度均為32bit,THUMB指令長(zhǎng)度為16bit.所有指令可大致分為三類,分別為,數(shù)組操作指令,內(nèi)存操作指令和分支指令.

數(shù)據(jù)操作指令

數(shù)據(jù)操作指令有以下2條規(guī)則:

  • 所有的操作數(shù)均為32bit;
  • 所有的結(jié)果均為32bit,且只能存放在寄存器當(dāng)中.
    總的來(lái)說(shuō),數(shù)據(jù)操作指令的基本格式是:
op{cond}{s} Rd,Rn,Op2

其中,”cond”和”s”是另個(gè)可選后綴;”cond”的作用是指定指令”op”在什么條件下執(zhí)行,共有17中條件:

指令 條件
EQ 結(jié)果為0(EQual to 0)
NE 結(jié)果不為0(Not Equal to 0)
CS 有進(jìn)位或借位(Carry Set)
HS 同CS(unsigned Higer or Same)
CC 沒(méi)有進(jìn)位或借位(Carry Clear)
LO 同CC(unsigned LOwer)
MI 結(jié)果小于0(MInus)
PL 結(jié)果大于等于0(PLus)
VS 溢出(Overflow Set)
VC 無(wú)溢出(Overflow Clear)
HI 無(wú)符號(hào)比較大于(unsigned HIger)
LS 無(wú)符號(hào)比較小于等于(unsigned Lower or Same)
GE 有符號(hào)比較大于等于(signed Greater than or Equal)
LT 有符號(hào)比較小于(signed Less Than)
GT 有符號(hào)比較大于(signed Greater Than)
LE 有符號(hào)比較小于等于(signed Less than or Equal)
AL 無(wú)條件(Always,默認(rèn))

“cond”的用法很簡(jiǎn)單,例如:

比較 R0, R1

比較R0和R1的值,如果R0大于等于R1,則R2 = R0;否則R2 = R1.
“s”的作用是指定指令”op”是否設(shè)置了flag,共有下面4種flag:

  • N(Negative)如果結(jié)果小于0則置1,否則置0;

  • Z(zero)如果結(jié)果是0則置1,否則置0;

  • C(Carry)對(duì)于加操作(包括CMN)來(lái)說(shuō),如果產(chǎn)生進(jìn)位則置1,否則置0;對(duì)于減操作(包括CMP來(lái)說(shuō)),Carry相當(dāng)于Not-Borrow,如果產(chǎn)生借位則置0,否則置1;對(duì)于有移位的非加/減操作來(lái)說(shuō),C置移出值得最后一位;對(duì)于其他的非加/減操作來(lái)說(shuō),C的值一般不變;

  • V(overflow)如果操作導(dǎo)致溢出,則置1,否則置0

需要注意一點(diǎn)的是,C flag表示無(wú)符號(hào)數(shù)運(yùn)算結(jié)果是否溢出;V flag表示有符號(hào)數(shù)運(yùn)算結(jié)果是否溢出.

算數(shù)操作指令可以大致分為4類:

算數(shù)操作

ADD R0,R1,R2; ——————> R0 = R1 + R2ADC R0,R1,R2; ——————> R0 = R1 + R2 + C(array)SUB R0,R1,R2; ——————> R0 = R1 - R2SBC R0,R1,R2; ——————> R0 = R1 - R2 - !CRSB R0,R1,R2; ——————> R0 = R2 - R1RSC R0,R1,R2; ——————> R0 = R2 - R1 - !C算數(shù)操作中,ADD和SUB為基礎(chǔ)操作,其他均為兩者的變種.RSB是”Reverse Sub”的縮寫(xiě),僅僅是把SUB的兩個(gè)操作數(shù)調(diào)換了位置而已;以”C”結(jié)尾的變種代表沒(méi)有進(jìn)位和借位的加減法,當(dāng)產(chǎn)生進(jìn)位或者借位時(shí),將Carrry flag 置為1.

邏輯操作

AND R0,R1,R2; ——————> R0 = R1 & R2ORR R0,R1,R2; ——————> R0 = R1 | R2EOR R0,R1,R2; ——————> R0 = R1 ^ R2BIC R0,R1,R2; ——————> R0 = R1 &~ R2MOV RO,R2; ——————> R0 = R2MVN R0,R2; ——————> R0 = ~R2邏輯操作指令都已經(jīng)用C操作符說(shuō)明了作用,但是C操作符里的移位操作并沒(méi)有對(duì)位的邏輯操作指令,ARM采用了桶式移位,共有四種指令:LSL 邏輯左移 LSR 邏輯右移 ASR 算術(shù)右移ROR 循環(huán)右移

比較操作

CMP R1,R2; ——————> 執(zhí)行R1 - R2并依結(jié)果設(shè)置flag

CMN R1,R2; ——————> 執(zhí)行R1 + R2并依結(jié)果設(shè)置flagTST R1,R2; ——————> 執(zhí)行R1 & R2并依結(jié)果設(shè)置flagTEQ R1,R2; ——————> 執(zhí)行R1 ^ R2并依結(jié)果設(shè)置flag比較操作其實(shí)就是改變flag的算術(shù)操作或邏輯操作,只是操作結(jié)果不保留在寄存器里而已.

乘法操作

MUL R4,R3,R2 ——————> R4 = R3 * R2MLA R4,R3,R2,R1 ——————> R4 = R3 * R2 + R1乘法操作的操作數(shù)必須來(lái)自寄存器

內(nèi)存操作指令

內(nèi)存操作指令的基本格式是:

op{cond}{type} Rd,[Rn,Op2]

其中Rn是基址寄存器,用于存放基地址;”cond”的作用與數(shù)據(jù)操作指令相同;”type”指定指令”op”操作的數(shù)據(jù)類型,共有四種:

B(unsigned Byte)

如果不指定”type”,則默認(rèn)是word
ARM內(nèi)存操作基礎(chǔ)指令只有2個(gè),LDR(loaD Register)將數(shù)據(jù)從內(nèi)存中讀出來(lái),存到寄存器中;STR(STore Register)將數(shù)組從寄存中讀出來(lái),存到內(nèi)存中.兩個(gè)指令的使用情況如下:

LDR

LDR Rt,[Rn {,#offset}]          ;   Rt = *(Rn {+ offset}),{}代表可選

STR

STR Rt,[Rn {,#offset}]          ;   *(Rn {+ offset}) = Rt

此外,LDR和STR的變種LDRD和STRD還可以操作雙字(DoubleWord),即一次性操作兩個(gè)寄存器,其基本格式如下:

op{cond} Rt,Rt2, [Rn {, #offset}]

其用法與原型類似,如下:

STRD

SRTD R4,R5, [R9,#offset]    ; *(R9 + offset) = R4;*(R9 + offset + 4) = R5

LDRD

LDRD R4,R5,[R9,#offset]     ; R4 = *(R9 + offset); R5 = *(R9+offset+4)

除LDR和STR外,還可以通過(guò)LDM(LoaD Multiple)和STM(STore Multipe)進(jìn)行塊傳輸,一次性操作多個(gè)寄存器.塊傳輸指令的基本格式是

op{cond}{}mode] Rd{!},reglist

其中Rd是基址寄存器,可選的”!”制定Rd變化后的值是否寫(xiě)會(huì)Rd, reglist是一系列寄存器,用大括號(hào)括起來(lái),它們之間可以用”,”分割,也可以用”-“表示一個(gè)范圍,比如,{R4-R6,R8}表示寄存器,R4,R5,R6,R8;這些寄存器的順序是按照自身的編號(hào)由小到大排列的,與大括號(hào)內(nèi)的排列順序無(wú)關(guān).需要特別注意的是,LDM和STM的操作方向與LDR和STR完全相反:LDM是把從Rd開(kāi)始,地址連續(xù)的內(nèi)存數(shù)據(jù)存入reglist中,STM是把reglist中的值存入從Rd開(kāi)始,地址連續(xù)的內(nèi)存中.此處特別容易混淆“cond” 的作用與數(shù)據(jù)操作指令相同.”mode”指定R4值得變化的4中規(guī)律,如下所示:

IA(Increament After)每次傳輸后增加Rd的值;

這是什么意思呢?下面以LDM為代表,舉一個(gè)簡(jiǎn)單的例子,相信大家一看就明白了.

在執(zhí)行以下命令后,R4,R5,R6的值分別變成:

foo():

STM指令的作用方式與此類似,不再贅述.LDM和STM的操作與LDR和STR完全相反

分支指令

分支指令可以分為無(wú)條件分支和條件分支兩種.

無(wú)條件分支

B Label;PC = Label

無(wú)條件分支

跳轉(zhuǎn)分支的cond是依照前面的flag來(lái)判斷的,它們的對(duì)應(yīng)關(guān)系如下:

cond flag
EQ Z = 1
NE Z = 0
CS C = 1
HS C = 1
CC C = 0
LO C = 0
MI N = 1
PL N = 0
VS V = 1
VC V = 0
HI C = 1 & Z = 0
LS C = 0
GE N = V
LT N != V
GT Z = 0 & N = V
LE Z = 1

在條件分支指令錢會(huì)有一條數(shù)據(jù)操作指令來(lái)設(shè)置flag,分支指令根據(jù)falg的值來(lái)決定代碼走向,舉例如下:

Label:

THUMB指令

THUMB指令集是ARM指令集的一個(gè)子集,每條THUMB指令均為16bit;因此THUMB指令比ARM指令更節(jié)省空間,且在16位數(shù)據(jù)總線上的傳輸效率更高.有得必有失,除了”b”之外,所有的THUMB指令均無(wú)法條件執(zhí)行;桶式移位無(wú)法結(jié)合其他指令執(zhí)行;大多數(shù)THUMB指令只能使用R0-R7這8個(gè)寄存器等.相對(duì)于ARM指令,THUMB指令的特點(diǎn)如下:

  • 指令數(shù)量減少

  • 沒(méi)有條件執(zhí)行

  • 所有指令默認(rèn)附帶*

  • 桶式移位無(wú)法結(jié)合其他指令執(zhí)行

  • 寄存器使用受限

  • 立即數(shù)和第二操作數(shù)使用有限

  • 不支持?jǐn)?shù)據(jù)寫(xiě)回

查看原文:GitHub

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乐疆,一起剝皮案震驚了整個(gè)濱河市涛浙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沮尿,老刑警劉巖摸吠,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件空凸,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡寸痢,警方通過(guò)查閱死者的電腦和手機(jī)呀洲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人道逗,你說(shuō)我怎么就攤上這事兵罢。” “怎么了滓窍?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵卖词,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我吏夯,道長(zhǎng)此蜈,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任噪生,我火速辦了婚禮舶替,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘杠园。我一直安慰自己,他們只是感情好舔庶,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布抛蚁。 她就那樣靜靜地躺著,像睡著了一般惕橙。 火紅的嫁衣襯著肌膚如雪瞧甩。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天弥鹦,我揣著相機(jī)與錄音肚逸,去河邊找鬼。 笑死彬坏,一個(gè)胖子當(dāng)著我的面吹牛朦促,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播栓始,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼务冕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了幻赚?” 一聲冷哼從身側(cè)響起禀忆,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎落恼,沒(méi)想到半個(gè)月后箩退,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡佳谦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年戴涝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡喊括,死狀恐怖胧瓜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情郑什,我是刑警寧澤府喳,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蘑拯,受9級(jí)特大地震影響钝满,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜申窘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一弯蚜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧剃法,春花似錦碎捺、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)叛复。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間岗钩,已是汗流浹背申眼。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工谬晕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宿亡,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓彪腔,卻偏偏與公主長(zhǎng)得像侥锦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子漫仆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

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