improvement and add is_static data
This commit is contained in:
parent
a365022185
commit
91fd0137d8
5 changed files with 57 additions and 30 deletions
|
|
@ -1,3 +1,21 @@
|
||||||
# Theseus Data Collector
|
# Theseus Data Collector
|
||||||
|
|
||||||
Collect runtime information about reflection operation done by en application to feed them to the patcher.
|
Collect runtime information about reflection operation done by en application to feed them to the patcher.
|
||||||
|
|
||||||
|
The Frida hook uses a Java class to collect the stack information, before building/installing the python package, you need to build the class:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
|
||||||
|
# If the default values do not match, set the variables:
|
||||||
|
#
|
||||||
|
# JAVAC: path to the java compiler
|
||||||
|
# ANDROID_SDK: path to the android sdk
|
||||||
|
# VERSION: Android SDK version to use
|
||||||
|
# D8: path to the d8 executable
|
||||||
|
# ANDROID_JAR: path to the android.jar file to link
|
||||||
|
# BUILD_F: build folder (will be delated if exist)
|
||||||
|
# OUT_FILE: the file where to put the b64 of the compiled dex
|
||||||
|
|
||||||
|
bash consumer/build.sh
|
||||||
|
poetry build # / poetry install / pip install .
|
||||||
|
```
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ class StackConsumer implements Consumer<StackFrame> {
|
||||||
public ArrayList<StackFrame> stack;
|
public ArrayList<StackFrame> stack;
|
||||||
|
|
||||||
public StackConsumer() {
|
public StackConsumer() {
|
||||||
this.stack = new ArrayList();
|
this.stack = new ArrayList<StackFrame>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,30 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
|
||||||
JAVAC='/usr/lib/jvm/java-17-openjdk/bin/javac'
|
JAVAC="${JAVAC:-/usr/lib/jvm/java-17-openjdk/bin/javac}"
|
||||||
SDK_TOOLS="${HOME}/Android/Sdk/"
|
ANDROID_SDK="${ANDROID_SDK:-${HOME}/Android/Sdk/}"
|
||||||
VERSION='34.0.0'
|
VERSION="${VERSION:-34.0.0}"
|
||||||
D8="${SDK_TOOLS}/build-tools/${VERSION}/d8"
|
D8="${D8:-${ANDROID_SDK}/build-tools/${VERSION}/d8}"
|
||||||
VERSION_B=$(echo "${VERSION}" | sed 's/\..*//')
|
VERSION_B="${VERSION_B:-$(echo "${VERSION}" | sed 's/\..*//')}"
|
||||||
ANDROID_JAR="${SDK_TOOLS}/platforms/android-${VERSION_B}/android.jar"
|
ANDROID_JAR="${ANDROID_JAR:-${ANDROID_SDK}/platforms/android-${VERSION_B}/android.jar}"
|
||||||
|
|
||||||
FOLDER=$(dirname "$(realpath $0)")
|
FOLDER=$(dirname "$(realpath $0)")
|
||||||
BUILD_F="${FOLDER}/build"
|
BUILD_F="${BUILD_F:-${FOLDER}/build}"
|
||||||
OUT_FILE="${FOLDER}/../theseus_frida/StackConsumer.dex.b64"
|
OUT_FILE="${OUT_FILE:-${FOLDER}/../theseus_frida/StackConsumer.dex.b64}"
|
||||||
|
|
||||||
|
echo "JAVAC = ${JAVAC}"
|
||||||
|
echo "ANDROID_SDK = ${ANDROID_SDK}"
|
||||||
|
echo "VERSION = ${VERSION}"
|
||||||
|
echo "D8 = ${D8}"
|
||||||
|
# echo "VERSION_B = ${VERSION_B}"
|
||||||
|
echo "ANDROID_JAR = ${ANDROID_JAR}"
|
||||||
|
echo "BUILD_F = ${BUILD_F}"
|
||||||
|
echo "OUT_FILE = ${OUT_FILE}"
|
||||||
|
|
||||||
rm -r "${BUILD_F}"
|
rm -r "${BUILD_F}"
|
||||||
mkdir "${BUILD_F}"
|
mkdir "${BUILD_F}"
|
||||||
|
|
||||||
"${JAVAC}" -d "${BUILD_F}" -classpath "${ANDROID_JAR}" "${FOLDER}/StackConsumer.java"
|
"${JAVAC}" -Xlint -d "${BUILD_F}" -classpath "${ANDROID_JAR}" "${FOLDER}/StackConsumer.java"
|
||||||
|
|
||||||
mkdir "${BUILD_F}/classes"
|
mkdir "${BUILD_F}/classes"
|
||||||
"${D8}" --classpath "${ANDROID_JAR}" "${BUILD_F}/theseus/android/StackConsumer.class" --output "${BUILD_F}/classes"
|
"${D8}" --classpath "${ANDROID_JAR}" "${BUILD_F}/theseus/android/StackConsumer.class" --output "${BUILD_F}/classes"
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ from pathlib import Path
|
||||||
|
|
||||||
import frida # type: ignore
|
import frida # type: ignore
|
||||||
from androguard.core.apk import get_apkid # type: ignore
|
from androguard.core.apk import get_apkid # type: ignore
|
||||||
|
from loguru import logger # type: ignore
|
||||||
|
|
||||||
|
logger.remove() # remove androguard logs
|
||||||
|
|
||||||
FRIDA_SCRIPT = Path(__file__).parent / "hook.js"
|
FRIDA_SCRIPT = Path(__file__).parent / "hook.js"
|
||||||
STACK_CONSUMER_B64 = Path(__file__).parent / "StackConsumer.dex.b64"
|
STACK_CONSUMER_B64 = Path(__file__).parent / "StackConsumer.dex.b64"
|
||||||
|
|
@ -35,32 +38,25 @@ def print_stack(stack, prefix: str):
|
||||||
print(f"{prefix}{frame['method']}:{frame['bytecode_index']}{native}")
|
print(f"{prefix}{frame['method']}:{frame['bytecode_index']}{native}")
|
||||||
|
|
||||||
|
|
||||||
# def get_ty(java_name: str) -> str:
|
|
||||||
# """Return the android name from the java name of a class / type"""
|
|
||||||
# # TODO: array
|
|
||||||
# # TODO: scalar
|
|
||||||
# if java_name == "V": # tmp stub
|
|
||||||
# return "V"
|
|
||||||
# return f"L{java_name.replace('.', '/')};"
|
|
||||||
|
|
||||||
|
|
||||||
# def get_method_id(method_data) -> str:
|
|
||||||
# """Get a method descriptor from the different elements collected from the methods."""
|
|
||||||
# name = method_data["name"]
|
|
||||||
# ret = get_ty(method_data["ret"])
|
|
||||||
# cls = get_ty(method_data["class"])
|
|
||||||
# args = "".join(map(get_ty, method_data["args"]))
|
|
||||||
# return f"{cls}->{name}({args}){ret}"
|
|
||||||
|
|
||||||
|
|
||||||
def handle_invoke_data(data, data_storage: dict):
|
def handle_invoke_data(data, data_storage: dict):
|
||||||
method = data["method"]
|
method = data["method"]
|
||||||
|
# TODO: good idea?
|
||||||
|
if method in [
|
||||||
|
"Landroid/view/View;->getTranslationZ()F",
|
||||||
|
"Landroid/view/View;->getElevation()F",
|
||||||
|
]:
|
||||||
|
return
|
||||||
if len(data["stack"]) == 0:
|
if len(data["stack"]) == 0:
|
||||||
return
|
return
|
||||||
caller_method = data["stack"][0]["method"]
|
caller_method = data["stack"][0]["method"]
|
||||||
addr = data["stack"][0]["bytecode_index"]
|
addr = data["stack"][0]["bytecode_index"]
|
||||||
|
is_static = data["is_static"]
|
||||||
|
if is_static:
|
||||||
|
is_static_str = " (static)"
|
||||||
|
else:
|
||||||
|
is_static_str = ""
|
||||||
print("Method.Invoke:")
|
print("Method.Invoke:")
|
||||||
print(f" called: {method}")
|
print(f" called: {method}{is_static_str}")
|
||||||
print(f" by: {caller_method}")
|
print(f" by: {caller_method}")
|
||||||
print(f" at: 0x{addr:08x}")
|
print(f" at: 0x{addr:08x}")
|
||||||
# print(f" stack:")
|
# print(f" stack:")
|
||||||
|
|
@ -72,6 +68,7 @@ def handle_invoke_data(data, data_storage: dict):
|
||||||
"method": method,
|
"method": method,
|
||||||
"caller_method": caller_method,
|
"caller_method": caller_method,
|
||||||
"addr": addr,
|
"addr": addr,
|
||||||
|
"is_static": is_static,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ Java.perform(() => {
|
||||||
const Method = Java.use("java.lang.reflect.Method");
|
const Method = Java.use("java.lang.reflect.Method");
|
||||||
const Class = Java.use("java.lang.Class");
|
const Class = Java.use("java.lang.Class");
|
||||||
const Constructor = Java.use("java.lang.reflect.Constructor");
|
const Constructor = Java.use("java.lang.reflect.Constructor");
|
||||||
|
const Modifier = Java.use("java.lang.reflect.Modifier");
|
||||||
Method.invoke.overload(
|
Method.invoke.overload(
|
||||||
"java.lang.Object", "[Ljava.lang.Object;" // the Frida type parser is so cursted...
|
"java.lang.Object", "[Ljava.lang.Object;" // the Frida type parser is so cursted...
|
||||||
).implementation = function (obj, args) {
|
).implementation = function (obj, args) {
|
||||||
|
|
@ -80,7 +81,8 @@ Java.perform(() => {
|
||||||
"args": this.getParameterTypes().map((argty) => argty.getName() ),
|
"args": this.getParameterTypes().map((argty) => argty.getName() ),
|
||||||
"ret": this.getReturnType().getName(),
|
"ret": this.getReturnType().getName(),
|
||||||
},*/
|
},*/
|
||||||
"stack": get_stack()
|
"stack": get_stack(),
|
||||||
|
"is_static": Modifier.isStatic(this.getModifiers()),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return this.invoke(obj, args);
|
return this.invoke(obj, args);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue