从”茄子快传”看应用程序如何获取手机已安装程序的apk文件

2024-02-28 00:40

本文主要是介绍从”茄子快传”看应用程序如何获取手机已安装程序的apk文件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

       ”茄子快传”是联想开发的一款近距离文件共享软件,它通过wifi-direct(速度飞快,不需要联网)或者普通的网络(速度慢)在不同手机间传递文件。不知为何,它就火了起来,火的也飞快。其中,共享传输已安装程序文件apk这一功能引起了我强烈的兴趣。

 

 

 

        我们知道android对每个应用的权限做了很苛刻的控制,每个应用程序有自己的用户id,每个应用程序只能访问自己的数据,比如程序com.android.calculator计算器程序只被允许访问/data/data/com.android.calculator目录下的数据,且该程序的所有数据也都保存在该目录下。同时当程序被安装时,系统会将安装文件apk拷贝到/data/app目录下。那茄子快船作为普通的程序,它怎么具有读取/data/app下apk文件的权限的呢?如果它不是读取该目录下的apk文件,那程序的安装文件apk它是从哪里获取到的呢?

         于是,我开始充分发挥主观能动性,开始不停思考它的实现方法,并有了如下想法和实践。

 

实现原理分析及实践

 

 

1)  实现方式一:

 

        一开始我很坚定的认为茄子快船肯定不是读取手机里的程序的安装文件apk。我认为它只不过读取了系统所有已安装程序的信息,然后根据程序的包名在网络服务器上搜索对应的安装文件(apk文件)并下载,然后再通过网络传送给其他手机。

 

       为了验证这一猜测,我猜想只要我断了网络,它自然没法做程序搜索,那么肯定就没法传送文件了。于是,我做了如下实验:

我断掉自己手机的所有网络(2g/wifi),然后再使用这个功能选择某一程序并选择发送给其他手机,结果发现它仍然工作。

 

        于是我接着猜测,这个apk文件很有可能在程序安装的时候就从服务器下载到茄子快船程序的目录里了,因此在发送的时候它不再需要网络了。于是我又做了另外一个实验:

 

         我断掉我所有的网络,然后通过adb安装某一程序,这样在安装的过程中,茄子快船肯定是没法从网络上下载相应的apk文件的。但是出人意料的是,茄子快船仍然成功传送了我刚刚安装的程序对应的安装文件。

2)  最后我不得不相信它确实是通过读取/data/app下的apk文件来传送安装程序的。

          那我开始想了,难道/data/app下的文件本身确实是可读的。我不信邪,我开始查看这些文件的权限信息。           于是我又开始了下面的实验。为了模拟一般程序的权限,我用shell用户来执行读取/data/app/下的文件以      验证普通程序是否有相关权限。

 

itleaks@Itleaks/tmp$ adb shell
1|shell@htc:/ $ ls /data -al                                                
opendir failed, Permission denied
shell@htc:/ $ ls /data/app -al
opendir failed, Permission denied
#没有权限
1|shell@htc:/ $

 

 

          从上面可以看出一般的程序应该是没法直接读取/data/app下面的文件啊,不对啊?只好出绝招了,我接着又使用root用户来查看目录的具体权限:

 

 

1|shell@htc:/ $ su root
root@htc:/ # ls /data -al
ls /data -al
drwxrwx--x system   system            2014-06-19 20:40 app

 

 

 

           到此,我终于明白了,原来/data/app目录对于其他用户具备-x权限。也就是说普通程序可以进入该目录,但是没法读取该目录文件里的内容,即没法查询该目录下有哪些文件。这也是为什么我们执行ls /data/app –al失败的原因,因为这个命令会读取目录文件,自然需要该目录对其他用户开放-r权限。在-x权限下,只需该目录下的文件对第三方程序开发-r权限,那么程序就可通过具体文件名称来读取该目录的对应文件。于是迫不及待的想看该目录下的文件权限属性。

 

 

root@htc:/ # cd /data/app
cd /data/app
root@htc:/data/app # ls -al
ls -al
-rw-r--r-- system   system    5784942 2014-05-18 15:22 cn.lvye.hd-1.apk
-rw-r--r-- system   system   16056547 2014-05-16 21:11 cn.whonow.whonow-1.apk

 

 

 

          果然,目录下的apk对于其他用户有-r权限。于是我重新模拟普通程序用户的权限开始如下的实验。

 

 

root@htc:/data/app # exit
exit
#回到shell用户
shell@htc:/ $ ls /data/app
opendir failed, Permission denied
shell@htc:/ $ cd /data/app
#进入/data/app目录成功
shell@htc:/data/app $ cd -
/
1|shell@htc:/ $ ls /data/app/cn.lvye.hd-1.apk -al
-rw-r--r-- system   system    5784942 2014-05-18 15:22 cn.lvye.hd-1.apk
#读取apk文件成功

 

 

 

          从上面可以看出,shell用户已经成功读取到cn.lvye.hd-1.apk文件的信息。但是还有一个问题,我们刚刚是通过root用户来查看/data/app目录下的apk文件的名字的,对于普通用户来说,它是没法知道/data/app下有哪些文件的,那它是如何知道某一个程序的安装文件名的呢?其实这个很简单,已安装程序的PackageInfo.sourceDir信息会指明该程序的安装程序名称及路径。具体获取代码如下:

 

public class MainActivity extends Activity {private static final String TAG = "Itleaks test";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);readFirstApkFile();}private void readFirstApkFile() {// TODO Auto-generated method stubList<PackageInfo> installedList = this.getPackageManager().getInstalledPackages(0);int installedListSize = installedList.size();ApplicationInfo firstApplicationInfo = null;for(int i = 0; i < installedListSize; i++) {PackageInfo info = installedList.get(i);ApplicationInfo aInfo = info.applicationInfo;Log.d(TAG, "application source dir " + aInfo.sourceDir); if (firstApplicationInfo == null) {firstApplicationInfo = aInfo;}}File file = new File(firstApplicationInfo.sourceDir);if (!file.exists()) {Log.e(TAG, "package:" + firstApplicationInfo.packageName+ " Apk file " + firstApplicationInfo.sourceDir + " doesn't exist");} else {FileInputStream in = null;try {in = new FileInputStream(file);int size;try {size = in.available();Log.d(TAG, "Apk file " + firstApplicationInfo.sourceDir + " size:" + size);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
}

 

 

 

         对于乐视lvye这个程序,其sourceDir为/data/app/cn.lvye.hd-1.apk,有了这个文件路径,普通程序就可以通过一般的文件读取操作来读取该文件了。


 

附录:

 

         大家可以在github上下载到文中的源码及apk文件:

         https://github.com/itleaks/apkfileshare

/********************************

* 本文来自博客  “爱踢门”

* 转载请标明出处:http://blog.csdn.net/itleaks

******************************************/

这篇关于从”茄子快传”看应用程序如何获取手机已安装程序的apk文件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/754017

相关文章

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR

cell phone teardown 手机拆卸

tweezer 镊子 screwdriver 螺丝刀 opening tool 开口工具 repair 修理 battery 电池 rear panel 后盖 front and rear cameras 前后摄像头 volume button board 音量键线路板 headphone jack 耳机孔 a cracked screen 破裂屏 otherwise non-functiona

JS和jQuery获取节点的兄弟,父级,子级元素

原文转自http://blog.csdn.net/duanshuyong/article/details/7562423 先说一下JS的获取方法,其要比JQUERY的方法麻烦很多,后面以JQUERY的方法作对比。 JS的方法会比JQUERY麻烦很多,主要则是因为FF浏览器,FF浏览器会把你的换行也当最DOM元素。 <div id="test"><div></div><div></div

vcpkg子包路径批量获取

获取vcpkg 子包的路径,并拼接为set(CMAKE_PREFIX_PATH “拼接路径” ) import osdef find_directories_with_subdirs(root_dir):# 构建根目录下的 "packages" 文件夹路径root_packages_dir = os.path.join(root_dir, "packages")# 如果 "packages"

Weex入门教程之4,获取当前全局环境变量和配置信息(屏幕高度、宽度等)

$getConfig() 获取当前全局环境变量和配置信息。 Returns: config (object): 配置对象;bundleUrl (string): bundle 的 url;debug (boolean): 是否是调试模式;env (object): 环境对象; weexVersion (string): Weex sdk 版本;appName (string): 应用名字;

MFC中App,Doc,MainFrame,View各指针的互相获取

纸上得来终觉浅,为了熟悉获取方法,我建了个SDI。 首先说明这四个类的执行顺序是App->Doc->Main->View 另外添加CDialog类获得各个指针的方法。 多文档的获取有点小区别,有时间也总结一下。 //  App void CSDIApp::OnApp() {      //  App      //  Doc     CDocument *pD

android两种日志获取log4j

android   log4j 加载日志使用方法; 先上图: 有两种方式: 1:直接使用架包 加载(两个都要使用); 架包:android-logging-log4j-1.0.3.jar 、log4j-1.2.15.jar  (说明:也可以使用架包:log4j-1.2.17.jar)  2:对架包输入日志的二次封装使用; 1:直接使用 log4j 日志框架获取日志信息: A:配置 日志 文

17 通过ref代替DOM用来获取元素和组件的引用

重点 ref :官网给出的解释是: ref: 用于注册对元素或子组件的引用。引用将在父组件的$refs 对象下注册。如果在普通DOM元素上使用,则引用将是该元素;如果在子组件上使用,则引用将是组件实例: <!-- vm.$refs.p will be the DOM node --><p ref="p">hello</p><!-- vm.$refs.child will be the c

react笔记 8-19 事件对象、获取dom元素、双向绑定

1、事件对象event 通过事件的event对象获取它的dom元素 run=(event)=>{event.target.style="background:yellowgreen" //event的父级为他本身event.target.getAttribute("aid") //这样便获取到了它的自定义属性aid}render() {return (<div><h2>{