天天看點

Android 圖解逆向工程中ARM常用彙編指令(一)

我們走得太快,靈魂都跟不上了。 微小的幸福就在身邊,容易滿足就是天堂。
Android 圖解逆向工程中ARM常用彙編指令(一)

這個view裡面有 PUSH/LDR/SUB/MOVS/BLX/SUBS/BEQ/CMP ,這些差不多都是常見的,不過也不需要看得懂,了解這個指令即可,接下來我們就來分析下這些指令分别有什麼作用吧。

先引入 概念性 東西,免得大家後面被搞混,那就是為什麼會有S和!。

S:指令執行後程式狀态寄存器的條件标志位将被重新整理 , 如ADDS R1,R0,#2

! :指令中的位址表達式中含有!字尾時,指令執行後,基址寄存器中的位址值将發生變化,變化的結果是:基址寄存器中的值(指令執行後)=指令執行前的值 + 位址偏移量,如 LDR R3,[R0,#2]! 指令執行後,R0 = R0 + 2

接下來分别講解這個View裡面的指令分别有什麼作用。

PUSH,顧名思義,直接PUSH進棧了。相反的,POP則為出棧了。

 指令示例:

PUSH{cond} reglist PUSH将寄存器推入滿遞減堆棧

PUSH {r0,r4-r7} 将R0,R4-R7寄存器内容壓入堆棧

POP{cond} reglist POP從滿遞減堆棧中彈出資料到寄存器

POP {r0,r4-r7} 将R0,R4-R7寄存器從堆棧中彈出

LDR,指令文法:LDR{條件} 目的寄存器,<存儲器位址>,LDR指令用于從存儲器中将一個32位的字資料傳送到目的寄存器中。該指令通常用于從存儲器中讀取32位的字資料到通用寄存器,然後對資料進行處理,當程式計數器PC作為 目的寄存器時,指令從存儲器中讀取的字資料被當作目的位址,進而可以實作程式流程的跳轉。該指令在程式設計 中比較常用,且尋址方式靈活多樣。

LDR R0,[R1] ;将存儲器位址為R1的字資料讀入寄存器R0。

LDR R0,[R1,R2] ;将存儲器位址為R1+R2的字資料讀入寄存器R0。

MOVS 、LDR 這些是跳轉指令,直接向程式計數器PC寫入跳轉位址值,通過向程式計數器PC寫入跳轉位址值,可以實作在4GB的位址空間中的任意跳轉,那有人會問,如果說從目前指令向前或向後的32MB的位址空間的跳轉是怎麼個實作原理?其實在 上篇文章中提及到了,它們是B\BL\BLX\BX 四大指令,這個我們最後才來講解,其實它們有點像我們常說的分支結構,我們從圖檔裡面選第四條指令作為檢視資料。

Android 圖解逆向工程中ARM常用彙編指令(一)

則可以看到,R5是原位址,其實為0xFF8->0x104A,複制傳回位址到PC,實作子的傳回,做安卓的同學可能會有個疑問,為什麼有個S,因為文法就是 MOV{條件}{S} 目的寄存器+源操作數。

看到這裡大家可能會頭暈,怎麼感覺都是看不懂的數字,那其它那些,如ADD、等就給大家整理了一份表格。

助記符

指令功能描述

ADD

加法指令

MRS

傳送CPSR或SPSR的内容到通用寄存器指令

ADC

帶進位加法指令

MRC

從協處理器寄存器到ARM寄存器的資料傳輸指令

AND

邏輯與指令

MSR

傳送通用寄存器到CPSR或SPSR的指令

B

分支指令

MUL

32位乘法指令

BL

帶傳回的分支指令

BIC

位清零指令

BLX

帶傳回和狀态切換的分支指令

MLA

32位乘加指令

BX

帶狀态切換的分支指令

MVN

資料取反傳送指令

TST

位測試指令

ORR

邏輯或指令

CDP

協處理器資料操作指令

RSC

帶錯位的逆向減法指令

RSB

逆向減法指令

SBC

帶錯位減法指令

CMN

比較反值指令

CMP

比較指令

STC

協處理器寄存器寫入存儲器指令

EOR

異或指令

STM

批量記憶體字寫入指令

LDC

存儲器到協處理器的資料傳輸指令

STR

寄存器到存儲器的資料存儲指令

LDM

加載多個寄存器指令

SUB

減法指令

LDR

存儲器到寄存器的資料加載指令

SWI

軟體中斷指令

MCR

從ARM寄存器到協處理器寄存器的資料傳輸指令

TEQ

相等測試指令

MOV

資料傳送指令

SUBS 從表中可以看到,SUB是減法指令,如SUB R0,R1,R2則對應了R0 = R1 - R2,SUB R0,R1,#1 則是R0 = R1 -1,要注意的是 SUBS 是低32位相減。

那 BEQ 呢?!不要着急,來看下圖

Android 圖解逆向工程中ARM常用彙編指令(一)

BEQ 指令是跳轉指令,但是跳轉要滿足一定的條件,滿足則跳轉執行,看下圖紅框部分。

Android 圖解逆向工程中ARM常用彙編指令(一)

那就隻剩下 CMP 了,CMP是比較指令,指令格式:CMP{條件} 操作數1,操作數2。

如 CMP R1,#10,則等于比較R1和10,并設定CPSR的标志位。

CMP R1,R0 ;将寄存器R1的值與寄存器R0的值相減,并根據 結果設定CPSR的标志位

CMP R1,#100 ;将寄存器R1的值與立即數100相減,并根 據結果設定CPSR的标志位

如果和BEQ一起使用話則是:CMP R1,#0 換行 BEQ Label ;當CPSR寄存器中的Z條件碼置位時,程式跳轉到标号Label處執行

OK , 從第一張圖中我們看到後面跟的是兩位,那如果是複雜一點的兩位以上怎麼看?

先來看MOV的,如MOV R0,R1 , LSL R3 ,這個又是何解?其實它是将R1的值左移R3位,然後将結果存放到R0中 。

再來看LDR的,LDR R0,[R1],R2 ,這個何解? 它是将存儲器位址為R1的字資料讀入寄存器R0,并将新位址R1+R2寫入R1 , 要記住,R1是最終落地的位址 。

繼續閱讀