康艷榮 ,范 瑋 ,趙 露 ,劉 亞
(1.公安部物證鑒定中心,北京 100038;2.天津市公安局物證鑒定中心,天津 300384;3.深圳市公安局, 廣東 深圳 518001)
Android是基于Linux內核的移動操作系統(tǒng),大部分適用于Linux動態(tài)內存分析的框架也適用于Android,如 Volatility[1]、Second Look[2]、Rekall[3]等。但基于Android的動態(tài)內存提取工具則非常少,2004年Carrier[4]提出了基于硬件的內存提取框架,但無法在Android上操作,目前基于Android的動態(tài)內存提取只有軟件工具,其中比較成熟的是2012年由Sylve[5]提出的LiME Forensics。2012年10月Muller等[6]在發(fā)表的論文中報道了一種在FROST狀態(tài)下提取Android手機隨機訪問內存的方法。FROST技術的實現(xiàn)也是基于LiME工具,但該文章沒有對提取的數據做任何分析,而且用于試驗的手機型號也僅限于Sam-sung Galaxy Nexus。2013 年,Stüttgen 等[7]提出了一種新的PTE物理內存提取技術,然而使用的PMEM工具僅能在Windows、Linux、Mac OS X運行,尚不能提取Android手機的物理內存。2014年,Stüttgen等[8]又提出了一種新的通過重定向技術使注入到目標系統(tǒng)的通用內核模塊執(zhí)行提取內存命令的方法,但該研究的實驗對象是2.6.38至 3.10的Linux發(fā)行版,并沒有在Android上進行測試。2014年,Cohen等[9]提出了Rekall Memory Forensic Framework,是一個完整的開源的動態(tài)內存提取與分析解決方案,該系列工具的支持對象有Windows, OSX 和Linux。在2015年最新發(fā)布的版本中,該框架可以對Android的動態(tài)內存進行分析,然而尚未能提取到Android的動態(tài)內存。
在Linux平臺上,基于內核模塊的取證工具通常需要針對特定版本內核和配置來進行編譯工作,這使得在實際工作中,對Linux內存提取操作十分復雜。由于Linux的內核安全機制,一般會拒絕裝載針對非本身版本的模塊,即使通過技術手段繞過內核校驗機制,也無法避免內核中的符號導出問題[10]。使用LiME工具對Android動態(tài)內存的提取準備工作中,需要基于目標系統(tǒng)對應的內核源代碼,而在大部分取證工作中,由于Android開放源代碼的不完全性,特別是對于廠商定制版的手機型號,很難獲取與目標Android系統(tǒng)完全匹配的內核源代碼,這使得取證工作的開展具有一定困難。本文提出一種通過解決未知符號錯誤實現(xiàn)基于相似內核提取Android手機動態(tài)內存的方法。該方法通過分析Linux下ELF格式與內核符號機制,在內核源碼中找到未知符號函數定義并取消其在內核中的配置,編譯內核時產生不具有指定的符號引用信息的模塊,最后將相似內核成功加載至目標手機并提取到動態(tài)內存數據。
Linux下的內核模塊實質上是可重定位的ELF(Executable and Linkable Format)目標文件,ELF文件是Linux里一種非常重要的數據形式,總體可分為ELF頭部、Section部分和尾部的Section Header Table部分。內核根據ELF頭部確定文件中需要映射到內存中的部分,在文件的動態(tài)鏈接過程中,外部符號通過全局偏移表(.got)和過程鏈接表(.plt)解決運行時的符號引用問題。符號表是可裝載模塊中描述符號定義的信息組合,全局偏移表用于映射模塊內部引用與外部地址,若在模塊加載過程中,出現(xiàn)獨立編譯的外部模塊需要本地內核加載的情況,內核無法解決符號引用問題,就會出現(xiàn)模塊裝載錯誤。
在Linux系統(tǒng)下,內核模塊之間的變量和函數的共享通過符號信息實現(xiàn),在底層代碼的實現(xiàn)層面上,內核符號信息的導出以宏聲明的方式聲明定義。Linux源碼下的/module.h中定義了內核符號導出的三種聲明方式:
#define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym)
#define EXPORT_SYMBOL_GPL_FUTURE(sym)
編譯內核模塊時,遇到EXPORT_SYMBOL的宏定義則在對應模塊中導出相應的符號信息,在對應的ELF視圖下可看到對應符號的內存地址。內核完全編譯后,生成存儲所有符號信息的System.map文件,對于指定的模塊可通過readelf命令讀取ELF中的符號信息。圖1為模塊中的外部符號變量在匯編視圖中的顯示。
圖1 內核模塊存在的外部符號Fig.1 External symbols from kernel module
基于上述原理,在本地內核中加載外部模塊時,可能會出現(xiàn)模塊中內核符號不一致問題導致加載失敗,解決這類問題的關鍵是在編譯階段防止模塊導出特定的符號信息。在編譯基于Linux的源碼時,內核配置的具體細節(jié)會使模塊中的導出符號產生很大差別,不同的配置選項用于引用不同的函數,因此在特定系統(tǒng)內核中加載外部模塊時,實質上是由于模塊中未知符號引用的函數體在特定內核中未被定義,目標系統(tǒng)無法識別該模塊中的函數,出現(xiàn)未解決的符號引用錯誤。在編譯前取消對該未知函數體的引用,可以解決此類問題。
由于Linux內核源碼的復雜性與差異性,基于某一內核版本編譯的模塊在內核配置上存在很大的不同,要使得編譯的外部模塊與目標系統(tǒng)內核中的符號信息相差最小,需盡量減小依賴編譯的內核與目標系統(tǒng)內核的版本差異性,這樣可使內核符號表中的引用的函數體相互匹配。
解決模塊因符號錯誤造成的加載失敗,需要對未解決的符號進行分析,在相應的內核源碼中確定所依賴的函數體,并分析該符號在模塊之間的相互依賴關系。再根據函數定義在內核配置中取消對應的配置,在編譯內核時產生的模塊即不具有指定的符號引用信息,可以使基于內核的取證模塊在目標內核中成功裝載。
LiME是基于內核編譯的可裝載模塊取證工具,可以從Android手機中提取動態(tài)內存,是面向Android的易失性取證方面非常有價值的工具。構造LiME模塊需要編譯對應目標Android手機的設備內核源代碼,而在現(xiàn)實取證工作中,出于各種原因或無法獲得目標Android手機的對應內核源代碼,使用相似內核源碼產生的模塊在手機上加載時,會出現(xiàn)內核符號表未知引用的問題。本文以HTC S710d,Android版本 2.2,內核版本2.6.3 5為實驗對象,相似內核選擇flyer-hc-mr-2.6.35-f4a346d。
Android 手機是USB調試模式并已經獲得ROOT權限。操作系統(tǒng)為32位Ubuntu 12.04。
JDK 7.0 配置與軟件包安裝:
$sudo apt-get install ia32-libs
$sudo apt-get update
$sudo apt-get install openjdk-7-jdk
$sudo apt-get install gitgnupg flex bison gperf build-essential/
zip curl libc6-dev libncurses5-dev:i386 x11protocore-dev/
libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-glx:i386/
libgl1-mesa-dev g++-multilib mingw32 tofrodos/
python-markdown libxml2-utils xsltproc zlib1gdev:i386
$sudoln -s /usr/lib/i386-linux-gnu/mesa/libGL.so.1/usr/lib/i386-linux-gnu/libGL.so
Android USB 訪問權限配置:
#HTC
SUBSYSTEM= =” usb”, SYSFS(idVendor)= =”0bb4”,MODE=”0666”
Android SDK 配置:
# Android SDK
export PATH=~/Android/Sdk/platform-tools:$PATH
export PATH=~/Android/Sdk/tools:$PATH
$sudo source /etc/profile
Android NDK 配置:
$chmoda+x android-ndk-r10c-darwin-x86_64.bin
$./android-ndk-r10c-darwin-x86_64.bin
export PATH=/home/liu/android/ndk/toolchains/arm-linux-androideabi-4.6/
prebuilt/linux-x86/bin: $PATH
$sudo source /etc/profile
Build cross-compiling environment
編譯器環(huán)境配置:(本實驗使用arm-eabi-4.4.3作為編譯器)
$sudomkdir /home/liu/cc
$sudochmod 777 /home/liu/cc
$sudo tar –xzvf arm-eabi-4.4.3
$sudogedit ~/.bashrc
# arm-eabi- path
export PATH=/home/liu/cc/ arm-eabi-4.4.3/bin:$PATH
$sudo source ~/.bashrc
$sudo arm-eabi-gcc –v
LiME配置:
$sudogit clone https://github.com/504ensicsLabs/LiME.git
# LiME
export LIME=/home/liu/android/lime/src
$sudo source /etc/profile
make KERNELRELEASE=
Makefile配置:
SUBARCH := arm
ARCH:= arm
CROSS_COMPILE:= /home/liu/cc/arm-eabi-4.4.3/bin/arm-eabi-
Lime模塊編譯:obj-m := lime.o
lime-objs := main.otcp.odisk.o
KDIR :=
PWD := $(shell pwd)
CCPATH :=
default:
$(MAKE) ARCH=arm CROSS_COMPILE=$(CCPATH)/arm-linux-androideabi- -C $(KDIR_GOLDFISH) EXTRA_CFLAGS=-fno-pic M=$(PWD) modules
將上述生成模塊上傳至目標Android手機中,裝載該模塊后出現(xiàn)如圖2所示的錯誤。
圖2 使用LiME時出現(xiàn)未知符號引用Fig.2 Unknown symbol errors caused by LiME execution
由該錯誤可知,Android手機裝載LiME模塊時,該模塊中含有__gnu_mcount_nc符號信息,但該符號引用在原Android系統(tǒng)中未被定義,于是出現(xiàn)無法識別該函數的錯誤提示。根據反饋的提示,需要在內核源碼中分析有關__gnu_mcount_nc符號變量的定義代碼,并尋找與該符號有依賴關系的函數定義。通過在源碼中進行遍歷操作,可知該符號由ftrace操作產生,ftrace可以動態(tài)地監(jiān)視Linux內核中的行為,是基于Linux內核的一個非常重要的內核跟蹤調試工具,ftrace定義中關于__gnu_mcount_nc的聲明如下:
#ifdef CONFIG_FUNCTION_TRACER
#define MCOUNT_ADDR((unsigned long)(__gnu_mcount_nc))
#define MCOUNT_INSN_SIZE4 /* sizeofmcount call */
#ifndef __ASSEMBLY__
extern void mcount(void);
extern void __gnu_mcount_nc(void);
……
內核配置里關于ftrace的選項與CONFIG_FUNCTION_TRACER相關,當啟用該內核設置時,編譯內核時就會加入ftrace的所有相關的函數引用,并向外部導出__gnu_mcount_nc的符號信息。實驗所用的Android手機中系統(tǒng)內核并無編譯ftrace功能,加載該模塊時就會觸發(fā)手機內核對該符號的依賴,但由于手機中未定義該函數,因此在Android手機加載模塊時出現(xiàn)未知符號__gnu_mcount_nc的提示。
確定未知符號由ftrace引起后,在源碼中繼續(xù)遍歷與ftrace相關的所有內核編譯選項,分析其函數間的調用關系,發(fā)現(xiàn)以下設置依賴于__gnu_mcount_nc符號:
CONFIG_FUNCTION_TRACER
CONFIG_DYNAMIC_FTRACE
CONFIG_FUNCTION_GRAPH_TRACER
……
編輯源碼下的.config配置文件,關閉相關配置選項,重新執(zhí)行編譯操作后的內核不具備ftrace功能。經分析發(fā)現(xiàn),編譯后的底層數據文件還存在__gnu_mcount_nc符號信息,查找后定位在/kernel/bounds.s與/arch/arm/kernel/asm-offsets.s中,如圖3所示該數據文件以匯編形式存在。
圖3 文件中的__gnu_mcount_nc符號Fig.3 “__gnu_mcount_nc” symbol in the related file
對編譯過程進行研究可知,LiME編譯外部模塊時依賴上述兩個文件,構造的外部模塊也會具有__gnu_mcount_nc符號,需要對符號所在的數據段進行刪除。使用gedit定位至該符號所在代碼,如圖4所示中的.LCFI2段,將所有內容刪除后直接使用LiME重新編譯模塊,讀取該模塊的ELF信息并未發(fā)現(xiàn)__gnu_mcount_nc符號,將模塊上傳至Android手機中最終能夠成功裝載,提取動態(tài)內存,且內存提取效率與使用源目標內核代碼相差很小。繼續(xù)使用多個型號手機進行內存提取實驗,按照基本原理方法對內核符號進行跟蹤調試,發(fā)現(xiàn)模塊中出現(xiàn)的未知符號主要與內核中內存管理、虛擬系統(tǒng)等底層架構有關,如配置了CONFIG_SPARSEMEM_高端內存管理相關選項組后,模塊中會調用mem_section符號信息,因此裝載模塊時需要內核對mem_section的依賴,而定義CONFIG_ARM_PATCH_PHYS_等關于地址管理的配置信息后,由于內核中需要映射虛擬地址與物理地址的關系,而導致內核需要引用__pv_phys_offset符號。在編譯內核前消除對相關符號的引用,可以使模塊中不含有該符號。實驗結果證明該方法編譯后的模塊可以在相似內核手機上加載并能成功提取動態(tài)內存。
通過LiME工具,使用相似內核代碼對目標Android手機進行動態(tài)內存提取實驗,實驗結果見表1。
表1 基于相似內核編譯的動態(tài)內存提取結果Table 1 Live memory extraction based on similar kernel compiling
本文介紹的方法能夠在無法獲取目標手機的內核源代碼時,使用相似內核源碼進行替代從而有效提取Android手機的動態(tài)內存。本實驗證明了通過調試內核符號可以使模塊在不同版本特征的內核中進行裝載,減少了目標系統(tǒng)對基于內核模塊的內存取證工具的影響,對實際取證工作有一定的積極作用。LiME是有效提取完整的Android手機動態(tài)內存的取證工具,在目前的情況下,這種取證方法可以大大提高內存提取成功率,而將對原始證據信息的影響降到最低。
[1] WALTERS A. Volatility: an advanced memory forensics framework[EB/OL].[2015-11-06]. https://code.google.com/p/volatility/.
[2] PIKEWERKS R. Linux incident response with second look[EB/OL].[2017-4-5].http://secondlookforensics.com/linux-incident-response/.
[3] STüTTGEN J, COHEN M. Robust Linux memory acquisition with minimal target impact[J]. Digital Investigation,2014,11(5):S112- S119.
[4] CARRIER B D, Grand J. A hardware-based memory acquisition procedure for digital investigations[J].Investigation, 2004,1(1):50–60.
[5] SYLVE J, CASE A, MARZIALE L, et al. Acquisition and analysis of volatile memory from Android devices[J]. Digital Investigation, 2012,8(s3-4):175-184.
[6] MüLLER T, SPREITZENBARTH M, FELIX C. FROST:forensic recovery of scrambled telephones [C]. International Conference on Applied Cryptography & Network Security,2013:373-388.
[7] STüTTGEN J, COHEN M. Anti-forensic resilient memory acquisition[J]. Digital Investigation,2013(10): S105–S115.
[8] STüTTGEN J, COHEN M. Robust Linux memory acquisition with minimal target impact [J]. Digital Investigation,2014(10):S112–S119.
[9] Cohen M. Rekall Memory Forensics [EB/OL].[2016-11-04].http://www.rekall-forensic.com/.
[10] The Linux kernel Archives. The Linux kernel source code[EB/OL].[2013-11-20].https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.12.tar.xz.
[11] (ELF) Specification v1.2[EB/OL].[1995-05-01]. http://refspecs.linuxbase.org/elf/elf.pdf.