内存检测_Android native内存检测工具介绍
點擊上方藍字關注我們噢~
檢測工具不僅可以在驗證時發現安全問題,也可以在運用場景中阻斷安全問題的發生,對于安全問題檢測和攻擊攔截非常友好,當然安全檢測功能會消耗一定的系統性能。本文將對已集成的部分檢測工具進行介紹。
01
背景
Android系統添加了clang的編譯特性,使C/C++代碼編譯時可以添加檢測功能,針對內存安全問題進行檢測。
Clang 12已經支持了很多類型的檢測功能,包括Address Sanitizer、Thread Sanitizer、Memory Sanitizer、Undefined Behavior Sanitizer、Data Flow Sanitizer、Leak Sanitizer等。Android系統集成了部分檢測工具能力。
02
檢測工具介紹
1.??? Address Sanitizer
Address Sanitizer(ASan)用于檢測代碼中的內存錯誤,可以檢測以下類型的錯誤:
1.? 堆棧和全局變量的越界訪問
2.??釋放后使用
3.? 返回后使用
4.? 超出范圍使用
5.? 雙重釋放、錯誤釋放
6.? 內存泄露?
下面通過一個示例來觀察Address Sanitizer是如何檢查內存錯誤的。下文中的代碼是一個簡單的內存釋放后使用的案例:
int main(int argc,int char **argv) { ? ?int *array = new int[100]; ? ?delete [] array; ? ?return array[argc]; } |
創建UseAfterFree.cc文件,使用clang進行編譯并且鏈接ASan參數-fsanitize=address。命令如下:
$clang++ -fsanitize=address UseAfterFree.cc -o AddressSanitizer.so
將未添加參數和添加參數的程序進行對比,可發現添加參數的程序插入了內存檢查邏輯,如下所示:
添加參數的程序
未添加參數的程序
ASan的檢測邏輯是通過內存映射進行的。其將內存分為兩部分:主內存和影子內存,主內存是程序正常使用的,影子內存用于記錄主內存是否可用。主內存每8個字節對應影子內存的一個字節。影子內存的地址是基于主內存計數的基礎上偏移0x7FFF8000,計算方式如下:
64-bit:影子內存地址 = (主內存 >> 3) + 0x7FFF8000
32-bit:影子內存地址 = (主內存 >> 3) + 0x20000000
除了內存映射之外,ASan還在被保護的內存對象周圍建立中毒狀態的內存空間,并對中毒狀態的影子內存做特殊標記。
如下圖所示,主內存可全部訪問,影子內存標記為00;主內存部分可訪問,影子內存標記為可訪問內存的大小:01-07;堆空間周圍中毒狀態內存標記為fa;釋放后的堆空間標記為fd。還有很多其他的標記狀態此處不詳細列舉。
內存標記示意圖
對于檢測原理和方式有了進一步的了解,下面對ASan在程序中的插樁代碼進行分析。經過未添加參數和添加參數的程序的對比,可以觀察到詳細的區別。
首先在申請了內存空間后,添加了空間申請是否成功的檢查。其次在內存釋放后、內存訪問前添加了檢測邏輯。檢測邏輯包含影子內存中的數值和最后一個雙字內存空間的前k個字節是否可訪問。
ASan檢測邏輯說明
由于ASan檢測工具性能影響較大,Android10和AArch64上的AOSP master分支已支持HWAddress Sanitizer(硬件輔助Address Sanitizer),此檢測工具內存開銷更小,代碼空間也更小。
2.???Bounds Sanitizer
Bounds Sanitizer (BoundSan) 用于對數組訪問的邊界檢查。BoundSan是基于Undefined Behavior Sanitizer(UBSan)檢測工具實現的,UBSan用于檢查各種類型的未定義行為,例如使用空指針、有符號整數溢出、浮點類型轉換溢出、數組索引邊界溢出、枚舉類型范圍溢出等。
示例代碼如下:
int main(int argc, char **argv) { ? ?int array[8]; ? ?int bound = 10 + argc; ? ?return array[bound]; } |
創建OutOfBounds.cc文件,使用clang編譯并連接UBSan參數-fsanitize=bounds。編譯命令如下:
clang++ -fsanitize=bounds OutOfBounds.cc -o BoundSan.exe
對比添加參數和未添加參數編譯的程序,觀察UBSan插入的檢測邏輯,如下所示:
添加UBSan參數邏輯
未添加UBSan參數邏輯
相比于ASan提供的檢測邏輯,UBSan提供的檢測邏輯相對簡單。在上圖中可以觀察到插樁代碼僅僅檢查了數組索引值是否超出了數組的最大長度,檢測到問題后報告對應錯誤,如圖所示:
3.???Integer Overflow Sanitization
Integer Overflow Sanitization (IntSan)檢測工具同樣基于Undefined Behavior Sanitizer(UBSan)檢測工具實現的,用于整數溢出檢查,包括有符號和無符號整數溢出檢查。
測試代碼如下所示:
int sum(int input){ ? ?int k = 0x7fffffff; ? ?k += ? input; ? ? ?return k; } int main(int argc, char **argv){ ???int a = sum(argc); ? ? return a; } |
創建IntegerOverflow.cc,使用clang編譯并連接UBSan參數-fsanitize=signed-integer-overflow。編譯命令如下:
clang++ -fsanitize=signed-integer-overflow IntegerOverflow.cc -o IntSan.exe
若需要使用無符號溢出檢查,則需要把參數變更為unsigned-integer-overflow,若有符號和無符號都需要,可以添加兩個參數,用逗號隔開。
對比有無參數編譯的程序,如下圖所示,觀察檢測邏輯。
添加IntSan參數邏輯
未添加IntSan參數邏輯
圖中紅框標記的邏輯即為IntSan添加的溢出檢測邏輯,其中if判斷邏輯中__OFADD__()是IDA定義的宏,用于生成兩數相加溢出的標記。
#define __OFADD__(x, y) invalid_operation // Generate overflow flag for (x+y)
03
總結
Android系統目前已支持了很多安全檢測的工具或機制,除了本文介紹的三類,還包括:
堆分配器(Scudo):用于緩解堆相關的漏洞;
控制流完整性(CFI):用于保證程序的原始控制流圖不被改變
只執行內存(XOM):用于緩解代碼重用攻擊;
影子調用堆棧(SCS):目前只支持aarch64,可保護程序返回地址被覆蓋。
添加了安全檢測功能后,對于系統的性能影響較大,所以在項目中實施安全檢測功能時還需要驗證和測試,android的配置參數支持黑名單或函數屬性來停用安全檢測功能,在不合理或者存在性能問題的代碼謹慎使用。
參考:https://source.android.google.cn/devices/tech/debug/fuzz-sanitizehttps://clang.llvm.org/docs/index.htmlhttps://github.com/google/sanitizers/wiki更多精彩閱讀Soot在Android組件NPE拒絕服務檢測中的應用如何用lint掃出不安全代碼如何用OLLVM來保護你的關鍵代碼長按關注??更多安全技術干貨等你發現?
好文!在看嗎?點一下鴨!總結
以上是生活随笔為你收集整理的内存检测_Android native内存检测工具介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 推荐系统的架构图
- 下一篇: java层 android_Androi