-
Notifications
You must be signed in to change notification settings - Fork 0
Implement basic Frida JSONL output and parser #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
3c3fce1
fda4892
c843822
b03c7bd
4c681df
28d28f9
24fe942
3c1bae7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| from typing import Union, Iterator | ||
| from pathlib import Path | ||
|
|
||
| from .models import FridaReport, Call | ||
| from models import FridaReport, Call | ||
| from capa.features.common import Feature, String, OS, Arch, Format | ||
| from capa.features.insn import API, Number | ||
| from capa.features.address import ( | ||
|
|
@@ -28,6 +28,9 @@ class FridaExtractor(DynamicFeatureExtractor): | |
| Processes JSON output from Frida instrumentation to extract behavioral features. | ||
| """ | ||
| def __init__(self, report: FridaReport): | ||
| # TODO: From what I’ve found, Frida cannot access original APK file to compute hashes at runtime. | ||
| # we may need to require users to provide both the Frida-generated log file and original file to capa, | ||
| # like we do with other extractors e.g. BinExport, VMRay, etc.. | ||
| super().__init__( | ||
| hashes=SampleHashes(md5="", sha1="", sha256="") | ||
| ) | ||
|
|
@@ -39,12 +42,27 @@ def get_base_address(self) -> Union[_NoAddress, None]: | |
|
|
||
| def extract_global_features(self) -> Iterator[tuple[Feature, Address]]: | ||
| """Basic global features""" | ||
| yield OS("android"), NO_ADDRESS | ||
| yield Arch("aarch64"), NO_ADDRESS | ||
| yield Format("android"), NO_ADDRESS | ||
| yield OS("android"), NO_ADDRESS # OS: Frida doesn't provide OS info | ||
|
|
||
| if self.report.processes: | ||
| process = self.report.processes[0] | ||
|
|
||
| if process.arch: | ||
| arch_mapping = { | ||
| "arm64": "aarch64", | ||
| "arm": "arm", | ||
| "x64": "amd64", | ||
| "x86": "i386" | ||
| } | ||
| capa_arch = arch_mapping.get(process.arch, process.arch) | ||
| yield Arch(capa_arch), NO_ADDRESS | ||
|
|
||
| if process.platform: | ||
| # TODO: capa doesn't have a dedicated FORMAT_ANDROID constant yet. | ||
|
||
| yield Format("android"), NO_ADDRESS | ||
|
|
||
| def extract_file_features(self) -> Iterator[tuple[Feature, Address]]: | ||
| """Baisc file features""" | ||
| """Basic file features""" | ||
| yield String(self.report.package_name), NO_ADDRESS | ||
|
|
||
| def get_processes(self) -> Iterator[ProcessHandle]: | ||
|
|
@@ -78,20 +96,24 @@ def get_calls(self, ph: ProcessHandle, th: ThreadHandle) -> Iterator[CallHandle] | |
| """Get all API calls in a specific thread""" | ||
| for i, call in enumerate(ph.inner.calls): | ||
xukunzh marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if call.thread_id == th.address.tid: | ||
| addr = DynamicCallAddress(thread=th.address, id=i) | ||
| addr = DynamicCallAddress(thread=th.address, id=call.call_id) | ||
| yield CallHandle(address=addr, inner=call) | ||
|
|
||
| def extract_call_features(self, ph: ProcessHandle, th: ThreadHandle, ch: CallHandle | ||
| ) -> Iterator[tuple[Feature, Address]]: | ||
| """Extract features from individual API calls""" | ||
| # TODO: Implement call feature extraction | ||
|
|
||
| # TODO: Implement call feature extraction from arguments and return value | ||
| call: Call = ch.inner | ||
|
|
||
| yield API(call.api_name), ch.address | ||
|
|
||
| def get_call_name(self, ph: ProcessHandle, th: ThreadHandle, ch: CallHandle) -> str: | ||
| """Format API call name and parameters""" | ||
| # TODO: Implement after extract_call_features agruments | ||
| call: Call = ch.inner | ||
|
|
||
| parts = [] | ||
| parts.append(call.api) | ||
| parts.append(call.api_name) | ||
| parts.append("(") | ||
|
|
||
| if call.arguments: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| {"id":0,"api":{"java_api":{"process_id":14881,"thread_id":14881,"call_id":0,"api_name":"java.io.File.<init>"}}} | ||
| {"id":1,"metadata":{"process_id":14881,"arch":"arm64","platform":"linux","package_name":"com.example.fridatestjavaapp"}} | ||
| {"id":2,"api":{"java_api":{"process_id":14881,"thread_id":14881,"call_id":1,"api_name":"java.io.File.<init>"}}} | ||
| {"id":3,"api":{"java_api":{"process_id":14881,"thread_id":14881,"call_id":2,"api_name":"java.io.File.<init>"}}} | ||
| {"id":4,"api":{"java_api":{"process_id":14881,"thread_id":14881,"call_id":3,"api_name":"java.io.FileOutputStream.write"}}} | ||
| {"id":5,"api":{"java_api":{"process_id":14881,"thread_id":14881,"call_id":4,"api_name":"java.io.File.<init>"}}} | ||
| {"id":6,"api":{"java_api":{"process_id":14881,"thread_id":14881,"call_id":5,"api_name":"java.io.File.<init>"}}} | ||
| {"id":7,"api":{"java_api":{"process_id":14881,"thread_id":14881,"call_id":6,"api_name":"java.io.FileInputStream.<init>(File)"}}} | ||
| {"id":8,"api":{"java_api":{"process_id":14881,"thread_id":14924,"call_id":7,"api_name":"java.io.File.<init>"}}} | ||
| {"id":9,"api":{"java_api":{"process_id":14881,"thread_id":14924,"call_id":8,"api_name":"java.io.FileInputStream.<init>(File)"}}} |
Uh oh!
There was an error while loading. Please reload this page.