0% found this document useful (0 votes)
0 views

Android-Dynamic-Analysis

The document provides an overview of SSL Pinning, a security mechanism that prevents Man-in-the-Middle attacks by ensuring apps communicate only with servers possessing specific SSL certificates or public keys. It details the types of SSL pinning, advantages, and how to set up Android emulators for dynamic analysis, including rooting, ADB commands, APK patching, and using Frida for scripting and bypassing SSL pinning. Additionally, it discusses Android Intents, their attack surfaces, and the different launch modes for activities, highlighting their behaviors and use cases.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views

Android-Dynamic-Analysis

The document provides an overview of SSL Pinning, a security mechanism that prevents Man-in-the-Middle attacks by ensuring apps communicate only with servers possessing specific SSL certificates or public keys. It details the types of SSL pinning, advantages, and how to set up Android emulators for dynamic analysis, including rooting, ADB commands, APK patching, and using Frida for scripting and bypassing SSL pinning. Additionally, it discusses Android Intents, their attack surfaces, and the different launch modes for activities, highlighting their behaviors and use cases.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

Android Dynamic Analysis

SSL Pinning
What is SSL Pinning?
SSL (Secure Sockets Layer) Pinning is a security mechanism used in applications to
prevent Man-in-the-Middle (MITM) attacks by ensuring that the app communicates
only with a server possessing a specific SSL certificate or public key. Instead of
relying solely on the operating system’s trusted Certificate Authorities (CAs), SSL
pinning pins a certificate or public key to the application.

How SSL Pinning Works


1. Regular SSL/TLS Communication
When an app communicates with a server over HTTPS, it verifies the
server’s certificate chain against a trusted list of Certificate Authorities
(CAs).
This verification is handled by the device’s operating system.
2. With SSL Pinning
The app includes a copy of the server’s certificate or its public key (the
“pinned” certificate or key) within the app’s code or configuration.
During an HTTPS connection, the app checks the server’s certificate against
the pinned certificate/key.
If the pinned certificate/key matches the server’s certificate, the connection
is established. If not, the connection is rejected—even if the certificate is
otherwise valid.

Types of SSL Pinning


1. Certificate Pinning
The app includes the server’s SSL certificate in its code.
During the handshake, the app compares the server’s certificate with the
pinned one.
2. Public Key Pinning
Instead of pinning the entire certificate, the app stores the hash of the
server’s public key.
More flexible: the server can renew its certificate without changing the public
key.
3. CA Pinning
Pins the Certificate Authority’s certificate instead of the server’s certificate.
Less secure but more flexible when the server rotates certificates issued by
the same CA.

Advantages of SSL Pinning


1. Increased Security
Prevents MITM attacks where an attacker uses a fraudulent certificate.
2. Bypassing OS-Level CA Trust
Protects against compromised or malicious Certificate Authorities.
3. Controlled Trust
Limits trust to only the specified servers.

Emulator Setup
Installing Android Studio
To access an Android Emulator, you need to install Android Studio. You can download
and install it from Android Studio’s official page.
Key Points:
The Emulator is an actual CPU emulator, reproducing the device architecture.
Google Play emulator images do not have root by default, but have the Google
Play Store installed like a real phone.
You can choose different Android versions depending on the API level you want to
test.

Rooting Your Emulator


You can root your emulator using the rootAVD project (rootAVD on GitLab).

./rootAVD.sh ListAllAVDs

This script (and associated tools) can help you root various Android emulator versions
(e.g., Android 14).

ADB
ADB Setup
1. Create an emulator of your choice (preferably one for each major version).
2. Root it (using the rootAvd script) if you need deeper system-level testing.
3. Add Burp certificate to the emulator:
Drag and drop the certificate into the emulator.
Go to Settings > Certificate Management > Install Certificate and choose it.
For Android 14, you may need a script (see below) that copies the user
certificates to the system store.

Example Script for Installing User Certificates System-Wide


(Android 14)
# Create a separate temp directory, to hold the current certificates
mkdir -p -m 700 /data/local/tmp/tmp-ca-copy

# Copy out the existing certificates


cp /apex/com.android.conscrypt/cacerts/* /data/local/tmp/tmp-ca-copy/

# Create the in-memory mount on top of the system certs folder


mount -t tmpfs tmpfs /system/etc/security/cacerts

# Copy the existing certs back into the tmpfs, so we keep trusting them
mv /data/local/tmp/tmp-ca-copy/* /system/etc/security/cacerts/

# Copy our new cert in, so we trust that too


cp /data/misc/user/0/cacerts-added/* /system/etc/security/cacerts/

# Update the perms & selinux context labels


chown root:root /system/etc/security/cacerts/*
chmod 644 /system/etc/security/cacerts/*
chcon u:object_r:system_file:s0 /system/etc/security/cacerts/*

# Inject the mount into running apps/namespaces (zygote, etc.)


ZYGOTE_PID=$(pidof zygote || true)
ZYGOTE64_PID=$(pidof zygote64 || true)

for Z_PID in "$ZYGOTE_PID" "$ZYGOTE64_PID"; do


if [ -n "$Z_PID" ]; then
nsenter --mount=/proc/$Z_PID/ns/mnt -- \
/bin/mount --bind /system/etc/security/cacerts
/apex/com.android.conscrypt/cacerts
fi
done

APP_PIDS=$(
echo "$ZYGOTE_PID $ZYGOTE64_PID" | \
xargs -n1 ps -o 'PID' -P | \
grep -v PID
)

for PID in $APP_PIDS; do


nsenter --mount=/proc/$PID/ns/mnt -- \
/bin/mount --bind /system/etc/security/cacerts
/apex/com.android.conscrypt/cacerts &
done
wait

echo "System certificate injected"

Common ADB Commands


Install an APK

adb install <path-to-apk>

List latest installed packages (third-party)

adb shell pm list packages -3

View information about a package (activities, intents, permissions)

adb shell dumpsys package <package-name>

Start an Intent from shell

adb shell am start -n <package-name>/.<ActivityName>

APK Patching
Generating a Keystore
keytool -genkey -v -keystore research.keystore -alias research_key \
-keyalg RSA -keysize 2048 -validity 10000

Signing the APK


# jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore
research.keystore app.apk research_key
# On newer Android versions, SHA1 signatures may be rejected. So simply use
the default algorithms:
jarsigner -verbose -keystore research.keystore app.apk research_key

Troubleshooting Common Issues


1. INSTALL_PARSE_FAILED_NO_CERTIFICATES
Usually means the APK is unsigned or the chosen algorithm (e.g., SHA1) is not
accepted.
2. INSTALL_FAILED_INVALID_APK Failed to extract native libraries
Some APKs with native libraries require adding

<application
android:extractNativeLibs="true"
...
/>

to the AndroidManifest.xml. Rebuild and re-sign afterward.


3. Targeting R+ (version 30 and above) requires the resources.arsc ...
uncompressed and aligned on a 4-byte boundary
Solution: After rebuilding with apktool, run:

# Align the APK


zipalign -p -f -v 4 ./dist/<apktool_build>.apk aligned.apk

# Sign it
apksigner sign --ks ./research.keystore ./aligned.apk

Frida Setup
Installing Frida
pip3 install frida-tools

After installation, verify by running:

frida --version

Objection Setup
pip3 install objection

Objection simplifies Frida patching of Android/iOS apps.

Injecting Frida via Objection


1. Download the sample app: FridaTarget.apk
2. Run objection’s patch command:

objection patchapk -s FridaTarget.apk

This extracts, patches, repacks, aligns, and signs the APK automatically.
3. Start the application with Frida:

frida -U FridaTarget

The -U connects via USB (or emulator).

Alternative: Using frida-server


If you have a rooted device (or rooted emulator):
1. Download frida-server from the Frida GitHub Releases.
2. Push it to the device/emulator:

adb push frida-server /data/local/tmp/


adb root
adb shell
cd /data/local/tmp
chmod +x frida-server
./frida-server

3. Connect with:

frida -U FridaTarget

Scripting with Frida


Instantiating Objects and Calling Methods
We can get JavaScript wrappers for Java classes by using Java.use :
Java.use("java.lang.String")

We can then instantiate those classes by calling $new:

var string_class = Java.use("java.lang.String");


var string_instance = string_class.$new("Teststring");
string_instance.charAt(0);

We can dispose of instances (for example to free up memory) using $dispose() ,


however this is almost never required, as the Garbage Collector should collect unused
instances.
We can also replace the implementation of a method by overwriting it on the class:

string_class.charAt.implementation = (c) => {


console.log("charAt overridden!");
return "X";
}

Tracing Activities
Java.perform(() => {
let ActivityClass = Java.use("android.app.Activity");
ActivityClass.onResume.implementation = function() {
console.log("Activity resumed:", this.getClass().getName());
// Call original onResume method
this.onResume();
}
})

Tracing Fragments
Java.perform(() => { let FragmentClass =
Java.use("androidx.fragment.app.Fragment");
FragmentClass.onResume.implementation = function() { console.log("Fragment
resumed:", this.getClass().getName()); // Call original onResume method
this.onResume(); } })

Frida Tracing
frida-trace -U -j 'classname!methodname'
frida-trace -U -j 'packagename.*!*' FridaTarget

SSL Pinning Bypass


With Frida we can often easily disable SSL validation or disable SSL pinning. For
example, to bypass Network Security Config and SSLContext based pinning, we can
use this simple script:

Java.perform(() => {
var PlatformClass = Java.use("com.android.org.conscrypt.Platform");

PlatformClass.checkServerTrusted.overload('javax.net.ssl.X509TrustManager',
'[Ljava.security.cert.X509Certificate;', 'java.lang.String',
'com.android.org.conscrypt.AbstractConscryptSocket').implementation =
function() {
console.log("Check server trusted");
}
})

For OKHTTP3-based pinning we need to combine the script of the previous section,
and a small new one that prevents the SSLPinner from being added to the
OkHttpClient:

Java.perform(() => {
var BuilderClass = Java.use("okhttp3.OkHttpClient$Builder");
BuilderClass.certificatePinner.implementation = function() {
console.log("Certificate pinner called");
return this;
}
})

We can also use the one script for all


https://codeshare.frida.re/@pcipolloni/universal-android-ssl-pinning-bypass-with-
frida/

Intents' Attack Surface


Android provides a variety of ways for apps to communicate with each other via
Intents. While powerful, this can also introduce vulnerabilities if not handled securely.

Intent Redirect
An attacker can supply (or control) an Intent used by a vulnerable app to start another
Activity or component. For example, a developer might let the user pass an Intent to
an exported Activity that then forwards that Intent to a privileged Activity.

Implicit Intent Hijacking


Sending implicit Intents is less common from an attacker’s perspective, but
receiving them can be risky.
Apps often use implicit Intents to broadcast or share data (e.g., images to the
gallery). If an attacker registers a handler for that action, they might capture
sensitive data.

Pending Intents
PendingIntents allow one app to pass an Intent to another app (e.g., for notifications)
that retains the original app’s permissions. If an attacker obtains this PendingIntent ,
they can exploit its privileged context.

Deep Links
A deep link is a special URL that opens a specific screen within an app. For instance,
a link in a browser could open myapp://open?param=value in your app.
These links can be hijacked like any other implicit Intent if you have an <intent-
filter> specifying you can handle the link.
Developers must carefully design deep link handling to avoid accidentally
exposing sensitive activities.

Launch Modes
Android defines four launch modes for activities that determine how new instances of
activities are created and how they interact with the back stack (task). Here is a
summary of each.

1. Standard (default)
Behavior: A new instance is created every time the activity is launched.
Usage: Default for most activities.
Example: An Activity A starts itself multiple times: stack looks like A -> A -> A .
<activity android:name=".YourActivity"
android:launchMode="standard" />

2. SingleTop
Behavior: If the activity is already at the top of the stack, no new instance is
created; onNewIntent() is called instead.
Usage: Good for activities that handle updates or new data via Intents.
Example: A notification repeatedly opens the same detail screen if it’s already on
top.

<activity android:name=".YourActivity"
android:launchMode="singleTop" />

3. SingleTask
Behavior: Only one instance of the activity in a task. If it exists in a background
task, that task is brought to the foreground and onNewIntent() is called.
Usage: Common for a main “Home” activity.
Example: Launching the main activity from multiple places reuses the same
instance in the same task.

<activity android:name=".YourActivity"
android:launchMode="singleTask" />

4. SingleInstance
Behavior: Similar to SingleTask but no other activities can be in the same task.
Usage: Used for standalone activities like a fullscreen media player or a kiosk
mode.
Example: A media player that must run separately.

<activity android:name=".YourActivity"
android:launchMode="singleInstance" />

Key Differences Between Launch Modes

Launch Mode New Instance Behavior When Already Task Affinity


Created? Running
Standard Always New instance is added to the Same as caller
stack
Launch Mode New Instance Behavior When Already Task Affinity
Created? Running
SingleTop Only if not on onNewIntent() of top activity Same as caller
top if already on top
SingleTask Only one Brings existing task to New or existing
instance per foreground, calls separate task
task onNewIntent()
SingleInstance Only one Brings activity to foreground, Always in its
instance calls onNewIntent() own unique task
globally

Use Cases
Standard: General-purpose activities.
SingleTop: Activities opened repeatedly via notifications/intents (e.g., detail
pages).
SingleTask: Main or entry-point activities (e.g., dashboards, home screens).
SingleInstance: Activities requiring complete isolation (e.g., special media
players, kiosks).

You might also like