我們走得太快,靈魂都跟不上了。
微小的幸福就在身邊,容易滿足就是天堂。
在逆向和爆破中我們經常會在IDA中接觸到彙編,一般做安卓的不會太了解VB回編等,不太了解的同學可以先檢視上篇文章
《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作為 目的寄存器時,指令從存儲器中讀取的字資料被當作目的位址,進而可以實作程式流程的跳轉。該指令在程式設計 中比較常用,且尋址方式靈活多樣。
詳情可見上篇文章中 Ctrl + F 搜尋《Android ARM常用的彙編指令合集》:加載/存儲指令
指令示例:
-
- LDR R0,[R1] ;将存儲器位址為R1的字資料讀入寄存器R0。
- LDR R0,[R1,R2] ;将存儲器位址為R1+R2的字資料讀入寄存器R0。
MOVS 、LDR 這些是跳轉指令,直接向程式計數器PC寫入跳轉位址值,通過向程式計數器PC寫入跳轉位址值,可以實作在4GB的位址空間中的任意跳轉,那有人會問,如果說從目前指令向前或向後的32MB的位址空間的跳轉是怎麼個實作原理?其實在 上篇文章中提及到了,它們是B\BL\BLX\BX 四大指令,這個我們最後才來講解,其實它們有點像我們常說的分支結構,我們從圖檔裡面選第四條指令作為檢視資料。
則可以看到,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 呢?!不要着急,來看下圖
BEQ 指令是跳轉指令,但是跳轉要滿足一定的條件,滿足則跳轉執行,看下圖紅框部分。
那就隻剩下 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是最終落地的位址 。
上篇文章中提及了其它更複雜的指令示例,不太明白這些可以看上篇文章的《Android ARM常用的彙編指令合集》,然後Ctrl + F 搜:資料加載/存儲指令 或者搜尋 資料處理指令,又或者搜尋 自己需要的指令。
作者:奧特曼超人Dujinyang
版權聲明:本文為部落客杜錦陽原創文章,轉載請附上博文連結!