Android Hacking
Terms
activities: each screen is an activity
resources : any other that is not java code
layout: how a view should look, xml
Intent: represent a way for one activity to another, what activity
AndroidManifest.xml : configuration file that android can use to launch the file
Broadcast and Receivers:
Services: Backgroud Application
Content Providers: Allows apps to share data and resources
META-INF/ : Android Certificates folder
assets/ : Stores images, icons,
lib/: Native libraries for the application
Static Analysis
### TODO
Understanding Dalvik, ### TODO
The Java Code is compiled to dalvik bytecode by android runtime.
Smali
Smali is the human readable version of dalvik bytecode , smali is like assembly language and dalvik just bytes
Entrypoint of android (Launcher activity)
the launcher activity is the first activity upon launch of an android app. Check the androidmanifest, the launcher activity will have the main and Launcher intent
using jd-gui ### TODO
ADB
List Devices
adb devices
Connect to a device
adb connect devices
Install app
adb install apk
Upload to /data/local/tmp/
adb push something /data/local/tmp/
Run shell command
adb shell
adb shell getprop ro.product.cpu.abi # get device architecture
Frida and Objection
Inject Frida into APK
objection patchapk -s <apk>
Start Application and drop into frida shell
frida -U <appname>
Uploading and running Frida Server on android
get architechture
adb shell getprop ro.product.cpu.abi
get release https://github.com/frida/frida/releases
adb push frida-server* /data/local/tmp
Network Interception
Install Split app
adb shell pm path com.app | sed 's/^package://g' | xargs -L1 adb pull
adb install-multiple *a.apk
Android 14
# Create a separate temp directory, to hold the current certificates
# Otherwise, when we add the mount we can't read the current certs anymore.
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/*
# Deal with the APEX overrides, which need injecting into each namespace:
# First we get the Zygote process(es), which launch each app
ZYGOTE_PID=$(pidof zygote || true)
ZYGOTE64_PID=$(pidof zygote64 || true)
# N.b. some devices appear to have both!
# Apps inherit the Zygote's mounts at startup, so we inject here to ensure
# all newly started apps will see these certs straight away:
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
# Then we inject the mount into all already running apps, so they
# too see these CA certs immediately:
# Get the PID of every process whose parent is one of the Zygotes:
APP_PIDS=$(
echo "$ZYGOTE_PID $ZYGOTE64_PID" | \
xargs -n1 ps -o 'PID' -P | \
grep -v PID
)
# Inject into the mount namespace of each of those apps:
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 # Launched in parallel - wait for completion here
echo "System certificate injected"
Dynamic Analysis Using Frida
Modify or observe the behaviour of an application during runtime.
Install frida-client on your PC with
pip install frida-tools
Install Frida Server on mobile based on the architechture of the mobile device
download server release here > “https://github.com/frida/frida/releases”
### Frida Trace trace function calls in application
frida-trace -U -j '<lassname>.*!*' <Application>
### Frida
list all the installed applications in the device along with their process ID and identifier.
frida-ps -Uai
attach frida to application by specifying the identifier
frida -U -f <application identifier>
connect to application on device on default port
frida -U -f application -l script_to_run
frida -H IP:Port # custom IP and Port
### FRIDA SCRIPTS
Javascript codes to change behavior of methods in runtime
Java.perform(function (){
// implementations here ..
})
Enumerate Package Names
Java.enumerateMethods('*!*')
change function implementation
<classname>.<function>.implementation = function(){
}
overload function
<classname>.<function>.overload('int', 'int').implementation = function(a,b){
}
access value
<classname>.<function>.value
Java.performNow(function(){
Java.choose('com.<classname>.<function>.MainActivity', {
onMatch: function(instance) {
console.log("Instance found");
},
onComplete: function() {}
});
});
To hook native functions, we can use the Interceptor API. Now, let’s see the template for this.
Interceptor.attach(targetAddress, {
onEnter: function (args) {
console.log('Entering ' + functionName);
// Modify or log arguments if needed
},
onLeave: function (retval) {
console.log('Leaving ' + functionName);
// Modify or log return value if needed
}
});
Get Target Address
Module.getBaseAddress("libraryname.so");
Module.enumerateExports("libraryname.so");
Module.enumerateImports("libfrida0x8.so");
Module.findExportByName("libc.so", "strcmp");
Calling Native function
var native_adr = new NativePointer(<address_of_the_native_function>);
const native_function = new NativeFunction(native_adr, '<return type>', ['argument_data_type']);
native_function(<arguments>);
Sending Intents
Intent intent1 = new Intent();
intent1.setClassName("<packagename>", "<pathname>");
intent1.setAction("<action>");
intent3.putExtra("reason", "next");
intent2.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setData(Uri.parse("<url>"));
startActivity(intent1);
Intent Filters
Intent filters serve important role in the resolution of implicit intents by the android os .
Broadcast Receiver
check AndroidManifest.xml for tag
<receiver>
The other way is by dynamically registering a receiver class using
registerReceiver().
AppWidgets
check
AppWidgetProvider
https://github.com/DERE-ad2001/Frida-Labs/blob/main/Frida%200xA/Solution/Solution.md