Android如何运作,第4部分


大家好! 我们花时间继续阅读有关内部Android设备的一系列文章。 在本文中,我将讨论Android启动过程,文件系统的内容,用户和应用程序数据的存储方式,root用户访问权限,Android构建的可移植性以及碎片问题。


系列文章:



配套


如前所述,Android体系结构围绕应用程序构建。 应用程序在系统的许多部分的设备中起着关键作用,构建活动和意图模型是为了应用程序的和谐交互,而Android安全模型基于应用程序的隔离。 并且,如果活动管理器负责协调应用程序组件之间的交互,则包管理器负责安装,更新和管理应用程序权限(包管理器-您可以使用pm命令在shell中调用它)。


顾名思义,“程序包管理器”在此级别通常称为程序包 。 软件包以APK格式分发(Android软件包)-特殊的zip档案。 每个软件包都有一个唯一标识此应用程序的名称 (也称为应用程序ID )(但不能标识其特定版本-相反,该软件包的不同版本的名称必须匹配,否则它们将被视为单独的软件包)。 程序包名称通常以反向DNS名称的形式书写-例如,YouTube应用程序使用程序包名称com.google.android.youtube 。 程序包名称通常与Java代码中使用的名称空间匹配,但Android不需要它(此外,应用程序的APK文件通常包含第三方库,该名称库与程序包名称完全没有关系,谁使用它们)。


组装期间的每个APK必须开发人员使用数字签名签名。 Android在安装应用程序时会检查此签名,并在更新已安装的应用程序时会另外比较用于签名新旧版本的公钥; 它们必须匹配,以确保新版本是由与旧版本相同的开发人员创建的。 (如果无法进行此检查,则攻击者可以使用与现有应用程序相同的名称创建一个程序包,通过“更新”该应用程序诱使用户安装它,并获得对该应用程序数据的访问权限。)


软件包本身的更新是安装新版本,而不是旧版本,其中保留了从用户那里收到的数据和权限。 您还可以将应用程序“降级”到旧版本,但是默认情况下,Android同时会擦除新版本保存的数据,因为旧版本可能无法使用新版本使用的数据格式。


正如我已经说过的,通常每个应用程序的代码都是在其自己的Unix用户(UID)下执行的,这可以确保它们相互隔离。 多个应用程序可能会明确要求 Android为它们使用通用的UID,这将允许它们直接访问彼此的文件,甚至(如果需要)在同一进程中运行。


尽管通常一个软件包对应一个APK文件,但Android支持由多个APK组成的软件包(这称为拆分APK或拆分APK )。 这是Android此类“魔术”功能的基础,例如动态加载其他应用程序模块( 动态功能模块 )和在Android Studio中即时运行 (自动更新正在运行的应用程序代码,而无需完全重新安装,并且在许多情况下,甚至无需重新启动)。



文件系统


文件系统设备是操作系统体系结构中最重要,最有趣的问题之一,Android中的文件系统设备也不例外。


首先要关注的是,使用哪种文件系统,即以哪种格式将文件内容保存在条件磁盘上(对于Android,通常是闪存和SD卡),以及系统内核如何提供支持。 。 Android中使用的Linux内核在某种程度上支持多种不同的文件系统-从Windows FAT和NTFS中使用的文件系统,以及臭名昭著的HFS +和现代APFS在达尔文中使用的文件系统-到计划9中的网络9pfs。 »对于Linux文件系统-例如,Btrfs和ext系列。


Linux的事实上的标准长期以来一直是ext4 ,大多数流行的Linux发行版默认使用ext4 。 因此,在Android中使用它的事实并不令人意外。 一些程序集(和一些发烧友)还使用F2FS (闪存友好文件系统),该文件专门针对闪存进行了优化(但是,由于其优势,目前尚不清楚 )。


其次,所谓的文件系统布局令人感兴趣-系统和用户文件夹以及文件在文件系统中的位置。 “常规Linux”中的文件系统布局应提供更详细的描述(例如,可以在此链接中找到 ); 我在这里只提及一些最重要的目录:


  • /home存储用户主文件夹; 在这里,程序会在各种隐藏文件夹( .cache.cache.config等)中存储特定于用户的设置,数据和缓存,
  • /boot存储Linux内核和initramfs映像(特殊启动文件系统),
  • /usr (调用/system会更合乎逻辑)存储系统本身的主要部分,包括库,可执行文件,配置文件以及资源-界面主题,图标,系统手册内容等,
  • /etc (调用/config会更合逻辑)存储系统范围的设置,
  • /dev存储设备文件和其他特殊文件(例如socket /dev/log ),
  • /var存储可变数据-日志,系统缓存,数据库内容等

Android使用相似但明显不同的文件系统布局。 以下是其中一些最重要的部分:


  • /data存储可变数据,
  • 内核和initramfs映像存储在单独的闪存分区中,该闪存分区无法安装在主文件系统上。
  • /system匹配/usr并存储系统,
  • /vendor -为该Android程序集的特定文件设计的/system的类似物,未包含在“标准” Android中,
  • /dev ,如“标准Linux”中一样,存储设备文件和其他特殊文件。

这些目录中最有趣的是/data/system/system的内容描述了系统,并包含其大部分组成文件。 /system位于闪存的单独部分,默认情况下以只读模式挂载; 通常,仅当系统更新时,其上的数据才会更改。 /data也位于单独的部分,描述了特定设备的可变状态,包括用户设置,已安装的应用程序及其数据,缓存等。 使用这种方案清除所有用户数据,即所谓的出厂重置,仅是清除数据部分的内容。 未触及的系统仍保留在“ 系统”部分中。


 # mount | grep /system /dev/block/mmcblk0p14 on /system type ext4 (ro,seclabel,relatime,data=ordered) # mount | grep /data /dev/block/mmcblk0p24 on /data type ext4 (rw,seclabel,nosuid,nodev,noatime,noauto_da_alloc,data=writeback) 

应用程序-即它们的APK,odex文件(提前编译的Java代码)和ELF库-安装在/system/app (对于系统附带的应用程序)或/data/app (对于用户安装)中应用程序)。 创建Android程序集时,将为每个预安装的应用程序分配一个名为/system/app/Terminal形式的文件夹,对于在安装过程中用户安装的应用程序,将创建以其包名开头的文件夹。 例如,YouTube应用程序保存在一个名为/data/app/com.google.android.youtube-bkJAtUtbTuzvAioW-LEStg==/的文件夹中。


关于此后缀

应用程序文件夹名称中的后缀是Base64中编码的16个随机字节。 使用此后缀可以防止其他应用程序“猜测”他们不应该知道的应用程序路径。 原则上,设备上安装的应用程序列表及其路径不是秘密-可以通过标准API获取 -但在某些情况下(即,对于Instant apps),对此数据的访问受到限制。


此后缀有另一个用途。 每次更新应用程序时,新的APK都会安装在带有新后缀的文件夹中,然后删除旧文件夹。 在8.0版Oreo之前,这是后缀的目的,而不是随机字节而是交替使用 -1-2 (例如,对于YouTube,为/data/app/com.google.android.youtube-2 )。


可以使用标准API或pm path org.example.packagename获取/system/app/data/app应用程序文件夹的完整路径,该pm path org.example.packagename可显示所有应用程序APK文件的路径。


 # pm path com.android.egg package:/system/app/EasterEgg/EasterEgg.apk 

由于预装的应用程序存储在系统部分 (我记得,其内容仅在系统更新时才更改),因此无法删除它们(相反,Android提供了“禁用”它们的功能)。 尽管如此,仍支持更新预安装的应用程序-在这种情况下,将在/data/app中为新版本创建一个文件夹,并且系统随附的版本仍在/system/app 。 在这种情况下,用户有机会“删除”该应用程序的更新,从而从/system/app返回到版本。


预安装的应用程序的另一个功能是它们可以接收特殊的“系统”权限 。 例如,第三方应用程序没有获得DELETE_PACKAGES权限,该权限允许您删除其他应用程序, REBOOT允许您重新启动系统,而READ_FRAME_BUFFER则允许直接访问屏幕内容。 这些权限具有签名保护级别 ,也就是说,尝试访问它们的应用程序必须使用与实现它们的应用程序或服务相同的密钥进行签名-在这种情况下,由于这些许可权是由系统实现的,因此对其进行签名的密钥Android版


为了存储可变数据,每个应用程序都在/data/data分配了一个文件夹(例如,对于YouTube,为/data/data/com.google.android.youtube )。 只有应用程序本身可以访问此文件夹-也就是说,只有该应用程序在其下启动的UID(如果该应用程序使用多个UID,或者如果多个应用程序使用一个公共UID,则所有操作都可能更加复杂)。 应用程序在此文件夹中保存设置,高速缓存(分别在shared_prefscache子文件夹中)以及所需的其他任何数据:


 # ls /data/data/com.google.android.youtube/ cache code_cache databases files lib no_backup shared_prefs # cat /data/data/com.google.android.youtube/shared_prefs/youtube.xml <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="user_account">username@gmail.com</string> <boolean name="h264_main_profile_supported7.1.2" value="true" /> <int name="last_manual_video_quality_selection_max" value="-2" /> <...> </map> 

系统知道cache文件夹的存在,如果没有足够的空间,可以自行清理它。 当您卸载该应用程序时,该应用程序的整个文件夹将被完全删除,并且该应用程序不会留下任何痕迹。 另外,两个用户都可以在设置中明确地执行操作:



分配给每个应用程序的数据存储称为内部存储。


此外,Android还具有另一种类型的存储-所谓的外部存储 (外部存储-此名称反映了最初的想法,即外部存储应位于插入手机的外部SD卡上)。 实际上,外部存储设备充当用户主文件夹的角色-文件,下载,音乐和图片等文件夹位于此处,文件管理器将其作为默认文件夹打开的外部存储设备,允许计算机在连接​​后访问外部存储设备的内容通过电缆。


 # ls /sdcard Alarms Download Podcasts Android Movies Ringtones Books Music Subtitles DCIM Notifications bluetooth Documents Pictures 

与内部存储不同,内部存储分为各个应用程序的文件夹,外部存储是一个“公共区域”:任何已获得用户适当许可的应用程序均具有完全访问权限。 正如我在上一篇文章中提到的那样,文件管理器之类的应用程序应该请求此权限。 对于大多数其他应用程序,最好将ACTION_GET_CONTENT操作与intent一起使用,使用户有机会在系统文件管理器中选择所需的文件。


许多应用程序倾向于将其一些内部文件保存在外部存储中,这些内部文件很大(例如,下载的图像和音频文件的缓存)。 为此,Android会将名称分配为Android/data/com.google.android.youtube的形式分配给外部存储文件夹中的应用程序。 该应用程序本身不需要访问整个外部存储器的权限即可访问此文件夹(因为其UID设置为该文件夹的所有者),但是任何其他具有此权限的应用程序都可以访问此文件夹,因此,值得使用仅用于存储公共和非关键数据。 当您卸载应用程序时,系统还将删除其在外部存储中的特殊文件夹; 但是,由应用程序在其特殊文件夹之外的外部存储器中创建的文件被认为属于用户,并且在删除创建它们的应用程序之后仍保留在原位。


正如我上面提到的,最初假定外部存储实际上位于外部SD卡上,因为那时SD卡的容量大大大于电话内置的内存容量(在HTC Dream中仅为256 MB,其中大约90兆字节分配给了数据部分)。 从那时起,许多情况发生了变化。 现代手机通常没有SD卡插槽,但移动标准安装了大量的内部存储器(例如,在Samsung Galaxy Note 9中,其最大存储容量为512 GB )。


因此,在现代Android中,内部存储器和外部存储器几乎总是位于内部存储器中。 外部存储器在文件系统中所处的实际路径采用/data/media/0的形式(为每个设备用户创建一个单独的外部存储器,并且路径中的数字与用户号相对应)。 出于兼容性目的,也可以通过/sdcard/mnt/sdcard/storage/self/primary/storage/emulated/0路径,以/mnt/runtime/开头的几个路径以及其他一些路径来访问外部存储。


另一方面,许多设备仍然具有SD卡插槽。 插入Android设备的SD卡可用作常规的外部驱动器(无需将其转换为系统的内部或外部存储设备)-将文件保存到其中,打开其中存储的文件,使用它将文件传输到其他设备等。 此外,Android允许您“借用” SD卡并在其上放置内部和外部存储(这称为借用存储- 采用的存储 )。 同时,系统重新格式化SD卡并对其内容进行加密-无法通过将SD卡连接到另一台设备来读取其中存储的数据。



例如,您可以在本文以及面向应用程序开发人员Android程序集创建者的官方文档中了解有关所有这些内容的更多信息。


载入中


计算机系统安全性的传统方法仅限于保护系统免受软件攻击。 人们认为, 如果攻击者可以物理访问计算机,那么该游戏已经丢失 :他可以完全访问存储在计算机上的任何数据。 为此,对于他来说,例如,在此计算机上运行由他控制的任意操作系统就足够了,从而允许他绕过“主要”权利系统施加的任何限制,或者直接将数据磁盘连接到另一台设备。 如果需要,攻击者可以使计算机处于可操作状态,但可以修补安装在其上的系统,安装任意后门,键盘记录程序等。


抵制软件攻击的重点在于Unix中限制用户权限的模型(以及Android中基于此限制的应用程序沙盒技术); Unix限制本身并不能保护系统免受用户进入服务器机房并获得对计算机的物理访问权限。 而且,如果可以并且应该保护严肃的多用户服务器免遭未经授权的个人计算机(特别是移动设备)的物理访问,则该方法根本不适用。


可以通过以下两种方法来尝试改善这种情况,使其免受攻击者获得对该设备的物理访问权:


  • 首先,可以对存储在磁盘上的数据进行加密 ,从而即使攻击者可以访问磁盘的内容 ,也可以防止攻击者获得对数据本身的访问权。
  • 其次,有可能以某种方式限制在设备上加载任意操作系统的能力 ,从而迫使攻击者通过已安装系统中的身份验证和授权过程。

Android中的安全启动模型正是与这两个保护区域相关联的。


验证启动


Android引导过程的设计是,一方面,它不允许攻击者在设备上下载任意操作系统,另一方面,它允许用户安装自定义的Android程序集(和其他系统)。


首先,与“台式”计算机不同,Android设备通常不允许用户(或攻击者)从外部介质启动; 相反,安装在设备上的引导程序(引导程序)将立即启动。 Bootloader是一个相对简单的程序,其任务(以正常模式加载时)包括:


  • 可信执行环境(例如ARM TrustZone)的初始化和配置,
  • 查找存储Linux内核映像和initramfs的内部存储器分区,
  • 验证其完整性(完整性)-否则,下载会因错误消息而中断-通过验证制造商的数字签名,
  • 将内核和initramfs加载到内存中,并将控制权转移给内核。

闪烁,解锁,快速启动和恢复


另外,bootloader支持用于更新和重新安装系统的其他功能。


-, (Android) , recovery . recovery, Android- , , Android recovery .


«» bootloader', — ( flashing ) . bootloader , fastboot mode ( bootloader mode), bootloader' fastboot ( fastboot Android SDK ).


bootloader' . , Samsung, bootloader'a (Loke) (Odin). Odin Samsung ( Odin), Heimdall .


bootloader' ( ), recovery Android, , :


 $ fastboot flash recovery recovery.img $ fastboot flash boot boot.img $ fastboot flash system system.img 

; : , , bootloader' Android, , , , .


, bootloader' (unlocking the bootloader, OEM unlock) — bootloader' recovery, ( ). Android, LineageOS ( CyanogenMod ), Paranoid Android , AOKP , OmniROM .


bootloader' - , ( data ) . , , (, Google ), — , .



recovery bootloader , .


bootloader' :



recovery, «» (flashaholics) — TWRP (Team Win Recovery Project). - «», zip-, :




Android ( file-based encryption ). ext4 , Linux ( fscrypt ), .


, data , , (credential encrypted storage). , , . , , .



credential encrypted storage Android device encrypted storage — , ( Trusted Execution Environment). , , , . , Direct Boot : ; ( ) device encrypted storage, , . , Direct Boot , , - .


Root


root- — « root» (UID 0, ). , root — Unix-, — — , .


, Android , root- . , « », Android « », root- «», :


  • — , APK ,
  • : -, email-, , , , , , ( activity intent', ),
  • (icon packs),
  • , ,
  • ( Android-) ,
  • , Android, .


, , , root- . root- ( ), Android root . , , Unix-; shell, adb shell , Unix- shell .


, , root :


  • -, root- Android — Android Studio QEMU, .
  • -, root- Android ( pre-rooted ROMs).
  • -, bootloader' root- Android , , su , bootloader.
  • , -, , , root-, ( root- ). , 2016 , root- Dirty Cow .

? , root- . , root-, , , . — , . , , system ( ).


, root- — , .


root-


With great power comes great responsibility.

, . , root- .


, , . , root- , , , root- . root, , , , — , , , ..


, Unix, Android , — . root- , , . , root- Android, .


, , root- , . , , , , , . , — , Google Pay ( Android Pay) — root- , .



, - Pokémon GO root- , , .


Google Play root-


Google Google Play Store Google Play Services , root- , Android , , , , . Play Store — ( , ) Android, . ( — , Amazon Android Fire OS — Echo, Fire TV, Fire Phone, Kindle Fire Tablet — Google). root- Android-.


, Google , root-, Google Play ( Open GApps ); Google , .


Device manufacturers work with Google to certify that Android devices with Google apps installed are secure and will run apps correctly. To be certified, a device must pass Android compatibility tests. If you are unable to add a Google Account on your Android device, your Android device software might not have passed Android compatibility tests, or the device manufacturer has not submitted the results to Google to seek approval. As a result, your device is uncertified. This means that your device might not be secure.

If you are a User wanting to use custom ROMs on your device, please register your device by submitting your Google Services Framework Android ID below.

root


«» Linux, Unix-, root- ( sudo su ) ( , Unix- root, ) (, ). , root-.


su Android Open Source Project , Unix- shell ( root), root-. su , , , .


, su . su , root-. , SuperSU ; Magisk .



Magisk


Magisk — , , /system , system ( systemless-ly ), «» Linux . Magisk Hide — root-, root- Magisk — - Google Pay, root- . Magisk Hide root-, SafetyNet Google.


, , Google Pay root- — root- . , root-, - Google Pay. , .


Magisk systemless- «» Magisk Modules , Magisk. , , root- Xposed ViPER , .


SoC,



, «», , — , — (, Wi-Fi ).


, Android- (system on a chip, SoC). — , , -, , LTE-, Bluetooth- Wi-Fi- .. — . , , , , , .


, , . , «», , , , . , , -, , , , .



— Android — SoC . , , — LTE- — . , ; , , .


SoC (, Qualcomm) Android- (, Sony LG), Android, Android Open Source Project. , Android, , , .


Android Android-. , Android. Android , , . .



, : Android — , . Android, .


, , , Android. .


-, . , . , , , , .


-, Android — developer experience (DX, user experience/UX). , Android, API — Android Framework, OpenGL/Vulkan — . , , , Android — , , .



Don't Stop Thinking About Tomorrow


Android- . , Google Nexus Pixel , Android. Android , , , .


, , Android, SoC. Android «» (, , Android-x86 RemixOS ). Android ChromeOS, Chromebook' Android- Linux- -. — Android — Anbox , Android- «» Linux-. (, Android- x86-, , Java, .)



, Android — , Android .


Android. , , . , , Android .


. 2017 Google Project Treble — , ( HAL, hardware abstraction layer) ( , ) . Treble , , , — — .


Treble . Treble (Sony, Nokia, OnePlus, Oppo, Xiaomi, Essential Vivo — Google) - Android Pie. Treble Essential Android Pie Essential Phone Android Pie. Android — - — , Treble, , SoC.


Treble . Java «write once, run everywhere» — Android- . Treble — , Android SoC. , , Treble. , Android- .




userspace Android: init, Zygote, Binder, props.

Source: https://habr.com/ru/post/zh-CN427431/


All Articles