collect classloaders on the fly
This commit is contained in:
parent
b86bf08229
commit
ba02e70dcc
5 changed files with 58 additions and 26 deletions
|
|
@ -3,7 +3,7 @@ name = "theseus-frida"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = ""
|
description = ""
|
||||||
authors = [
|
authors = [
|
||||||
{name = "Jean-Marie Mineau",email = "jean-marie.mineau@inria.fr"}
|
{name = "Jean-Marie Mineau",email = "jean-marie.mineau@centralesupelec.fr"}
|
||||||
]
|
]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.13,<4.0.0"
|
requires-python = ">=3.13,<4.0.0"
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ import lzma
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TextIO, Any
|
from typing import TextIO, Any
|
||||||
|
|
||||||
|
from .app_exploration import explore_app
|
||||||
|
|
||||||
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
|
from loguru import logger # type: ignore
|
||||||
|
|
@ -76,6 +78,7 @@ def cl_id_to_string(classloader: int) -> str | None:
|
||||||
def handle_classloader_data(data: dict, data_storage: dict):
|
def handle_classloader_data(data: dict, data_storage: dict):
|
||||||
data["id"] = cl_id_to_string(data["id"])
|
data["id"] = cl_id_to_string(data["id"])
|
||||||
data["parent_id"] = cl_id_to_string(data["parent_id"])
|
data["parent_id"] = cl_id_to_string(data["parent_id"])
|
||||||
|
print(f"[+] Got classloader {data['id']}({data['str']})")
|
||||||
data_storage["classloaders"].append(data)
|
data_storage["classloaders"].append(data)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -363,21 +366,21 @@ def collect_runtime(apk: Path, device_name: str, file_storage: Path, output: Tex
|
||||||
# Resume the execution of the APK
|
# Resume the execution of the APK
|
||||||
device.resume(pid)
|
device.resume(pid)
|
||||||
|
|
||||||
print("==> Press ENTER to end the analysis <==")
|
|
||||||
input()
|
|
||||||
|
|
||||||
# Dump all known classloaders
|
# Dump all known classloaders
|
||||||
global CLASSLOADER_DONE
|
# Don't wait for confirmation that all cl were sended
|
||||||
CLASSLOADER_DONE = False
|
# global CLASSLOADER_DONE
|
||||||
|
# CLASSLOADER_DONE = False
|
||||||
script.post({"type": "dump-class-loaders"})
|
script.post({"type": "dump-class-loaders"})
|
||||||
t = spinner()
|
# t = spinner()
|
||||||
while not CLASSLOADER_DONE:
|
# while not CLASSLOADER_DONE:
|
||||||
print(
|
# print(
|
||||||
f"[{t.__next__()}] Waiting for the list of classloaders to be sent",
|
# f"[{t.__next__()}] Waiting for the list of classloaders to be sent",
|
||||||
end="\r",
|
# end="\r",
|
||||||
)
|
# )
|
||||||
time.sleep(0.3)
|
# time.sleep(0.3)
|
||||||
print(f"[*] Classloader list received" + " " * 20)
|
# print(f"[*] Classloader list received" + " " * 20)
|
||||||
|
|
||||||
|
explore_app()
|
||||||
|
|
||||||
# Try to find the Main class loader
|
# Try to find the Main class loader
|
||||||
main_class_loader: str | None = None
|
main_class_loader: str | None = None
|
||||||
|
|
|
||||||
7
frida/theseus_frida/app_exploration.py
Normal file
7
frida/theseus_frida/app_exploration.py
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
def explore_app():
|
||||||
|
manual_exploration()
|
||||||
|
|
||||||
|
|
||||||
|
def manual_exploration():
|
||||||
|
print("==> Press ENTER to end the analysis <==")
|
||||||
|
input()
|
||||||
|
|
@ -1,14 +1,26 @@
|
||||||
|
const sended_class_loaders = new Set();
|
||||||
|
|
||||||
|
function send_class_loader(cl) {
|
||||||
|
const System = Java.use('java.lang.System');
|
||||||
|
let cl_id = System.identityHashCode(cl);
|
||||||
|
while (cl != null && !sended_class_loaders.has(cl_id)) {
|
||||||
|
let parent_ = cl.getParent();
|
||||||
|
send({"type": "classloader", "data": {
|
||||||
|
"id": cl_id,
|
||||||
|
"parent_id": System.identityHashCode(parent_),
|
||||||
|
"str": cl.toString(),
|
||||||
|
"cname": cl.$className
|
||||||
|
}});
|
||||||
|
sended_class_loaders.add(cl_id);
|
||||||
|
cl = parent_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function dump_classloaders() {
|
function dump_classloaders() {
|
||||||
Java.perform(() => {
|
Java.perform(() => {
|
||||||
const System = Java.use('java.lang.System');
|
|
||||||
var class_loader = Java.enumerateClassLoadersSync();
|
var class_loader = Java.enumerateClassLoadersSync();
|
||||||
for (var cl of class_loader) {
|
for (var cl of class_loader) {
|
||||||
send({"type": "classloader", "data": {
|
send_class_loader(cl);
|
||||||
"id": System.identityHashCode(cl),
|
|
||||||
"parent_id": System.identityHashCode(cl.getParent()),
|
|
||||||
"str": cl.toString(),
|
|
||||||
"cname": cl.$className
|
|
||||||
}});
|
|
||||||
}
|
}
|
||||||
send({"type": "classloader-done"})
|
send({"type": "classloader-done"})
|
||||||
});
|
});
|
||||||
|
|
@ -125,11 +137,13 @@ Java.perform(() => {
|
||||||
var stack = stackConsumer.getStack()
|
var stack = stackConsumer.getStack()
|
||||||
//send({"type": "stack", "data": stackConsumer.getStack()});
|
//send({"type": "stack", "data": stackConsumer.getStack()});
|
||||||
return stack.map((frame) => {
|
return stack.map((frame) => {
|
||||||
|
let cl = frame.getDeclaringClass().getClassLoader();
|
||||||
|
send_class_loader(cl);
|
||||||
return {
|
return {
|
||||||
"bytecode_index": frame.getByteCodeIndex(),
|
"bytecode_index": frame.getByteCodeIndex(),
|
||||||
"is_native": frame.isNativeMethod(),
|
"is_native": frame.isNativeMethod(),
|
||||||
"method": frame.getDeclaringClass().descriptorString() + "->" + frame.getMethodName() + frame.getDescriptor(),
|
"method": frame.getDeclaringClass().descriptorString() + "->" + frame.getMethodName() + frame.getDescriptor(),
|
||||||
"cl_id": System.identityHashCode(frame.getDeclaringClass().getClassLoader()),
|
"cl_id": System.identityHashCode(cl),
|
||||||
//{
|
//{
|
||||||
//"descriptor": frame.getDescriptor(),
|
//"descriptor": frame.getDescriptor(),
|
||||||
//"name": frame.getMethodName(),
|
//"name": frame.getMethodName(),
|
||||||
|
|
@ -170,11 +184,13 @@ Java.perform(() => {
|
||||||
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) {
|
||||||
|
let cl = this.getDeclaringClass().getClassLoader();
|
||||||
|
send_class_loader(cl);
|
||||||
send({
|
send({
|
||||||
"type": "invoke",
|
"type": "invoke",
|
||||||
"data": {
|
"data": {
|
||||||
"method": get_method_dsc(this),
|
"method": get_method_dsc(this),
|
||||||
"method_cl_id": System.identityHashCode(this.getDeclaringClass().getClassLoader()),
|
"method_cl_id": System.identityHashCode(cl),
|
||||||
/*{
|
/*{
|
||||||
"name": this.getName(),
|
"name": this.getName(),
|
||||||
"class": this.getDeclaringClass().getName(),
|
"class": this.getDeclaringClass().getName(),
|
||||||
|
|
@ -193,11 +209,13 @@ Java.perform(() => {
|
||||||
// Class.newInstance()
|
// Class.newInstance()
|
||||||
Class.newInstance.overload(
|
Class.newInstance.overload(
|
||||||
).implementation = function () {
|
).implementation = function () {
|
||||||
|
let cl = this.getClassLoader();
|
||||||
|
send_class_loader(cl);
|
||||||
send({
|
send({
|
||||||
"type": "class-new-inst",
|
"type": "class-new-inst",
|
||||||
"data": {
|
"data": {
|
||||||
"constructor": this.descriptorString() + "-><init>()V",
|
"constructor": this.descriptorString() + "-><init>()V",
|
||||||
"constructor_cl_id": System.identityHashCode(this.getClassLoader()),
|
"constructor_cl_id": System.identityHashCode(cl),
|
||||||
/*{
|
/*{
|
||||||
"name": "<init>",
|
"name": "<init>",
|
||||||
"class": this.getName(),
|
"class": this.getName(),
|
||||||
|
|
@ -215,11 +233,13 @@ Java.perform(() => {
|
||||||
Constructor.newInstance.overload(
|
Constructor.newInstance.overload(
|
||||||
"[Ljava.lang.Object;"
|
"[Ljava.lang.Object;"
|
||||||
).implementation = function (args) {
|
).implementation = function (args) {
|
||||||
|
let cl = this.getDeclaringClass().getClassLoader();
|
||||||
|
send_class_loader(cl);
|
||||||
send({
|
send({
|
||||||
"type": "cnstr-new-isnt",
|
"type": "cnstr-new-isnt",
|
||||||
"data": {
|
"data": {
|
||||||
"constructor": get_constr_dsc(this),
|
"constructor": get_constr_dsc(this),
|
||||||
"constructor_cl_id": System.identityHashCode(this.getDeclaringClass().getClassLoader()),
|
"constructor_cl_id": System.identityHashCode(cl),
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
"name": "<init>",
|
"name": "<init>",
|
||||||
|
|
@ -262,6 +282,7 @@ Java.perform(() => {
|
||||||
let classloader_class = null;
|
let classloader_class = null;
|
||||||
let classloader_id = System.identityHashCode(loader);
|
let classloader_id = System.identityHashCode(loader);
|
||||||
if (loader !== null) {
|
if (loader !== null) {
|
||||||
|
send_class_loader(loader);
|
||||||
classloader_class = loader.getClass().descriptorString();
|
classloader_class = loader.getClass().descriptorString();
|
||||||
}
|
}
|
||||||
send({
|
send({
|
||||||
|
|
@ -334,6 +355,7 @@ Java.perform(() => {
|
||||||
let classloader_id = System.identityHashCode(loader);
|
let classloader_id = System.identityHashCode(loader);
|
||||||
if (loader !== null) {
|
if (loader !== null) {
|
||||||
classloader_class = loader.getClass().descriptorString();
|
classloader_class = loader.getClass().descriptorString();
|
||||||
|
send_class_loader(loader);
|
||||||
}
|
}
|
||||||
send({
|
send({
|
||||||
"type": "load-dex",
|
"type": "load-dex",
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ name = "theseus-autopatcher"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = ""
|
description = ""
|
||||||
authors = [
|
authors = [
|
||||||
{name = "Jean-Marie 'Histausse' Mineau",email = "histausse@protonmail.com"}
|
{name = "Jean-Marie MINEAU",email = "jean-marie.mineau@centralesupelec.fr"}
|
||||||
]
|
]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.13,<4.0.0"
|
requires-python = ">=3.13,<4.0.0"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue