Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/source/app_decoding.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ To manually capture the logs follow these steps:
6. Perform the actions required to get the packets needed for analysis (add device, send commands, etc).

.. note::
This process is incredibly time sensitive, it may take multiple attempts to get it right.
This process is incredibly time sensitive, it may take multiple attempts (10+) to get it right.


run.sh
Expand All @@ -111,7 +111,7 @@ and in addition writes the logs to a file as well as the console. This is
the recommend approach.

.. note::
The app must not be running when you start the script.
The app must **not** be running when you start the script.

This script performs the following actions:

Expand Down
103 changes: 83 additions & 20 deletions scripts/frida.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,15 @@
* Script name : frida.js
* Description : Frida script for preventing exit and extracting shared preferences
* Author : Harvey Lelliott (@flip-dots)
* Date : 23/03/26
* Date : 16/07/26
*
* License : MIT
* Revision : 1.0.0
* Revision : 1.1.0
*
* This script is based off https://codeshare.frida.re/@ninjadiary/frinja---sharedpreferences/
* but with additional code to prevent the anti-tamper mechanism from killing the app.
*/

// Prevent anti-tamper mechanism from fully killing app
setImmediate(function() {
Java.perform(function() {
var System = Java.use('java.lang.System');
var Process = Java.use('android.os.Process');

// Stop System.exit()
System.exit.implementation = function(code) {
console.log("[!] Intercepted exit (" + code + ")");
};

// Stop Process.killProcess()
Process.killProcess.implementation = function(pid) {
console.log("[!] Intercepted killProcess for PID: " + pid);
};
});
});

// Log any reads/writes to shared preferences
// From: https://codeshare.frida.re/@ninjadiary/frinja---sharedpreferences/
setImmediate(function() {
Expand Down Expand Up @@ -181,3 +163,84 @@ Java.perform(function () {
};
});
});


/**********************
* *
* Anti-Tamper Bypass *
* *
**********************/


// Prevent anti-tamper mechanism from killing the app in Java
setImmediate(function() {
Java.perform(function() {
console.log("Tampering with anti-tamper protection using Java API...");

var System = Java.use('java.lang.System');
var Process = Java.use('android.os.Process');

// Stop System.exit()
System.exit.implementation = function(code) {
console.log("[!] Intercepted exit (" + code + ")");
};

// Stop Process.killProcess()
Process.killProcess.implementation = function(pid) {
console.log("[!] Intercepted killProcess for PID: " + pid);
};
});
});


// Prevent anti-tamper mechanism from killing the app in C
function blockNativeExit() {
console.log("Tampering with anti-tamper protection using C API...");

let usleepAddr = null;
try {
usleepAddr = Module.findGlobalExportByName("usleep") || Module.findExportByName("usleep");
} catch (e) {
console.log("[-] Could not find usleep globally: " + e.message);
}

let nativeUsleep = null;
if (usleepAddr) {
nativeUsleep = new NativeFunction(usleepAddr, 'int', ['uint32']);
}

// Standard libc functions used by packers to terminate processes
const exitSymbols = ["exit", "_exit", "abort", "kill", "pthread_exit"];

exitSymbols.forEach(function (symbol) {
let address = null;
try {
// Find global exports using Frida 17 APIs
address = Module.findGlobalExportByName(symbol) || Module.findExportByName(symbol);
} catch (e) {
// Ignore search errors
}

if (address) {
try {
Interceptor.attach(address, {
onEnter: function (args) {
console.log("[!] Native anti-debug triggered " + symbol + "(). Freezing thread to prevent crash...");

// Infinite loop using the native OS sleep to halt the calling thread
while (true) {
if (nativeUsleep) {
nativeUsleep(100000); // Sleep for 100ms per iteration safely
}
}
}
});
console.log("[+] Hooked native function: " + symbol);
} catch (e) {
console.log("[-] Failed to hook: " + symbol + " (" + e.message + ")");
}
}
});
}

blockNativeExit();
60 changes: 56 additions & 4 deletions scripts/frida_2.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*
* Script name : frida.js
* Script name : frida_2.js
* Description : Frida script for preventing exit, extracting shared preferences, and tracing crypto/BLE with timestamps
* Author : Harvey Lelliott (@flip-dots) / Enhanced
* Date : 23/03/26
* Date : 16/07/26
* * License : MIT
* Revision : 1.1.1
* Revision : 1.2.1
*/

// --- UTILITY FUNCTIONS ---
Expand Down Expand Up @@ -293,4 +293,56 @@ setImmediate(function() {
log("[-] Error hooking Bluetooth: " + e);
}
});
});
});

// Prevent anti-tamper mechanism from killing the app in C
function blockNativeExit() {
console.log("Tampering with anti-tamper protection using C API...");

let usleepAddr = null;
try {
usleepAddr = Module.findGlobalExportByName("usleep") || Module.findExportByName("usleep");
} catch (e) {
console.log("[-] Could not find usleep globally: " + e.message);
}

let nativeUsleep = null;
if (usleepAddr) {
nativeUsleep = new NativeFunction(usleepAddr, 'int', ['uint32']);
}

// Standard libc functions used by packers to terminate processes
const exitSymbols = ["exit", "_exit", "abort", "kill", "pthread_exit"];

exitSymbols.forEach(function (symbol) {
let address = null;
try {
// Find global exports using Frida 17 APIs
address = Module.findGlobalExportByName(symbol) || Module.findExportByName(symbol);
} catch (e) {
// Ignore search errors
}

if (address) {
try {
Interceptor.attach(address, {
onEnter: function (args) {
console.log("[!] Native anti-debug triggered " + symbol + "(). Freezing thread to prevent crash...");

// Infinite loop using the native OS sleep to halt the calling thread
while (true) {
if (nativeUsleep) {
nativeUsleep(100000); // Sleep for 100ms per iteration safely
}
}
}
});
console.log("[+] Hooked native function: " + symbol);
} catch (e) {
console.log("[-] Failed to hook: " + symbol + " (" + e.message + ")");
}
}
});
}

blockNativeExit();
19 changes: 10 additions & 9 deletions scripts/patch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
# Script name : patch.sh
# Description : Script for injecting Frida gadget into Anker Android app
# Author : Harvey Lelliott (@flip-dots)
# Date : 23/03/26
# Date : 16/07/26
# Usage : ./patch.sh [ADB device (e.g 192.168.1.1:1234)]
#
# License : MIT
# Revision : 1.0.0
# Revision : 1.1.0
#
set -euxo pipefail

Expand All @@ -16,7 +16,7 @@ set -euxo pipefail
# Constants #
#############

FRIDA_VERSION="17.8.2"
FRIDA_VERSION="17.8.3"

UBER_APK_SIGNER_VERSION="1.3.0"

Expand Down Expand Up @@ -53,7 +53,7 @@ WORKING_FOLDER=$(pwd)

# Folder to put all data in
DATA_FOLDER="${WORKING_FOLDER}/data"
mkdir -p $DATA_FOLDER
rm -rf $DATA_FOLDER && mkdir -p $DATA_FOLDER

# Folder to put source APK inside
APK_SOURCE_FOLDER="${DATA_FOLDER}/source_apks"
Expand All @@ -73,7 +73,7 @@ mkdir -p $APK_SIGNED_FOLDER

# Folder to put tools in
TOOLS_FOLDER="${WORKING_FOLDER}/tools"
mkdir -p $TOOLS_FOLDER
rm -rf $TOOLS_FOLDER && mkdir -p $TOOLS_FOLDER

# Folder to put Frida gadgets in
FRIDA_FOLDER="${TOOLS_FOLDER}/frida"
Expand Down Expand Up @@ -124,10 +124,11 @@ cp "${WORKING_FOLDER}/frida_config.json" "${APK_DECOMPILED_FOLDER}/lib/armeabi-v
cp "${WORKING_FOLDER}/frida_config.json" "${APK_DECOMPILED_FOLDER}/lib/arm64-v8a/libnative-utils.config.so"

# Add Frida gadget to app startup
sed -i '' '34c \
const-string v0, "native-utils"\
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V\
' "${APK_DECOMPILED_FOLDER}/smali/s/h/e/l/l/A.smali"
sed -i '' 's/\.locals 5/\.locals 6/g' "${APK_DECOMPILED_FOLDER}/smali/s/h/e/l/l/S.smali"
sed -i '' '2386c \
const-string v5, "native-utils"\
invoke-static {v5}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V\
' "${APK_DECOMPILED_FOLDER}/smali/s/h/e/l/l/S.smali"

# Modify manifest to enable Frida loading
sed -i '' '/<application/,/>/ s/android:allowBackup="false"/android:allowBackup="true"/' "${APK_DECOMPILED_FOLDER}/AndroidManifest.xml"
Expand Down
Loading
Loading