저자 Summit 계정: windy_ll
Android 보안에 ebpf 적용: 바인더와 결합하여 동작 검사 샌드박스 완성(1부) 1. IPC에 대한 간략한 소개
IPC는 Inter-Process Communication의 약어로, 프로세스 간 통신 또는 크로스 프로세스 통신을 의미합니다. 두 프로세스 간의 데이터 교환 프로세스를 말합니다.
Android에는 언제 프로세스 간 통신이 필요합니까? Android가 시스템 서비스를 요청할 때 휴대폰 주소록 액세스, 위치 획득 등과 같은 크로스 프로세스 통신이 필요합니다. 이 문서의 목표는 이 동작을 캡처하기 위한 간단한 샌드박스를 구현하는 것입니다
2.바인더에 대한 간략한 소개
Binder는 Android의 크로스 프로세스 통신 형태로, IPC의 구체적인 구현 방식으로 이해될 수 있습니다
3. ServiceManager에 대한 간략한 소개
ServiceManager는 Android에서 매우 중요한 시스템 서비스입니다. 이름에서 알 수 있듯이 시스템 서비스를 관리하는 데 사용됩니다.
ServiceManager는 init 프로세스에 의해 시작됩니다ServiceManager는 서비스 등록 및 검색, 프로세스 간 통신, 시스템 서비스 시작 및 활성화, 시스템 서비스 목록 인스턴스 제공 등의 기능을 담당합니다
바인더 드라이버는 기본 통신 세부 사항을 결정하므로 ServiceManager는 탐색과 동일하며 특정 통신에 이동 방법, 목적지 등을 알려줍니다.
4. 통신 분석 4.1 클라이언트 호출 JAVA 계층 분석
WifiManager 클래스의 getConnectInfo 함수(이 함수는 Wi-Fi 정보를 얻음)를 분석의 예로 사용하세요
Ctrl+왼쪽 클릭하여 참조를 보면 오른쪽에 표시된 것처럼 해당 함수가 .wifi.WifiManager 클래스에 정의되어 있음을 확인할 수 있습니다.
위 그림에서 볼 수 있듯이 getConnectInfo 함수의 특정 코드에는 thrownewRuntimeException("Stub!");이라는 한 문장만 있는데, 이는 이 함수가 ROM의 동일한 클래스에 의해 대체되고 실행된다는 것을 알려줍니다. 여기에 정의된 것은 컴파일에 필요합니다(PS: 참고용). Android 소스 코드의 Frameworks/base/wifi/java/amdroid/net/wifi 디렉토리에서 이 클래스를 찾은 다음 함수의 특정 구현을 찾을 수 있습니다. 오른쪽에 표시된 대로:
이 함수는 IWifiManager의 getConnectionInfo 함수를 호출하는 것을 볼 수 있습니다. Frameworks/base/wifi/java/amdroid/net/wifi 디렉토리에서 IWifiManager.aidl 파일을 찾을 수 있습니다. getConnectionInfo 함수는 그림과 같이aidl에 정의되어 있습니다. 오른쪽:
여기서 개념을 소개해야 합니다---AIDL AIDL은 크로스 프로세스 함수 호출을 실현하기 위해 안드로이드 서비스의 소켓을 노출하는 데 사용되는 안드로이드의 소켓 언어입니다. AIDL은 컴파일할 때 Stub과 Proxy라는 두 가지 클래스를 생성합니다. Stub 클래스는 서버측 표현 계층의 표현이고, Proxy는 클라이언트가 얻은 인스턴스입니다. Android는 이러한 프록시-스텁
디자인 패턴을 통해 IPC를 구현합니다.
아래에aidl 파일을 작성한 후 해당 Java 코드를 생성하여 호출이 어떻게 구현되는지 확인합니다. 먼저 Android Studio에서 임의의 프로젝트를 찾은 다음 오른쪽과 같이 새 ADL 파일을 만듭니다.
이후 Build->MakeProbject를 생성할 수 있습니다. 생성된 경로는 오른쪽과 같이 build/generated/aidl_source_output_dir/debug/out/package 이름에 있습니다.
생성된 Java 파일을 관찰하면 Proxy 클래스가 이미 생성되어 있음을 알 수 있습니다. Proxy 클래스에서는 오른쪽 그림과 같이 우리가 정의한 함수를 찾을 수 있습니다.
이 함수를 자세히 분석해 보겠습니다. 먼저 acquire 함수를 통해 Parcel 인스턴스를 생성한 다음 Parcel의 write 시리즈 함수를 호출하여 쓰기 작업을 수행하지만 IBinder의 transact 함수를 호출하여 함수를 추적합니다. 분석된 Java 파일은 오른쪽에 표시된 대로 Frameworks/base/core/java/android/os 디렉터리에서 찾을 수 있습니다.
IBinder는 트랜잭션 메소드를 정의하는 소켓 Linux 삭제 명령이라는 것을 알 수 있습니다. 이 메소드에는 4개의 매개변수가 있습니다. 첫 번째 매개변수 코드는 서버가 이 번호를 수신한 후 찾아냅니다. Stub 클래스의 정적 변수를 사용하면 어떤 함수가 호출되는지 파싱할 수 있습니다. 두 번째와 세 번째 매개변수인 _data 및 _reply는 전달된 매개변수와 반환된 값으로, 모두 직렬화된 데이터
Android Linux 커널 계층입니다. 매개변수 플래그는 결과를 차단하고 기다려야 하는지 여부를 나타내며, 0은 차단하고 기다리는 것을 의미하고, 1은 즉시 반환을 의미합니다.
전역 검색 후 동일한 디렉터리에 있는 BinderProxy 클래스가 이 소켓을 구현하는 것을 찾을 수 있습니다. (추신: 동일한 디렉터리에 이 소켓을 구현하는 Binder 클래스도 있다는 점에 주목할 가치가 있지만 Binder 클래스는 클라이언트 구현이 아닌 서버 측 구현), 오른쪽 그림과 같이:
이 함수를 분석한 결과 마침내 transactNative 함수로 이동하는 것을 확인할 수 있습니다. 이 시점에서 IPC 통신 클라이언트 Java 계층에 대한 분석이 완료되었습니다
4.2 클라이언트 호출 네이티브 레이어 분석
transactNative 함수를 전역적으로 검색하면 오른쪽에 표시된 것처럼 해당 함수가 기본 레이어에 정보를 등록하는 것을 확인할 수 있습니다.
android_os_BinderProxy_transact 함수를 추적하면 오른쪽에 표시된 대로 함수가 먼저 getBPNativeData(env,obj)->mObject.get()을 통해 BpBinder 객체를 얻은 다음 BpBinder 트랜잭션 함수를 호출하는 것을 확인할 수 있습니다.
계속해서 따라가면 오른쪽에 표시된 대로 IPCThreadState의 트랜잭션 기능에 들어간 것을 확인할 수 있습니다.
다음으로, writeTransactionData 함수가 먼저 호출되는 것을 볼 수 있습니다. 이 함수는 바인더_트랜잭션_데이터 구조를 채우고 이를 바인더 드라이버로 보낼 준비를 하는 데 사용됩니다. 그런 다음 오른쪽에 표시된 대로 waitForResponse를 호출하여 반환을 기다립니다.
waitForResponse 함수에 이어 이 함수에서 가장 중요한 것은 talkWithDriver 함수를 호출하는 것임을 알 수 있습니다. talkWithDriver 함수를 분석해 보면 오른쪽과 같이 최종적으로 ioctl이 호출되는 것을 알 수 있습니다.
지금까지 클라이언트 측 네이티브 레이어 분석이 완료되었습니다
4.3 커널 계층 분석(바인더 드라이버 분석)
이 시점에서Android Linux 커널 레이어에서 ebpf 프로그램이 데이터 형식을 캡처하고 구문 분석하기 시작할 수 있습니다
사용자 계층이 ioctl을 호출하면 커널 상태로 들어가 바인더_ioctl 커널 함수에 들어갑니다. (ps: 해당 설명자는 커널 장치 소스 코드의 바인더.c에서 찾을 수 있습니다. 바인더_ioctl 함수를 분석하면 찾을 수 있습니다. 이 함수의 주요 기능은 두 프로세스 간에 데이터를 전송하기 위한 통신 데이터 ioctl 명령은 BINDER_WRITE_READ입니다. 이 명령이 발생하면 오른쪽에 표시된 대로 바인더_ioctl_write_read 함수가 호출됩니다.
binder_ioctl_write_read 함수에 따르면, 이 함수는 먼저 unsignedlong 유형 arg 매개변수가 가리키는 주소 값을 바인더_write_read 구조로 읽는다는 것을 알 수 있습니다. 이는 ioctl 명령이 BINDER_WRITE_READ일 때 전달된 매개변수가 다음을 가리키는 포인터임을 나타냅니다. 오른쪽에 표시된 것처럼inder_write_read 구조:
커널 상태 분석은 여기에서 완료할 수 있지만 우리는 이미 원하는 데이터, 즉 바인더_write_read 구조를 관찰했습니다. 아래와 같이 이 구조의 정의를 살펴볼 수 있습니다.
으아악
이 구조는 프로세스 간 통신 중에 전송되는 데이터를 설명하는 데 사용됩니다. 클라이언트에서 서버로 전송되는 통신 패킷을 읽을 때 write_size, write_consumed, write_buffer만 주의하면 됩니다. 이 필드에는 바인더_트랜잭션_데이터 구조가 포함되어 있습니다. 이 구조는 기본 레이어 writeTransactionData 함수에 채워져 있습니다. 그 중 write_buffer 및 read_buffer가 가리키는 데이터 구조는 대략 다음과 같습니다.
일반적으로 드라이버는 여러 명령과 주소 조합을 한 번에 전달하며, 바인더_트랜잭션_데이터 구조에 해당하는 명령을 찾아야 합니다. 바인더.h 헤더 파일에서 드라이버가 정의한 모든 명령을 찾을 수 있습니다(+ /refs /heads/android-mainline/include/uapi/linux/android/binder.h), 오른쪽에 표시된 대로:
可以发觉,BC_TRANSACTION和BC_REPLY指令都对应着binder_transaction_data结构体参数,但我们只须要顾客端发往驱动的数据包,所以我们只须要BC_TRANSACTION指令对应的参数即可
经过前面的剖析,我们找到了我们须要的核心数据---binder_transaction_data结构体,现今来看一下该结构体的定义,定义如下:
<em style="cursor: pointer;font-size: 12px"> 复制代码</em><em style="cursor: pointer;font-size: 12px"> 隐藏代码<br></em><code><span>struct</span> <span>binder_transaction_data</span> {<br> <span>union</span> {<br> __u32 handle;<br> <span>binder_uintptr_t</span> ptr;<br> } target; <span>/* 该事务的目标对象 */</span><br> <span>binder_uintptr_t</span> cookie; <span>/* 只有当事务是由Binder驱动传递给用户空间时,cookie才有意思,它的值是处理该事务的Server位于C++层的本地Binder对象 */</span><br> __u32 code; <span>/* 方法编号 */</span><br> __u32 flags;<br> <span>pid_t</span> sender_pid;<br> <span>uid_t</span> sender_euid;<br> <span>binder_size_t</span> data_size; <span>/* 数据长度 */</span><br> <span>binder_size_t</span> offsets_size; <span>/* 若包含对象,对象的数据大小 */</span><br> <span>union</span> {<br> <span>struct</span> {<br> <span>binder_uintptr_t</span> buffer; <span>/* 参数地址 */</span><br> <span>binder_uintptr_t</span> offsets; <span>/* 参数对象地址 */</span><br> } ptr;<br> __u8 buf[<span>8</span>];<br> } data; <span>/* 数据 */</span><br>};</code>
有了该数据结构linux安装,我们就可以晓得顾客端调用服务端的函数的函数、参数等数据了
五、实现疗效
PS:整套系统用于商业,就不做开源处理了,这儿只给出核心结构体复印的截图,就不再发后端的截图了
读取手机通信录(ps:这儿读取下来的数据采用了Toast复印的,所以将捕捉到的Toast相应的通讯包也一起复印了下来,下同):
获取地理位置:
获取wifi信息:
六、其他
里面当然我们只剖析到了发送部份,反过来,虽然我们也可以读取返回包甚至于更改返回包,就可用于对风控的对抗,比如在内核态中更改APP恳求的设备标示信息(其实前提是app走系统提供的驱动通讯),亦或则用于逆向的工作,比如过root检查等等。
这部份验证代码就暂不放下来了,感兴趣的可以自己实现一下
-官方峰会
公众号设置“星标”,您不会错过新的消息通知
如开放注册、精华文章和周边活动等公告
위 내용은 android linux 커널 계층 Android 크로스 프로세스 통신: IPC, Binder 및 ServiceManager 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!