康艷榮 ,范 瑋 ,趙 露 ,劉 亞
(1.公安部物證鑒定中心,北京 100038;2.天津市公安局物證鑒定中心,天津 300384;3.深圳市公安局, 廣東 深圳 518001)
Android是基于Linux內(nèi)核的移動(dòng)操作系統(tǒng),大部分適用于Linux動(dòng)態(tài)內(nèi)存分析的框架也適用于Android,如 Volatility[1]、Second Look[2]、Rekall[3]等。但基于Android的動(dòng)態(tài)內(nèi)存提取工具則非常少,2004年Carrier[4]提出了基于硬件的內(nèi)存提取框架,但無法在Android上操作,目前基于Android的動(dòng)態(tài)內(nèi)存提取只有軟件工具,其中比較成熟的是2012年由Sylve[5]提出的LiME Forensics。2012年10月Muller等[6]在發(fā)表的論文中報(bào)道了一種在FROST狀態(tài)下提取Android手機(jī)隨機(jī)訪問內(nèi)存的方法。FROST技術(shù)的實(shí)現(xiàn)也是基于LiME工具,但該文章沒有對(duì)提取的數(shù)據(jù)做任何分析,而且用于試驗(yàn)的手機(jī)型號(hào)也僅限于Sam-sung Galaxy Nexus。2013 年,Stüttgen 等[7]提出了一種新的PTE物理內(nèi)存提取技術(shù),然而使用的PMEM工具僅能在Windows、Linux、Mac OS X運(yùn)行,尚不能提取Android手機(jī)的物理內(nèi)存。2014年,Stüttgen等[8]又提出了一種新的通過重定向技術(shù)使注入到目標(biāo)系統(tǒng)的通用內(nèi)核模塊執(zhí)行提取內(nèi)存命令的方法,但該研究的實(shí)驗(yàn)對(duì)象是2.6.38至 3.10的Linux發(fā)行版,并沒有在Android上進(jìn)行測(cè)試。2014年,Cohen等[9]提出了Rekall Memory Forensic Framework,是一個(gè)完整的開源的動(dòng)態(tài)內(nèi)存提取與分析解決方案,該系列工具的支持對(duì)象有Windows, OSX 和Linux。在2015年最新發(fā)布的版本中,該框架可以對(duì)Android的動(dòng)態(tài)內(nèi)存進(jìn)行分析,然而尚未能提取到Android的動(dòng)態(tài)內(nèi)存。
在Linux平臺(tái)上,基于內(nèi)核模塊的取證工具通常需要針對(duì)特定版本內(nèi)核和配置來進(jìn)行編譯工作,這使得在實(shí)際工作中,對(duì)Linux內(nèi)存提取操作十分復(fù)雜。由于Linux的內(nèi)核安全機(jī)制,一般會(huì)拒絕裝載針對(duì)非本身版本的模塊,即使通過技術(shù)手段繞過內(nèi)核校驗(yàn)機(jī)制,也無法避免內(nèi)核中的符號(hào)導(dǎo)出問題[10]。使用LiME工具對(duì)Android動(dòng)態(tài)內(nèi)存的提取準(zhǔn)備工作中,需要基于目標(biāo)系統(tǒng)對(duì)應(yīng)的內(nèi)核源代碼,而在大部分取證工作中,由于Android開放源代碼的不完全性,特別是對(duì)于廠商定制版的手機(jī)型號(hào),很難獲取與目標(biāo)Android系統(tǒng)完全匹配的內(nèi)核源代碼,這使得取證工作的開展具有一定困難。本文提出一種通過解決未知符號(hào)錯(cuò)誤實(shí)現(xiàn)基于相似內(nèi)核提取Android手機(jī)動(dòng)態(tài)內(nèi)存的方法。該方法通過分析Linux下ELF格式與內(nèi)核符號(hào)機(jī)制,在內(nèi)核源碼中找到未知符號(hào)函數(shù)定義并取消其在內(nèi)核中的配置,編譯內(nèi)核時(shí)產(chǎn)生不具有指定的符號(hào)引用信息的模塊,最后將相似內(nèi)核成功加載至目標(biāo)手機(jī)并提取到動(dòng)態(tài)內(nèi)存數(shù)據(jù)。
Linux下的內(nèi)核模塊實(shí)質(zhì)上是可重定位的ELF(Executable and Linkable Format)目標(biāo)文件,ELF文件是Linux里一種非常重要的數(shù)據(jù)形式,總體可分為ELF頭部、Section部分和尾部的Section Header Table部分。內(nèi)核根據(jù)ELF頭部確定文件中需要映射到內(nèi)存中的部分,在文件的動(dòng)態(tài)鏈接過程中,外部符號(hào)通過全局偏移表(.got)和過程鏈接表(.plt)解決運(yùn)行時(shí)的符號(hào)引用問題。符號(hào)表是可裝載模塊中描述符號(hào)定義的信息組合,全局偏移表用于映射模塊內(nèi)部引用與外部地址,若在模塊加載過程中,出現(xiàn)獨(dú)立編譯的外部模塊需要本地內(nèi)核加載的情況,內(nèi)核無法解決符號(hào)引用問題,就會(huì)出現(xiàn)模塊裝載錯(cuò)誤。
在Linux系統(tǒng)下,內(nèi)核模塊之間的變量和函數(shù)的共享通過符號(hào)信息實(shí)現(xiàn),在底層代碼的實(shí)現(xiàn)層面上,內(nèi)核符號(hào)信息的導(dǎo)出以宏聲明的方式聲明定義。Linux源碼下的/module.h中定義了內(nèi)核符號(hào)導(dǎo)出的三種聲明方式:
#define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym)
#define EXPORT_SYMBOL_GPL_FUTURE(sym)
編譯內(nèi)核模塊時(shí),遇到EXPORT_SYMBOL的宏定義則在對(duì)應(yīng)模塊中導(dǎo)出相應(yīng)的符號(hào)信息,在對(duì)應(yīng)的ELF視圖下可看到對(duì)應(yīng)符號(hào)的內(nèi)存地址。內(nèi)核完全編譯后,生成存儲(chǔ)所有符號(hào)信息的System.map文件,對(duì)于指定的模塊可通過readelf命令讀取ELF中的符號(hào)信息。圖1為模塊中的外部符號(hào)變量在匯編視圖中的顯示。
圖1 內(nèi)核模塊存在的外部符號(hào)Fig.1 External symbols from kernel module
基于上述原理,在本地內(nèi)核中加載外部模塊時(shí),可能會(huì)出現(xiàn)模塊中內(nèi)核符號(hào)不一致問題導(dǎo)致加載失敗,解決這類問題的關(guān)鍵是在編譯階段防止模塊導(dǎo)出特定的符號(hào)信息。在編譯基于Linux的源碼時(shí),內(nèi)核配置的具體細(xì)節(jié)會(huì)使模塊中的導(dǎo)出符號(hào)產(chǎn)生很大差別,不同的配置選項(xiàng)用于引用不同的函數(shù),因此在特定系統(tǒng)內(nèi)核中加載外部模塊時(shí),實(shí)質(zhì)上是由于模塊中未知符號(hào)引用的函數(shù)體在特定內(nèi)核中未被定義,目標(biāo)系統(tǒng)無法識(shí)別該模塊中的函數(shù),出現(xiàn)未解決的符號(hào)引用錯(cuò)誤。在編譯前取消對(duì)該未知函數(shù)體的引用,可以解決此類問題。
由于Linux內(nèi)核源碼的復(fù)雜性與差異性,基于某一內(nèi)核版本編譯的模塊在內(nèi)核配置上存在很大的不同,要使得編譯的外部模塊與目標(biāo)系統(tǒng)內(nèi)核中的符號(hào)信息相差最小,需盡量減小依賴編譯的內(nèi)核與目標(biāo)系統(tǒng)內(nèi)核的版本差異性,這樣可使內(nèi)核符號(hào)表中的引用的函數(shù)體相互匹配。
解決模塊因符號(hào)錯(cuò)誤造成的加載失敗,需要對(duì)未解決的符號(hào)進(jìn)行分析,在相應(yīng)的內(nèi)核源碼中確定所依賴的函數(shù)體,并分析該符號(hào)在模塊之間的相互依賴關(guān)系。再根據(jù)函數(shù)定義在內(nèi)核配置中取消對(duì)應(yīng)的配置,在編譯內(nèi)核時(shí)產(chǎn)生的模塊即不具有指定的符號(hào)引用信息,可以使基于內(nèi)核的取證模塊在目標(biāo)內(nèi)核中成功裝載。
LiME是基于內(nèi)核編譯的可裝載模塊取證工具,可以從Android手機(jī)中提取動(dòng)態(tài)內(nèi)存,是面向Android的易失性取證方面非常有價(jià)值的工具。構(gòu)造LiME模塊需要編譯對(duì)應(yīng)目標(biāo)Android手機(jī)的設(shè)備內(nèi)核源代碼,而在現(xiàn)實(shí)取證工作中,出于各種原因或無法獲得目標(biāo)Android手機(jī)的對(duì)應(yīng)內(nèi)核源代碼,使用相似內(nèi)核源碼產(chǎn)生的模塊在手機(jī)上加載時(shí),會(huì)出現(xiàn)內(nèi)核符號(hào)表未知引用的問題。本文以HTC S710d,Android版本 2.2,內(nèi)核版本2.6.3 5為實(shí)驗(yàn)對(duì)象,相似內(nèi)核選擇flyer-hc-mr-2.6.35-f4a346d。
Android 手機(jī)是USB調(diào)試模式并已經(jīng)獲得ROOT權(quán)限。操作系統(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 訪問權(quán)限配置:
#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)境配置:(本實(shí)驗(yà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
將上述生成模塊上傳至目標(biāo)Android手機(jī)中,裝載該模塊后出現(xiàn)如圖2所示的錯(cuò)誤。
圖2 使用LiME時(shí)出現(xiàn)未知符號(hào)引用Fig.2 Unknown symbol errors caused by LiME execution
由該錯(cuò)誤可知,Android手機(jī)裝載LiME模塊時(shí),該模塊中含有__gnu_mcount_nc符號(hào)信息,但該符號(hào)引用在原Android系統(tǒng)中未被定義,于是出現(xiàn)無法識(shí)別該函數(shù)的錯(cuò)誤提示。根據(jù)反饋的提示,需要在內(nèi)核源碼中分析有關(guān)__gnu_mcount_nc符號(hào)變量的定義代碼,并尋找與該符號(hào)有依賴關(guān)系的函數(shù)定義。通過在源碼中進(jìn)行遍歷操作,可知該符號(hào)由ftrace操作產(chǎn)生,ftrace可以動(dòng)態(tài)地監(jiān)視Linux內(nèi)核中的行為,是基于Linux內(nèi)核的一個(gè)非常重要的內(nèi)核跟蹤調(diào)試工具,ftrace定義中關(guān)于__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);
……
內(nèi)核配置里關(guān)于ftrace的選項(xiàng)與CONFIG_FUNCTION_TRACER相關(guān),當(dāng)啟用該內(nèi)核設(shè)置時(shí),編譯內(nèi)核時(shí)就會(huì)加入ftrace的所有相關(guān)的函數(shù)引用,并向外部導(dǎo)出__gnu_mcount_nc的符號(hào)信息。實(shí)驗(yàn)所用的Android手機(jī)中系統(tǒng)內(nèi)核并無編譯ftrace功能,加載該模塊時(shí)就會(huì)觸發(fā)手機(jī)內(nèi)核對(duì)該符號(hào)的依賴,但由于手機(jī)中未定義該函數(shù),因此在Android手機(jī)加載模塊時(shí)出現(xiàn)未知符號(hào)__gnu_mcount_nc的提示。
確定未知符號(hào)由ftrace引起后,在源碼中繼續(xù)遍歷與ftrace相關(guān)的所有內(nèi)核編譯選項(xiàng),分析其函數(shù)間的調(diào)用關(guān)系,發(fā)現(xiàn)以下設(shè)置依賴于__gnu_mcount_nc符號(hào):
CONFIG_FUNCTION_TRACER
CONFIG_DYNAMIC_FTRACE
CONFIG_FUNCTION_GRAPH_TRACER
……
編輯源碼下的.config配置文件,關(guān)閉相關(guān)配置選項(xiàng),重新執(zhí)行編譯操作后的內(nèi)核不具備ftrace功能。經(jīng)分析發(fā)現(xiàn),編譯后的底層數(shù)據(jù)文件還存在__gnu_mcount_nc符號(hào)信息,查找后定位在/kernel/bounds.s與/arch/arm/kernel/asm-offsets.s中,如圖3所示該數(shù)據(jù)文件以匯編形式存在。
圖3 文件中的__gnu_mcount_nc符號(hào)Fig.3 “__gnu_mcount_nc” symbol in the related file
對(duì)編譯過程進(jìn)行研究可知,LiME編譯外部模塊時(shí)依賴上述兩個(gè)文件,構(gòu)造的外部模塊也會(huì)具有__gnu_mcount_nc符號(hào),需要對(duì)符號(hào)所在的數(shù)據(jù)段進(jìn)行刪除。使用gedit定位至該符號(hào)所在代碼,如圖4所示中的.LCFI2段,將所有內(nèi)容刪除后直接使用LiME重新編譯模塊,讀取該模塊的ELF信息并未發(fā)現(xiàn)__gnu_mcount_nc符號(hào),將模塊上傳至Android手機(jī)中最終能夠成功裝載,提取動(dòng)態(tài)內(nèi)存,且內(nèi)存提取效率與使用源目標(biāo)內(nèi)核代碼相差很小。繼續(xù)使用多個(gè)型號(hào)手機(jī)進(jìn)行內(nèi)存提取實(shí)驗(yàn),按照基本原理方法對(duì)內(nèi)核符號(hào)進(jìn)行跟蹤調(diào)試,發(fā)現(xiàn)模塊中出現(xiàn)的未知符號(hào)主要與內(nèi)核中內(nèi)存管理、虛擬系統(tǒng)等底層架構(gòu)有關(guān),如配置了CONFIG_SPARSEMEM_高端內(nèi)存管理相關(guān)選項(xiàng)組后,模塊中會(huì)調(diào)用mem_section符號(hào)信息,因此裝載模塊時(shí)需要內(nèi)核對(duì)mem_section的依賴,而定義CONFIG_ARM_PATCH_PHYS_等關(guān)于地址管理的配置信息后,由于內(nèi)核中需要映射虛擬地址與物理地址的關(guān)系,而導(dǎo)致內(nèi)核需要引用__pv_phys_offset符號(hào)。在編譯內(nèi)核前消除對(duì)相關(guān)符號(hào)的引用,可以使模塊中不含有該符號(hào)。實(shí)驗(yàn)結(jié)果證明該方法編譯后的模塊可以在相似內(nèi)核手機(jī)上加載并能成功提取動(dòng)態(tài)內(nèi)存。
通過LiME工具,使用相似內(nèi)核代碼對(duì)目標(biāo)Android手機(jī)進(jìn)行動(dòng)態(tài)內(nèi)存提取實(shí)驗(yàn),實(shí)驗(yàn)結(jié)果見表1。
表1 基于相似內(nèi)核編譯的動(dòng)態(tài)內(nèi)存提取結(jié)果Table 1 Live memory extraction based on similar kernel compiling
本文介紹的方法能夠在無法獲取目標(biāo)手機(jī)的內(nèi)核源代碼時(shí),使用相似內(nèi)核源碼進(jìn)行替代從而有效提取Android手機(jī)的動(dòng)態(tài)內(nèi)存。本實(shí)驗(yàn)證明了通過調(diào)試內(nèi)核符號(hào)可以使模塊在不同版本特征的內(nèi)核中進(jìn)行裝載,減少了目標(biāo)系統(tǒng)對(duì)基于內(nèi)核模塊的內(nèi)存取證工具的影響,對(duì)實(shí)際取證工作有一定的積極作用。LiME是有效提取完整的Android手機(jī)動(dòng)態(tài)內(nèi)存的取證工具,在目前的情況下,這種取證方法可以大大提高內(nèi)存提取成功率,而將對(duì)原始證據(jù)信息的影響降到最低。
[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.