在Android上切换root设备的GPS

5

从某个Android版本开始(我想是2.3.x),无论应用有什么权限,都不能通过API打开/关闭GPS。过去可以通过利用电源控制小部件中的漏洞来实现(请参见这里),但现在已修复。

假设我拥有root权限,我该怎样打开和关闭GPS呢?


编辑:这里是如何在jelly bean上获取读取日志权限的,这对于普通应用程序不再允许。我尝试使用类似的解决方案来获取WRITE_SECURE_SETTINGS权限以切换GPS,但它没有起作用。


编辑:到目前为止,我只找到了一个可行的解决方案:将应用转换为系统应用程序(可在这里找到一个有效的解决方案,即使在Android 4.2.1上也适用)。然而,我想到的是通过root权限从一开始就规避它,因为据我所知,root权限可以做任何事情。


@androiddeveloper 你对制作另一个(非常有限的)apk并将其安装到system/app感到多么舒适?这样可以授予apk所需的任何权限。这就是avast为其反盗版所做的事情。但是有一个问题,那就是卸载。 - A--C
@androiddeveloper:关于“作为root权限可以做任何事情,根据我所知。”这并不完全正确。Android权限与Linux权限是分开的。它们有一些重叠(例如,一些uid映射到某些Android权限),但通常您可以将它们视为两个单独的权限层。因此,仅具有Linux权限对Android权限没有太大帮助(因为它们是应用程序级实体,Linux对其一无所知)。 - Victor Ronin
@A--C 我知道这个解决方案,就像这里写的一样:http://stackoverflow.com/a/14850224/878126。问题是我想克服这种方法的缺点(比如卸载)。 - android developer
@Victor Ronin,你确定吗?我认为root权限是“所有权限之母”,可以完全控制一切。据我所知,它甚至可以替换ROM(尽管通常是通过引导加载程序完成的)。 - android developer
@androiddeveloper:要做到这一点,你需要修改Android操作系统代码,重新编译并上传到你的设备(这对最终用户来说不可行),或者你需要找到Android逻辑中的某些漏洞并利用它。我们讨论过的两种方法都属于逻辑漏洞的范畴。你正在尝试通过在低级别使用根权限的方式来授予高级别权限(例如,能够挂载系统分区进行写入或能够在运行时更改UID)。 - Victor Ronin
显示剩余7条评论
3个回答

3

我查看了一下Android源代码,发现以下代码:

 public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
            String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED);
            return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
        }

  /**
   * Thread-safe method for enabling or disabling a single location provider.
   * @param cr the content resolver to use
   * @param provider the location provider to enable or disable
   * @param enabled true if the provider should be enabled
   */
        public static final void setLocationProviderEnabled(ContentResolver cr,
                String provider, boolean enabled) {
            // to ensure thread safety, we write the provider name with a '+' or '-'
            // and let the SettingsProvider handle it rather than reading and modifying
            // the list of enabled providers.
            if (enabled) {
                provider = "+" + provider;
            } else {
                provider = "-" + provider;
            }
            putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider);
        }       

我相信,如果您拥有root访问权限,则可以读取和写入Settings.Secure。通过这种方式,您应该能够控制GPS(setLocationProviderEnabled)。
然而,据我了解,它不会关闭GPS硬件,只会忽略此位置提供程序。
我不知道有哪些接口可以与GPS通信并关闭硬件。但是,您还有另一个选择,即禁用负责GPS的内核模块(我不知道它的名称)。
更新1
我检查了Android(4.1)中WRITE_SECURE_SETTINGS的定义。在这里。
   <permission android:name="android.permission.WRITE_SECURE_SETTINGS"
        android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
        android:protectionLevel="signature|system|development"
        android:label="@string/permlab_writeSecureSettings"
        android:description="@string/permdesc_writeSecureSettings" />

基于“系统”级别。将其添加到您的应用程序清单中,将此应用程序复制到系统映像(您需要将其挂载为可写),然后您就可以开始使用了。
还有一件事。uid shell拥有此权限。
 <assign-permission name="android.permission.WRITE_SECURE_SETTINGS" uid="shell" />   

我记不太清楚,但有一种方法可以临时更改uid(如果您是root用户)。我在Android代码中看到过。所以,您可以将uid更改为shell,执行某些操作,然后再更改回来。

更新 2

我找到了这种更改uid的方法。

如果您下载AOSP,您可以在几个地方的本地库中找到它的使用方法:

./base/cmds/screenshot/screenshot.c

它会执行 setuid(AID_SHELL);

./native/cmds/dumpstate/dumpstate.c

setuid(AID_SHELL)

还有其他几个地方。

我认为您应该尝试一下,以获取具有WRITE_SECURE_SETTINGS权限的AID_SHELL组。

更新 3

关于细节,我不确定。我相信应该有一个用于GPS硬件的本地驱动程序和Unix设备。然而,在不同的设备上,它可能有不同的名称。

您可以尝试使用rmmod Linux命令删除某些模块。我相信它应该会禁用GPS。


问题是,即使在已经root的设备上,我仍无法获得WRITE_SECURE_SETTINGS权限。我尝试的命令是:"su -c pm grant android.permission.WRITE_SECURE_SETTINGS"。这个命令对于获取读取日志的权限很有效,但现在对于这个权限却不起作用了。一些应用程序声称成功实现了此操作。不知道它们是如何工作的。 - android developer
@androiddeveloper:我认为将这个信息包含在问题中是有意义的。我会看看WRITE_SECURE_SETTINGS发生了什么。 - Victor Ronin
那么我无法避免告诉(高级)用户将应用程序安装为系统应用程序吗?没有任何方法可以绕过此限制,即使具有应该能够执行所有操作的根权限?我认为作为系统应用程序,您不需要在清单中放置额外的标志以获取此权限。但是,我从未找到一种自动将应用程序转换为系统应用程序(在同一应用程序内部)的方法。 - android developer
你说的“如何实现”的线索是什么意思?我认为最好的想法是查看我提到的这两个文件,以了解它们在那里的使用方式。你需要创建一个本地库,并将此代码放入其中,并从Java代码中调用它。 - Victor Ronin
我很感激你的努力,但我只会为一个有效的解决方案或最合适的答案授予悬赏。 - android developer
显示剩余6条评论

2

无需系统应用,只需使用su命令启用高精度模式的GPS 只需使用

 Process proc=Runtime.getRuntime().exec(new String[]{"su",
"pm grant com.your_app_packagename android.permission.WRITE_SECURE_SETTINGS",
"settings put secure location_providers_allowed gps,network,wifi"});
 proc.waitFor();

请在后台线程上运行这些命令 :)

更多信息可以参考此链接这里


您能否详细阐述一下您的答案,并对您提供的解决方案进行更多描述? - abarisone
这些是需要在后台线程中运行的命令。第一条命令用于调用su,第二条命令用于授予安全权限,第三条命令用于打开高精度GPS。 - Dayvon

1

这个SO Question似乎是与该主题相关的最接近的问题。

在2.2版本之前存在一个漏洞利用程序,可以更改GPS设置。在2.3之后,似乎目前无法在没有用户干预的情况下完成。

以下是几次不成功尝试的答案/评论: - 如何在Android上以编程方式启用或禁用GPS? - https://dev59.com/Xm445IYBdhLWcg3wuspT#10004614

显然,使用BusyBox可以实现此目的,但我在网上找不到任何可靠的信息。来源:https://stackoverflow.com/a/14850224/238722

更新

答案中提到的与BusyBox相关的链接,包含可供下载的工作示例项目


1
即使在已经root的设备上,你也不能像获取其他权限一样轻易地获得该权限。你必须将应用程序作为系统应用程序才行。 - android developer
这是我从帖子和快速在线研究中收集到的信息。显然,Android操作系统只允许系统应用程序进行该更改。 - Jesse
请问你能否尝试寻找一个 BusyBox 的解决方案吗? - android developer
@androiddeveloper 关于BusyBox的答案,有一个可供下载的工作样例项目(http://rapidshare.com/files/1458124346/GPSToggler-20130222.7z)。我没有Android设备,因此无法测试;不过发布者确认它可以在4.1.2上运行。 - Jesse
一些ROM实际上允许使用不仅限于系统应用程序的安全性。此外,没有必要要求最终用户将模块安装到/system/app中,您可以在后台完成。但是,您仍然需要root访问权限,并且必须重新启动手机。为了获得一种通用解决方案,您确实需要a)root,b)系统APK和c)重新启动。 - OGP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接