About Android

Android is a mobile operating system based on a modified and customized version of the Linux kernel and other open-source software.

Android is the world’s most widely used mobile operating system, powering over 72.1% of smartphones globally. Its open-source nature allows manufacturers to customize and enhance the user experience, leading to diverse variations like Samsung’s One UI and Xiaomi’s MIUI.

With millions of apps available on the Google Play Store, Android’s primary app marketplace, users have access to a vast ecosystem of applications. The Google Play Store performs rigorous security checks on these applications to ensure they are safe for users.

Additionally, unlike iOS, Android permits the installation of apps from third-party sources, increasing flexibility and contributing to its widespread adoption but also posing security concerns as these sources are not always trusted.

Beyond smartphones, Android has evolved to power a wide range of smart devices, including smartwatches, TVs, cars, VR headsets, and IoT devices, showcasing its versatility and extensive reach in the tech world.

Android Architecture

Android architecture consists of several layers that support the functioning and development of Android applications.

Among all the components, the Linux Kernel provides the main functionality of operating system functions to smartphones. Android Runtime (ART) provides a platform for running Android applications

1.⠀Linux kernel

The foundational layer that acts as an abstraction layer between the hardware and the rest of the software stack. It manages and controls hardware components like the microphone, Bluetooth, camera, Wi-Fi, audio, and more via drivers.

This layer provides core services such as security, memory management, process management, and networking. It supports multiple CPU architectures, such as ARM, x86, and MIPS, and both 32-bit and 64-bit architectures.

During the development process, applications are configured to run on a specific version of the Android Runtime/API. This configuration is specified in the AndroidManifest.xml file using the minSdkVersion attribute.

Android APIs

The API specifications change with every new Android release, such as Android 10 or 11. Each new version/API offers critical bug fixes, security patches, and new features.

This view shows the percentage of devices running each specific version of Android.

Lower SDK/Android versions are more susceptible to security issues and vulnerabilities, making them prone to a variety of old attacks.

The higher, the better, But developers want to include the most customers possible!

shows the cumulative percentage of devices running each version of Android.

To know more about each API version

2.⠀Hardware abstraction layer “HAL”

It allows applications to access hardware components irrespective of the device manufacturer or type and independent of the programming language being used. It acts as an interface between applications and the hardware.

HAL Unifying access by allowing applications to access hardware components such as the camera, microphone, GPS, Bluetooth, and touch drivers without needing specific built-in drivers or manufacturer details.

New/Upcoming HAL Types:

  • Automotive: Android Auto, Apple CarPlay
  • IoT:
    ⠀↬⠀Fitness Watches & Devices
    ⠀↬⠀Smart Home Devices (Alexa, Google Home)
  • Gaming Peripherals
  • VR

3.⠀Libraries: Native C/C++ Libraries

provides functionalities for performance-intensive tasks, essential for handling complex operations efficiently. These libraries are written in C or C++ and are used by both the Android operating system and applications to leverage hardware capabilities directly without requiring a VM.

Libraries:
⠀↬⠀Surface Manager: Manages display and compositing.
⠀↬⠀Media Framework: Provides support for audio and video playback ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀and recording.
⠀↬⠀SQLite: A relational database for storing application data.
⠀↬⠀WebKit: Browser engine for rendering web content.
⠀↬⠀OpenGL|ES: API for 2D and 3D graphics.
⠀↬⠀Libc: Standard C library for Android.
⠀⠀⠀⠀➛⠀WebKit: Built-in web browser for the app (iFrame).
⠀⠀⠀⠀➛⠀OpenMAX AL, OpenGL ES: UI frameworks for 2D/3D models.

These libraries facilitate the creation of Android applications, including components like Graphics, Libc, SSL, SQLite, Media, WebKit, OpenGL, Surface Manager, etc.

4.⠀Android Runtime (ART) and Core Libraries

They are facilitating the execution of apps and some system services. Initially, Android used the Dalvik Virtual Machine (DVM) to run applications, but it has since transitioned to ART, which offers significant enhancements.
ART introduces ahead-of-time (AOT) compilation, improved garbage collection, and better debugging support. This shift from Dalvik to ART has resulted in faster execution times because ART precompiles code, eliminating the overhead associated with Dalvik’s just-in-time (JIT) compilation.
Both ART and Dalvik were specifically created for the Android project to ensure efficient multi-instance execution on devices. ART continues to execute the Dalvik Executable (DEX) format and adheres to the DEX bytecode specification.

The core libraries in Android are crucial for implementing applications using standard Java or Kotlin programming languages. These libraries include essential components that provide the foundation for the application framework and power Android applications, similar to the role of the Java Virtual Machine (JVM). By leveraging these core libraries, developers can build robust and efficient applications that integrate seamlessly with the Android platform.

Zygote

The initial cell formed when a new organism is produced

Zygote is a daemon responsible for launching applications. It starts at boot time, loading common system libraries and resources. As the base boilerplate process, Zygote forks itself to create new app processes, making it a part of all processes running on the device. This forking mechanism allows new applications to start more quickly and efficiently because they can share the already loaded resources. By reusing the initialized runtime environment, Zygote significantly reduces the startup time for new applications.

This process also enables shared code across Dalvik/Art VM in contrast with Java VM where each instance has its own copy of core library class files and heap objects.

We will encounter it when dealing with Magisk and Zygisk, you can read more about it.

5.⠀Java API Framework

It allows your app to interact with other apps and the device itself as defined in the Android app. This interaction is facilitated through a variety of APIs and services.

These APIs serve as the building blocks for creating Android apps, simplifying the reuse of core, modular system components and services.

Key Features and Components

  1. View System
    A rich and extensible view system used to build an app’s UI, including lists, grids, text boxes, buttons, and an embeddable web browser.
    It normalizes the app’s UI to ensure consistency across different devices and screen sizes.
  2. Content Providers
    These allow sharing data with other applications via a specific directory (if exported). The URI format is content://<app-URI>/directory.
  3. Managers

⠀⠀➛⠀Activity Manager: Manages the lifecycle of applications and provides ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀a common navigation back stack.
⠀⠀➛⠀Window Manager: Manages windows and screen layout.
⠀⠀➛⠀Notification Manager: Manages system-wide notifications, enabling ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀apps to display custom alerts in the status bar.
⠀⠀➛⠀Package Manager: Manages installed application packages, checks ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀for updates, and ensures integrity.
⠀⠀➛⠀Telephony Manager: Manages telephony services, including ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀receiving/making calls and accessing contacts.
⠀⠀➛⠀Resource Manager: Provides access to non-code resources such as ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀localized strings, graphics, and layout files.
⠀⠀➛⠀Location Manager: Manages location services.
⠀⠀➛⠀Sensors Manager: Manages access to sensors like accelerometers ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀and gyroscopes.

Developers have full access to the same framework APIs that Android system apps use. This gives developers the ability to create feature-rich applications using the Java API Framework.

6.⠀System apps

Consists of the pre-installed applications that come with the Android phone. These are apps provided by the phone manufacturer itself, such as Contacts, Phone, System Settings, Text Message Apps, Camera, and System Monitor. Additionally, there are third-party applications like browsers and Google Applications.

Android gives you the ability to set new default apps to replace vendor-supplied or system apps.

Dalvik vs Android Runtime

Dalvik is a virtual machine designed for Android that utilizes a Just-In-Time JIT compilation model. It compiles the bytecode into machine code at the moment of execution, which can lead to slower performance and increased power consumption.
Dalvik executes files in the Dalvik Executable .dex format, optimized for a minimal memory footprint. However, its garbage collection process can cause noticeable performance lags due to execution pauses.
Dalvik is based on a 32-bit architecture and is not a Java Virtual Machine JVM, so Java bytecode cannot run directly on it. Instead, Dalvik requires an exclusive use bytecode called Dex. It uses a tool called dexopt to create optimized dex files, known as Odex files.

ART is a virtual machine that replaced Dalvik as the default runtime starting from Android 5.0 Lollipop was optional in android 4.4. Unlike Dalvik, ART uses an Ahead-Of-Time “AOT” compilation model, compiling bytecode into native machine code during app installation.
ART also executes .dex files but converts them into Executable and Linkable Format .oat files during installation. Its more efficient garbage collection process minimizes pause times, leading to smoother performance.
While Dex files are still used, Odex is replaced by OAT files using a tool called dex2oat. These OAT files can be executed in the Executable and Linkable Format ELF at install time only once, allowing the bytecode to be run by the processor instead of a virtual machine.
.oat files are embedded in ELF object files, enabling them to run on any processor or architecture.

A comparison of Dalvik and ART architectures
╔══════════════════════════╦═══════════════════════════════╦════════════════════════════════════╗
║ Feature ║ Dalvik ║ ART ║
╠══════════════════════════╬═══════════════════════════════╬════════════════════════════════════╣
║ Compilation Type ║ Just-In-Time (JIT) ║ Ahead-Of-Time (AOT) ║
║ Bytecode Format ║ DEX ║ DEX converted to OAT ║
║ Execution Speed ║ Slower due to JIT ║ Faster due to precompilation ║
║ Application Installation ║ Faster ║ Slower due to AOT ║
║ Memory Usage ║ Higher due to JIT overhead ║ Lower due to optimized native code ║
║ Garbage Collection ║ Basic GC ║ Advanced GC with reduced pauses ║
║ Startup Time ║ Longer due to JIT compilation ║ Shorter due to precompiled code ║
║ Battery Usage ║ Higher due to JIT compilation ║ Lower due to efficiency ║
╚══════════════════════════╩═══════════════════════════════╩════════════════════════════════════╝

Just-In-Time (JIT)

With the Dalvik JIT compiler, each time an app runs, it dynamically translates portions of Dalvik bytecode into machine code. As the app continues to run, more bytecode is compiled and stored in cache. Because JIT compiles code incrementally, it has a smaller memory footprint and requires less physical space on the device.

Ahead-Of-Time (AOT)

ART uses an AOT compiler. During the app installation phase, it statically converts the DEX bytecode into machine code, which is then stored on the device. This process occurs only once, at installation. Without the need for JIT compilation, the code executes significantly faster.

Android Security implementation and processes Isolation

There are two layers:

  1. Operating System OS Layer
    The Android OS employs several mechanisms to ensure installed applications are isolated from one another. These mechanisms include process isolation, UID separation, and sandboxing.

⠀⠀➛⠀Process Isolation
⠀⠀⠀⠀ Each application runs in a separate Linux process. This isolation ⠀⠀⠀⠀ prevents applications from interfering with one another’s memory ⠀⠀⠀⠀ or execution.

⠀⠀➛⠀UID Separation
⠀⠀⠀ ⠀Each application is assigned a unique user ID “UID” upon ⠀⠀⠀ ⠀⠀⠀⠀ ⠀⠀⠀⠀ installation. The UID system ensures that applications have distinct ⠀⠀⠀ ⠀sets of permissions and access controls.

⠀⠀⠀ ⠀u0_a47 and u0_a46 are the UIDs of different applications. Only the ⠀⠀⠀ ⠀owner “the app itself” or root can access them, and no other users or ⠀⠀⠀ ⠀application scan access these directories.

⠀⠀⠀ ⠀Two applications can be configured to use the same UID. To do that ⠀⠀⠀ ⠀applications must define the same android:sharedUserId value in ⠀⠀⠀ ⠀⠀⠀⠀ their manifests.
⠀⠀⠀ ⠀There are some pre-defined IDs are stored in ⠀⠀⠀ ⠀⠀⠀⠀ ⠀⠀⠀ ⠀⠀⠀⠀ ⠀⠀⠀ ⠀android_filesystem_config.h , First user installed application ID ⠀⠀⠀ ⠀⠀⠀⠀ starts from 10,000

SO user u0_a47 has UID of 10047

⠀⠀➛⠀Sandboxing
⠀⠀⠀ ⠀Sandboxing leverages process isolation and UID separation to create ⠀⠀⠀ ⠀a controlled environment. Applications are restricted from accessing ⠀⠀⠀ ⠀other applications’ data or code as each process has its own virtual ⠀⠀⠀ ⠀machine. Enforced by the Linux kernel and reinforced by SELinux ⠀⠀⠀ ⠀policies.

⠀⠀➛⠀SELinux (Security-Enhanced Linux)
⠀⠀⠀ ⠀Implements mandatory access controls (MAC). It enforces security ⠀⠀⠀ ⠀policies to further restrict process actions and interactions. When ⠀⠀⠀ ⠀SELinux is enforced, it denies all process interactions by default and ⠀⠀⠀ ⠀then creates policies to allow only the expected interactions between ⠀⠀⠀ ⠀them.

⠀ ⠀➛⠀Verified Boot
⠀⠀⠀ ⠀Ensures the integrity of the boot process by verifying each stage of ⠀⠀⠀ ⠀the boot chain. Protects against unauthorized modifications to the ⠀⠀⠀ ⠀system partition.

2.⠀Application Layer
⠀⠀ At the application level, developers have control over the exposure of ⠀⠀ functionalities and the configuration of application capabilities. This ⠀⠀ includes defining permissions, using secure coding practices, and ⠀⠀ ⠀⠀ leveraging Android’s security features.

⠀ ⠀➛⠀Permissions
⠀⠀⠀ ⠀ Developers declare required permissions in the ⠀⠀⠀ ⠀⠀⠀⠀ ⠀⠀⠀ ⠀⠀⠀⠀⠀AndroidManifest.xml file. Permissions control access to sensitive ⠀⠀⠀ ⠀ APIs and resources.

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Permissions, such as those requested when you install an app, don’t all need to be asked for at the beginning. Android applications can request permissions dynamically as needed. However, all permissions must be declared in the manifest. Each permission also specifies a protection level.

⠀ ⠀➛⠀Network Security Configuration
⠀⠀⠀⠀⠀Lets you customize your app’s network security settings in a safe, ⠀⠀⠀⠀⠀declarative configuration file without modifying app code.

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">secure.example.com</domain>
<domain includeSubdomains="true">cdn.example.com</domain>
<trust-anchors>
<certificates src="@raw/trusted_roots"/>
</trust-anchors>
</domain-config>
</network-security-config>

To learn more about it, we will need it for certificate pinning.

There are other AndroidManifest features related to the Application Layer in Android Security implementation that we will discuss later.

Application Data Storage

  • Generic Application Data
    /data/app/com.example.app Stores the installed APK files and certain application metadata.
  • Runtime Storage of Data
    /data/data/com.example.app Contains runtime data like preferences, databases, and files created by the application during its execution.
  • External Storage for Runtime
    /mnt/sdcard/Android/data/com.example.app Used for storing larger files or data that the user might need to access directly, such as media files.

About the build process for APK

The source code is compiled by the Java compiler into Java bytecode, resulting in files with a .class extension. Multiple .class files are packaged into a JAR file. This Java bytecode must be converted into the .dex format for the Dalvik Virtual Machine (DVM), a task performed by the dex compiler. Additionally, processes like ProGuard, R8, and signing are applied before the final APK file is generated. All the DEX files, resources, assets, and the manifest file are packaged into the APK file.

This process can be logically reversed. Since the APK format is a type of ZIP format, you can unzip it to access the .dex file. The .dex file can be converted back into a JAR file because .dex and .class files are isomorphic. Finally, you can view the code using the JD-GUI tool. By using this tool, you can reverse an APK to the source code, including deobfuscation, in a single step.

How JAVA code execution works normally?

To maintain platform independence, Java developed the Java Virtual Machine (JVM). JVMs are platform-specific, making them dependent on the platform. The Java compiler converts .java files into .class files, known as byte code. The JVM then converts this byte code into machine code.

This step was revolutionary. Compiled code, while fast during execution, is platform-dependent. Interpreted code is slow as it translates during execution. Java, however, introduced a hybrid approach. It compiles .java files into .class files, which are platform-independent. Each platform then has its own JVM installed to run these class files.

However, this method faced performance issues and wasn’t entirely suitable for smartphones.

How Android code execution works?

Instead of using pure Java bytecode, Java classes are compiled into DEX bytecode. This DEX bytecode is then translated into native machine code by either the ART or Dalvik runtime. The DEX bytecode is designed to be independent of the device’s architecture. Android employs this approach for platform-specific optimizations, resource efficiency, and enhanced security.

_64K reference limit_

Within a single DEX bytecode file, only 65,536 methods can be referenced due to the Dalvik Executable specification limits. This includes methods from the Android framework, library methods, and your own code. To handle additional methods beyond this limit, they can be distributed across multiple DEX files using a technique called multidexing.

App Structure

Android apps can be written using Kotlin, the Java programming language, and C++ languages. The Android SDK tools compile your code along with any data and resource files into an APK or an Android App Bundle.

An APK (Android Application Package) file is the format used to install applications on the Android operating system. It is an archive format based on the JAR format and functions as a ZIP archive with specific files and directories. These files can be opened using any decompression tool by changing the extension to .zip or directly. When you download and install an Android application, you are installing an APK file. APK files can also be installed directly from a desktop or within a file manager app without downloading.

How to Find and Download APKs

  1. Trusted Sources
  • Official Websites; Download APKs from the official websites of the applications if they offer an APK download option.
  • Google Play Store: developers and corberites usually publish their application on google play store, after downloading it you can pull the APK file
    To pull them you can use adb tool i would explain it later

2. Mirror websites: Websites like apkpure or apkcombo they both offer google desktop extensions to search and download APKs directly. APKMirror also mirrors APKs from the Google Play Store.

It is better to use the application ID for searching Or, if you have visited the application page on the Google Play Store, the APKPure or APKCombo extension can detect it.

3. Tools like APKd:

Android package (APK) file structure

APK files can be unpacked using unzip app_name.apk.

1.⠀ Manifest File AndroidManifest.xml

Declares essential information about the app to the Android system, such as its package name, components (activities, services, broadcast receivers, content providers), permissions, and hardware/software requirements. It is serialized into binary format during the compilation process of the app and can be reconstructed using a decompilation tool.

This is how it would look after decompilation.

2. ⠀Java/Kotlin Bytecode classes.dex

Contains the compiled Java/Kotlin code in the Dalvik Executable DEX format, which the Android Runtime ART executes.

3. ⠀Native Libraries lib/ directory

Contains native code libraries compiled for different architectures, each corresponding to a specific ABI, such as ARM or x86, which are supported platforms for the app to run.

These native libraries are compiled into shared object files that can be loaded and executed by the Android runtime.

4. ⠀Resources res/ and resources.arsc

It contains non-code resources such as XML layouts, colors, strings, images, and other assets. Sometimes, it contains hardcoded tokens, secrets, or API keys, which can pose a security risk if exposed.
The res/ directory contains these resources, which are not compiled into resources.arsc. Instead, resources.arsc is a binary file that contains precompiled resources for efficient access by the app during runtime.

5.Assets assets/

contains raw asset files that the app can read using AssetManager, including additional native libraries or DEX files, which malware authors may use to conceal code or payloads.
It also holds certificates used for the certificate pinning process and allows developers to store various resources and external files such as images, music files, and other media. This makes the directory significant for examining potential hidden or sensitive data.

6. ⠀META-INF Directory

Contains the APK’s signature and manifest files used to verify the integrity and authenticity of the APK.

  • MANIFEST.MF: This is the manifest file that lists the files in the archive along with their SHA-1 or SHA-256 digests. It ensures that files haven't been tampered with after the APK was signed.
  • .SF File: Contains a list of names/hashes of the corresponding lines in the MANIFEST.MF file, ensuring its integrity.
  • .RSA File: This file contains the public key used to sign the APK, encoded in the PKCS#7 format. It is used to verify the signature against the MANIFEST.MF file and its corresponding .SF file.

The MANIFEST.MF file ensures that the files within the APK are intact and untampered, while the .SF file ensures that the MANIFEST.MF itself remains secure

7. ⠀com directory

Does not contain any interesting data.

Only the META-INF/ and res/ directories are essential and exist in any package content for Android applications.

Unzipping VS Decompiling

Unzipping an Android application refers to extracting the contents of the APK file, which is essentially a ZIP archive. This process allows you to view the raw files and resources bundled in the application. However, some files, such as classes.dex which contains the compiled code and AndroidManifest.xml which is in a serialized binary format, are in binary format and not directly readable.

Decompiling an Android application involves converting the binary code compiled .dex files back into a human-readable format source code. This process is more advanced than unzipping and is used to analyze the application’s logic and functionality. The decompiled code is often represented in SMALI, an intermediate language used by the Android runtime, which provides a detailed and readable version of the bytecode.

Methods to Decompile Applications

  1. Manual Process Using Dex2Jar

After Unzipping the Application you can use dex2jar to converting dex file to jar then using jd-gui to view it

unzip app.apk => dex2jar classes.dex => jd-gui classes.jar

Sample of the decompiled code

2. Mass decompilation

3. JADX-GUI

UI version of Jadx and used for Gui view of decompiled code

jadx-gui = dex2jar + jd-gui but jd-gui more accurate

4. apktool “most reliable method to patch or edit on the code”

To decode the apk file apktool d app.apk

APKTool stands out among other tools due to its ability to produce a smali directory, which is essential for understanding the internals of an Android application and patching it before recompiling.
When APKTool decompiles an APK, it translates the DEX files into smali files, which are human-readable representations of the DEX bytecode. This feature enables us to analyze the application’s logic at a low level. By modifying smali code, we can inject custom logic, patch vulnerabilities, or alter application behaviors.
After making these modifications, the smali files can be recompiled back into a DEX file and repackaged into an APK for further testing or analysis.

You can use apktool b app/ to build back the application after modifying it

apktool help menu

5. Androgurd

A Python-based framework meticulously crafted to facilitate the thorough examination of Android application files. It combines all old tools into a single command line interface. One of its key abilities is decompilation, allowing users to translate APK files back into readable source code for detailed examination.

androguard decompile -o /output app.apk

Additionally, Androguard can generate control flow graphs (CFG) for each method using the Graphviz format.
androguard decompile -o outputfolder -f png -i someapp.apk --limit "^Lcom/elite/.*"
allows you to specify output formats and filter which parts of the application to include. These PNG files can then be viewed using an image editor like GIMP.

6. APKLab extension on VScode

APKLab seamlessly integrates the best OpenSource tools such as: Quark-Engine, Apktool, Jadx, uber-apk-signer, apk-mitm and more to the excellent VS Code so you can focus on app analysis and get it done without leaving the IDE.

  1. Install APKLab extension on your VScode
  2. Open the Command Palette (Ctrl+Shift+P) ➜ APKLab: Open an APK

Check their manual for the other features

The most reliable tool to use is APKTool if you need to modify an application’s behavior and then recompile it. For just viewing the application, jadx-gui is my preferred option as it not only enables you to view the application structure in a more handy way but also allows you to view the corresponding smali for Java files, though you cannot edit them directly.
Recently, I started using APKLab as it automates the process of decompiling, viewing, recompiling, and signing the application, but it does not work for all applications.

Wait for the coming parts

Resources

--

--

No responses yet