通用Android Native Hook 檢測
前言
Hook技術運用很廣泛兴蒸,從應用安全角度來看邦邦,Hook也是動態(tài)分析、破解一款程序的有效手段砌左。為了提高自己應用被破解的門檻拉背,我們需要一些檢測(對抗)手段师崎,目前也有很多檢測方法,有些是針對特定工具來檢測椅棺,有些較為通用犁罩,這里我把我的一些想法分享給大家齐蔽,歡迎批評指正
目標
給定一個進程內的一個So模塊,判斷它是被inline hook或者GOT hook
GOT HOOK檢測
首先簡單的介紹一下GOT hook是怎么做的
ELF常見的重定位方式如下
創(chuàng)建一個測試工程(arm)床估,來了解一下R_ARM_JUMP_SLOT含滴、R_ARM_GLOB_DAT和R_ARM_ABS32具體是怎么重定位的,工程部分代碼如下
編譯成共享文件(-shared -fPIC)之后丐巫,先看看匯編代碼谈况,6個BLX對應源碼中6個調用過程
再看看.rel.dyn段和.rel.plt段內容(我為了方便查看,grep了一下輸出递胧,導致信息不完整)碑韵,其中前5項是在.rel.dyn段,最后一項(R_ARM_JUMP_SLOT)在.rel.plt段
第一列是需要進行重定位位置在文件的偏移缎脾,通過IDA祝闻,分別來看看各個位置在文件中的內容
1.R_ARM_GLOB_DAT - 0x1adb4、0x1adb8遗菠、0x1adbc (這些位置都在.got段)
2.R_ARM_ABS32 - 0x1b004联喘、0x1b008 (這些位置都在.data段)
3.R_ARM_JUMP_SLOT - 0x1ae5c (這也在.got段)
現在把這個共享文件加載(dlopen)到內存,再看看內存中這6個地址(加載基地址+文件偏移)的內容
1.R_ARM_GLOB_DAT - 0x1adb4辙纬、0x1adb8豁遭、0x1adbc
2.R_ARM_ABS32 - 0x1b004、0x1b008
3.R_ARM_JUMP_SLOT - 0x1ae5c
這個0xF28FB625(0xF28FB624+1)就是strlen在內存中的入口
直接來總結(文件偏移用小寫16進制贺拣,實際內存地址用大寫16進制)
1.R_ARM_GLOB_DAT堤框,重定位信息記錄在'.rel.dyn'段中,其offset指向了.got段中的項纵柿,在加載到內存后蜈抓,會將offset的內容修改為相應符號的實際內存地址
a.0x1adb4(strlen_ptr) 內容被修改成了 strlen 的實際內存地址(0xF28FB625)
b.0x1adb8(global_strlen1_ptr) 內容被修改成了 global_strlen1 的實際內存地址(0xD35DE004)
c.0x1adbc(global_strlen2_ptr) 內容被修改成了 global_strlen2 的實際內存地址(0xD35DE008)
2.R_ARM_ABS32 ,重定位信息記錄在'.rel.dyn'段中昂儒,其offset指向了.data段中的項沟使,在加載到內存后,會將offset的內容修改為相應符號地址
a.0x1b004(global_strlen1) 內容被修改成了 strlen 的實際內存地址(0xF28FB625)
b.0x1b008(global_strlen2) 內容被修改成了 strlen 的實際內存地址(0xF28FB625)
3.R_ARM_JUMP_SLOT ,重定位信息記錄在'.rel.plt'段中渊跋,其offset指向了.got段中的項腊嗡,在加載到內存后,會將offset的內容修改為相應符號地址
0x1ae5c (strlen_ptr_0) 內容被修改成了 strlen 的實際內存地址(0xF28FB625)
通過上面的圖文描述拾酝,大概了解全局指針調用外部函數和局部指針調用外部函數的調用過程燕少,這里在單獨說一下直接調用外部函數的調用過程,也就是唯一一個在'rel.plt'段中的R_ARM_JUMP_SLOT類型蒿囤,匯編中0x8c30和0x8c38這兩個BLX客们,實際上會跳轉到.plt段
然后在通過LDR指令將strlen_ptr_0指向的內容賦值給PC,最終實現函數調用
好了!5状臁:闵怠!=ǖ恕S濉!9俦摺7惺帧!W⒉尽F跫!L苍!K摇M婊病!=骶俊6鞲ぁ!=赫堋E纤!Q煊臁3憾帧!<陌凇A吕薄!I裟铡桑阶!
明白了具體的重定位過程,檢測GOT hook的核心思路也出來了勾邦,就是檢測'.rel.dyn'和'.rel.plt'中的重定位項的offset指向的(實際內存)地址的內容是不是它應該在的模塊
那么怎么獲取'.rel.dyn'和'.rel.plt'中的重定位項內容呢蚣录?
解析加載后的ELF文件的Dynamic Segment,其中DT_JMPREL眷篇、DT_PLTRELSZ對應'.rel.plt'信息萎河,DT_REL、DT_RELSZ對應'.rel.dyn'信息,你可能還需要DT_SYMTAB和DT_STRTAB來輔助解析符號名
那么怎么判斷是不是符號應該在的區(qū)域呢公壤?
一圖便知
獲取到了重定位項的實際內存地址之后换可,然后去/proc/self/maps里查找該地址所屬的區(qū)域是否映射來至NEEDED的文件或是你自身
注意:如果你本來就有hotfix的情況,這里可能就會出現誤報
最后代碼就不提供了厦幅,主要也就是ELF的linking view 和 execution view 的解析
INLINE HOOK檢測
在之前描述重定位的時候沾鳄,要求是開啟了-fPIC,位置無關代碼讓.text段的內容在ELF加載前后沒有發(fā)生變化确憨,那么檢測inline hook的一個思路就出來了译荞,對比內存中的.text段和文件中的.text的crc是否相等
大致流程
????1.解析/proc/self/maps
????2.匹配到你需要檢測的so文件,獲取其的加載基地址和文件路徑
????3.通過mmap將文件映射到內存休弃,然后把內容傳給ELF解析工具吞歼,獲取其.text段的偏移和大小
????4.通過偏移+加載基地址 和 偏移+mmap返回值 以及.text段大小來計算crc,并比對
那么如果沒有開啟位置無關怎么辦呢塔猾?
目前我很少在Android上看到沒有開啟的PIC/PIE的ELF文件篙骡,查閱了相關資料,沒有看到明確的要求丈甸,為了兼容沒開啟PIC/PIE的情況糯俗,這里還有一種方式來檢測
掃描inline hook的跳轉指令?
arm? 對應指令- LDR PC, [PC, #-4]? ?字節(jié)碼 - 0xE51FF004?
thumb32??對應指令-?LDR.W PC, [PC, #0]? ? 字節(jié)碼 - 0x00F0DFF8
當然這個功能也可以用來定位具體被hook地址
如果還有其他的檢測思路,歡迎評論私信
若有志同道合的小伙伴也歡迎私信加個微信^_^
查考鏈接:
1.https://source.android.com/security/enhancements/enhancements50
2.https://source.android.com/devices/tech/dalvik/configure?hl=en