汇编之堆栈别乱用
引言
在做開發中,可能根據某些特定功能的實現,需要嵌入一段shellcode的匯編代碼,當然,前提是你需要有一定的匯編基礎,在實際的逆向分析中,理解匯編的指令真的不是很難,無非就是讀寫、比較、計算數值,操作堆棧、操作寄存器的一系列的操作,如果遇見不會的指令上網查詢一下就一目了然了,但是當你真正的去實現一段匯編代碼的功能時,你可能會遇見一些讓你頭疼的坑,當然可能這個坑就是你自己挖的,沒辦法你挖的你就得負責填上。
異常問題環境相關描述
實現功能:自寫arm匯編指令調用dlopen函數;
問題手機:經測試vivo/oppo、CPU驍龍660、系統Android 8.1,需要同時符合這三點要求的都會中招;
定位問題點
最后鎖定到問題點在__dl__ZN12LinkerLogger10ResetStateEv函數中的VST1.8 {D16}, [R0@64]!指令,當執行該指令時會出發"SIGBUS"錯誤信號導致程序崩潰;
分析過程
首先看一下錯誤信號"SIGBUS"的含義,通過搜索得知,該錯誤表示**“未對其的訪問”** ,分析調試代碼,第一個想到的就是“dlopen”的第一個參數字符串文件路徑,該字符串不是4字節對齊,因此把修改字符串文件路徑進行對齊,但是錯誤繼續出現,與此同時在對函數的進一步跟蹤發現,出錯的__dl__ZN12LinkerLogger10ResetStateEv函數,根本未使用這個字符串文件路徑,所以可以肯定是問題點不在這里,失去了線索,一度陷入迷茫中…
帶著一份執著,我又調試運行了幾次,發現問題每次都出現在VST1.8 {D16}, [R0@64]這條指令上,這不是一條常用指令到底什么意思呢?帶著疑問去找到了答案,這是arm匯編里面的VFP浮點指令操作,該條指令的意思是把D16寄存器的值賦值到R0寄存器指向的地址中,(知識點介紹:VFP指令集操作的是高精度的浮點值,所以他的寄存器是按64位8字節方式操作的,即一個“QDWORD”值,關于VFP信息參考連接:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204ic/Bcfhdhgd.html )
從上圖我看一下D16寄存器的值的來源,指令為VMOV.I32 D16, #0,從指令中解析出D16寄存器的值等于“0x0000000000000000”,然后在來看一下R0寄存器值的來源,指令MOV R0, R4表示R0寄存器的值是R4寄存賦值過來的,而從指令 ADD R4, SP, #8中獲得R4指令是SP+8的地址,由此可見我們R0寄存器實際指向的地址是SP+8,
從圖中我們可以看出R0的地址為0xFFA1660C,那執行VST1.8 {D16}, [R0@64]指令實際上就是吧地址0xFFA1660C、0xFFA16610這兩個堆棧地址指向的值置0,分析到這一步,如果是聰明的人應該就知道問題點了,誰讓我笨呢!沒有看出來,好吧,既然沒看出來我沒就用笨的方法來吧,只要努力笨鳥也會先飛的,又思考了一下,決定寫個demo,正常掉一下對dlopen,在用IDA逆向跟蹤一下。
通過上面的圖看出當前R0寄存器的值為"0xFFA177E8",再仔細看一下出錯的時候R0寄存器的值“0xFFA1660C”,再仔細想一下錯誤提示“未對其的訪問“,在想一下VFP浮點指令集是64位操作數的特征,最后再結合一這個圖:
突然茅塞頓開了是吧!就是我們的R0寄存器指向的地址沒有對齊導致的“SIGBUS”錯誤,“0xFFA1660C”地址在64位的操作運算中就是非法的操作,之前我們知道R0的來源是堆棧地址,那接下來就看看我自己編寫的匯編代碼中操作堆棧的位置:
追溯起源,從圖中可知R0~R7一共是8個dword值,在加上一個LR,一共是9個dword值壓入堆棧,就是這里導致后面VST1.8 {D16}, [R0@64]指令執行出錯,帶著好信的心里,我特意看了一下其他正常函數的堆棧操作,都是按照8字節對齊的。于是乎各種感嘆,學藝不精啊!!!!!!~好了問題找到了,那就按8字節對齊的方式去操作堆棧,如圖:
由于R0~R3在這里主要的用途就是傳參寄存器,其自身就是可變的,所以不考慮這幾個寄存器,只把R4寄存器和LR寄存器進行了保存,最后生成項目,重新運行程序,程序沒有崩潰正常運行,到這里我們終于解決了問題,仿佛有些感動的淚水,畢竟在查找這個問題的時候所花的時間和經歷,對此刻來說都是值得的。
在前面我說過,只有在vivo/oppo、CPU是驍龍660、系統為Android 8.1的手機才會出現這樣的錯誤,因為在實際中我做過其他機型、其他CPU及其他系統版本的測試都沒有問題,個人認為可能是有viov/oppo廠商在定制該種配置手機的ROM的時候可能是添加/未添加某種處理機制產生的現象,當然我們不能說這是人家廠商的問題,我只能說是自己的粗心與馬虎給自己造成的問題,但能遇見這樣的問題也并不是一件壞的事情,塞翁失馬焉知禍福?我溫習了舊知識,同時也學習了新知識。
總結
- 上一篇: 芯天下8bit MCU
- 下一篇: 计算机二级考试干货内容,计算机二级考试经