前言
今天主要介紹的是通過核心通訊的方式擷取裝置網卡mac指紋,主要通過netlink的方式和核心通訊去擷取mac網卡位址 。
這種方式可以直接繞過android的權限。
在不給app授權的時候也可以直接擷取到網卡資訊。因為很難進行mock,是以很多大廠app也都是采用這種辦法去擷取。
netlink簡介:
Netlink是linux提供的用于核心和使用者态程序之間的通信方式。
- 但是注意雖然Netlink主要用于使用者空間和核心空間的通信,但是也能用于使用者空間的兩個程序通信。
- 隻是程序間通信有其他很多方式,一般不用Netlink。除非需要用到Netlink的廣播特性時。
- NetLink機制是一種特殊的socket,它是Linux特有的,由于傳送的消息是暫存在socket接收緩存中,并不為接受者立即處理,是以netlink是一種異步通信機制。系統調用和ioctl是同步通信機制。
一般來說使用者空間和核心空間的通信方式有三種:
proc
ioctl
Netlink
而前兩種都是單向的,但是Netlink可以實作雙工通信。
Netlink協定基于BSD socket和AF_NETLINK位址簇(address family)。
使用32位的端口号尋址(以前稱為PID),每個Netlink協定(或稱作總線,man手冊中則稱之為netlink family),通常與一個或者一組核心服務/元件相關聯,如NETLINK_ROUTE用于擷取和設定路由與鍊路資訊、NETLINK_KOBJECT_UEVENT用于核心向使用者空間的udev程序發送通知等。
netlink特點:
1,支援全雙工、異步通信
2,使用者空間可以使用标準的BSD socket接口(但netlink并沒有屏蔽掉協定包的構造與解析過程,推薦使用libnl等第三方庫)
3,在核心空間使用專用的核心API接口
4,支援多點傳播(是以支援“總線”式通信,可實作消息訂閱)
5,在核心端可用于程序上下文與中斷上下文
如何通過netlink擷取網卡資訊?
android 是如何通過netlink擷取網卡位址的?
不管是ip指令行還是Java的network接口,最終都是調用到ifaddrs.cpp -> getifaddrs
getifaddrs方法介紹
NetlinkConnection這個結構體是一個netlink的封裝類
重點看一下ReadResponses的實作過程
使用流程:
通過周遊拿到我們需要的内容,輸出即可。
SVC内聯安全封裝:
在接受消息的時候android源碼是采用recv去接受的消息
通過循環的方式去判斷結束位置。
但是recv這種函數很容易被hook,inlinehook recv ,recvfrom ,recvmsg
在方法執行完畢以後直接就可以處理參數二的傳回值。
在不直接使用系統提供的recv 以後,有兩種方式可以選擇。
- 方法1:
直接調用syscall函數,通過syscall函數進行切入到recv 。
這種方式可以更好的相容32和64位,但是可能被直接hook syscall這個函數入口 。
因為和裝置指紋相關的函數,是重點函數,側重安全。是以重點采用方法2
将syscall 彙編代碼嵌入到指定方法内部。
- 方法2:我們直接把recv換成svc内聯彙編代碼如下
相當于自己實作syscall (代碼摘抄自libc syscall)
使用的話也很簡單,導入函數頭就好。
32位:
64位:
将代碼替換成如下:
很不幸,報錯了,安卓8核心上使用了seccomop 過濾掉了svc 直接調用 recv
報錯的原因一句話
seccomp prevented call to disallowed arm system call 291
secomp簡介:
seccomp是Linux的一種安全機制,android 8.1以上使用了seccomp
主要功能是限制直接通過syscall去調用某些系統函數
seccomp的過濾模式有兩種(strict&filter)
第一種strict隻支援如下四種,如果一旦使用了其他的syscall 則會收到SIGKILL信号
read()
write()
exit()
rt_sigreturn
通過下面方式進行設定。
strict
filter(BPF)
Seccomp-bpf
bpf是一種過濾模式,隻有在linux高版本會存在該功能
當某程序調用了svc 首先會進入我們自己寫的bpf規則
通過我們自己的寫的規則,進行判斷該函數是否被運作調用。
常用的就是ptrace+seccomp去修改svc的參數内容&傳回值結果。
回到正文,不過還好,
在android底層 recv的實作是recvfom代碼如下
我們将svc調用号切換到recvform
程式完美運作起來,網卡擷取成功。