Accessing hidden System Service APIs in Android

本文介绍了如何在Android中访问隐藏的系统服务API,特别是如何收集GPS卫星信息。通过直接与LocationManager服务交互,可以绕过公共API限制,获取卫星状态更新等详细信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Accessing hidden System Service APIs in Android

转自:http://blog.codetastrophe.com/2008/12/accessing-hidden-system-service-apis-in.html

 

Android's SDK allows developers to do a lot with the platform, but there are some interesting capabilities of the system that aren't accessible through the public API. It's still possible to access these capabilities with a little bit of work and the Android source code, available from http://source.android.com. The source code I wrote is  here.

The capability I wanted to expose is collecting GPS satellite information - data on the satellites (SVs - space vehicles) themselves. There are hidden methods in the LocationManager service API to set up callbacks to collect this data, but they aren't accessible through the public API. I considered the various ways I could get this data and the easiest one I came up with is to send messages directly to the  LocationManager service itself using the IPC interface.

LocationManager and LocationManagerService

The  LocationManager API in the  android.locationnamespace is the public interface to the LocationManagerService, in  com.android.server. The service runs in a separate process, and the API communicates with it using Android's IPC mechanism ( Binder). When an Android application wants to communicate with the LocationManagerService, it uses this API call to get a reference to the API object:
 
Normally, an application will then use the  LocationManagerAPI to register for location events (via requestLocationUpdates()) and then use the data to do really fun and interesting things, like  this.
If you dig into the  LocationManager source code, you'll see that there's a method called registerGpsStatusListener(). This sets up a listener that's able to get updates on GPS satellite information – PRNs, elevations, azimuths, etc, of each of the satellites in view of the GPS. This is what I want. Unfortunately, this method, as well as the argument type ( GpsStatusListenerTransport), aren't visible in the android.jar that comes with the SDK. It's still possible to get at this information by communicating directly with the LocationManagerService itself.

The APIs available in the Android SDK communicate with system services using IPC. Specifically, they use interfaces defined with  AIDL to communicate with the service. The AIDL specifications for the service IPC API's isn't available in the SDK, but you can get them from the Android source code. The AIDL is used to generate a client stub that Java classes can use to send messages to and receive messages from the service.

Accessing LocationManagerService directly

The class in  LocationManager that communicates with the LocationManagerService is  GpsStatusListenerTransport. This is an extension of the  IGpsStatusListener.Stub class, which was generated from an AIDL specification – IGpsStatusListener.aidl. It's possible to copy IGpsStatusListener.aidl from the Android source code and add to your project to generate the IGpsListenerStatus.Stub class. This project can then use this to communicate directly with the service that implements that interface.
IGpsStatusListener isn't the only AIDL interface we'll need –  ILocationManager.aidl,  ILocationListener.aidl, and Address.aidl are also needed to do what we want. Once these classes are available in our project (I put them in the android.location namespace to avoid changing the code, but it doesn't really matter which namespace they belong to). Once these interfaces are available to our project, it's really easy to get what we want.

While it is possible to write a totally new client for the LocationManagerService using the AIDL interfaces, it's actually easier for us to re-use an existing client. Setting up a new connection involves a bunch of lines of code and my carpal tunnels hate when I write too much code. The easy way is to use the Java reflection API to get the handle to the system service:
 
Accessing private fields like this in Java is generally frowned upon in production code, but we're hackers and we want the data and we can do whatever we want to get it and the establishment can't stop us.

So now that we have access to the  ILocationManager API, we can see that there is an  addGpsStatusListener()method we can call to add a listener that retrieves the GPS satellite status updates. This takes an  IGpsStatusListenerobject, which we can create by instantiating a class that extends  IGpsStatusListener.stub. Passing that object to addGpsStatusListener() will result in us getting onSvStatusChanged() callbacks with the satellite status. Nice.

Before we get any of this spiffy satellite info, the GPS must be enabled. In my sample app, I used the regular LocationManager API to do this by adding a LocationListener. The result of all of my efforts is this useless and boring application that shows some information about some satellites:

Oops...

If you start digging into the service code, you might notice that no permissions are required to add a listener for GPS status updates. This is a minor and low-risk information leak vulnerability. Applications shouldn't have access to GPS location data unless they have the correct permission. If an application creates a service that listens for GPS status updates (but not GPS location updates, which require the ACCESS_FINE_LOCATION permission), it will get these updates when any other application turns on the GPS. It's possible, with some fancy math, to determine the location of the phone with this data. You'll need to know the exact time, the relative locations of the GPS satellites to the user, and the absolute locations of the GPS satellites in space at that time. The time and relative locations can come from the phone, and the precise locations of the satellites can be found at http://www.navcen.uscg.gov/GPS/almanacs.htm. I'll leave doing the fancy math as an exercise to the reader.
Update: Proposed patch to add permission check, http://review.source.android.com/5124.

 

### 处理 Android 中 `OpenSSLSocketImpl.setUseSessionTickets` 方法反射调用被灰名单限制 在 Android P (API level 28) 和更高版本中,Google 对反射 API 的访问进行了严格控制,引入了灰名单机制来阻止应用程序通过反射访问某些内部类和方法。对于 `OpenSSLSocketImpl.setUseSessionTickets` 这样的情况,可以考虑以下几种解决方案: #### 使用 Conscrypt 库替代原生 SSL 实现 Conscrypt 是 Google 开发的一个高性能 TLS/SSL 提供者库,支持更广泛的加密算法并提供更好的性能。可以通过集成此库来替换默认的 OpenSSL 实现。 ```java // 添加依赖项至 build.gradle 文件 dependencies { implementation 'org.conscrypt:conscrypt-android:2.5.1' } // 初始化 conscrypt provider Security.insertProviderAt(Conscrypt.newProvider(), 1); ``` 这样做的好处是可以直接利用 Conscrypt 提供的功能而无需担心反射带来的兼容性和安全性问题[^4]。 #### 动态加载特定版本下的实现 如果确实需要保持原有的逻辑,则可以根据不同的 SDK 版本动态判断是否执行该操作,在较新的系统上跳过对受限接口的操作。 ```java if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { try { final Method method = socket.getClass().getMethod("setUseSessionTickets", boolean.class); method.invoke(socket, true); } catch (Exception e) { Log.w(TAG, "Failed to invoke setUseSessionTickets via reflection.", e); } } ``` 这种方法能够有效规避高版本系统的限制,同时保留低版本设备上的功能[^2]。 #### 尝试其他方式设置 Session Tickets 行为 除了直接修改 `OpenSSLSocketImpl` 属性外,还可以探索是否有其他途径影响 session ticket 的行为,比如调整连接参数或配置文件中的选项等。不过这通常取决于具体的应用场景和技术栈[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值