Skip to content

Commit de264a3

Browse files
committed
Parse dex
Signed-off-by: Prabhu Subramanian <[email protected]>
1 parent 22d985d commit de264a3

File tree

4 files changed

+114
-8
lines changed

4 files changed

+114
-8
lines changed

blint/android.py

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import sys
55
import tempfile
66

7-
from blint.binary import parse
7+
from blint.binary import parse, parse_dex
88
from blint.cyclonedx.spec import (
99
Component,
1010
ComponentEvidence,
@@ -64,7 +64,7 @@ def exec_tool(args, cwd=None, stdout=subprocess.PIPE):
6464
return None
6565

6666

67-
def collect_app_metadata(app_file):
67+
def collect_app_metadata(app_file, deep_mode):
6868
"""
6969
Collect various metadata about an android app
7070
"""
@@ -81,7 +81,7 @@ def collect_app_metadata(app_file):
8181
parent_component.properties.append(
8282
Property(name="internal.appPermissions", value=permissions)
8383
)
84-
components = collect_files_metadata(app_file)
84+
components = collect_files_metadata(app_file, parent_component, deep_mode)
8585
return parent_component, components
8686

8787

@@ -257,7 +257,88 @@ def collect_so_files_metadata(app_file, app_temp_dir):
257257
return file_components
258258

259259

260-
def collect_files_metadata(app_file):
260+
def collect_dex_files_metadata(app_file, parent_component, app_temp_dir):
261+
file_components = []
262+
# Parse all .dex files
263+
dex_files = find_files(app_temp_dir, [".dex"])
264+
for adex in dex_files:
265+
dex_metadata = parse_dex(adex)
266+
name = os.path.basename(adex).removesuffix(".dex")
267+
rel_path = os.path.relpath(adex, app_temp_dir)
268+
group = (
269+
parent_component.group
270+
if parent_component and parent_component.group
271+
else ""
272+
)
273+
version = (
274+
parent_component.version
275+
if parent_component and parent_component.version
276+
else "latest"
277+
)
278+
purl = f"pkg:generic/{name}@{version}"
279+
component = Component(
280+
type=Type.file,
281+
group=group,
282+
name=name,
283+
version=version,
284+
purl=purl,
285+
scope=Scope.required,
286+
evidence=ComponentEvidence(
287+
identity=Identity(
288+
field=FieldModel.purl,
289+
confidence=0.5,
290+
methods=[
291+
Method(
292+
technique=Technique.binary_analysis,
293+
value=rel_path,
294+
confidence=0.5,
295+
)
296+
],
297+
)
298+
),
299+
properties=[
300+
Property(name="internal:srcFile", value=rel_path),
301+
Property(name="internal:appFile", value=app_file),
302+
Property(
303+
name="internal:header",
304+
value=", ".join(dex_metadata.get("header")),
305+
),
306+
Property(
307+
name="internal:functions",
308+
value=", ".join(dex_metadata.get("methods")),
309+
),
310+
Property(
311+
name="internal:classes",
312+
value=", ".join(dex_metadata.get("classes")),
313+
),
314+
Property(
315+
name="internal:fields",
316+
value=", ".join(dex_metadata.get("fields")),
317+
),
318+
Property(
319+
name="internal:strings",
320+
value=", ".join(dex_metadata.get("strings")),
321+
),
322+
Property(
323+
name="internal:types",
324+
value=", ".join(dex_metadata.get("types")),
325+
),
326+
Property(
327+
name="internal:prototypes",
328+
value=", ".join(dex_metadata.get("prototypes")),
329+
),
330+
Property(
331+
name="internal:map",
332+
value=", ".join(dex_metadata.get("map")),
333+
),
334+
],
335+
)
336+
component.bom_ref = RefType(purl)
337+
file_components.append(component)
338+
return file_components
339+
340+
341+
def collect_files_metadata(app_file, parent_component, deep_mode):
261342
"""
262343
Unzip the app and collect metadata
263344
"""
@@ -266,6 +347,10 @@ def collect_files_metadata(app_file):
266347
unzip_unsafe(app_file, app_temp_dir)
267348
file_components += collect_version_files_metadata(app_file, app_temp_dir)
268349
file_components += collect_so_files_metadata(app_file, app_temp_dir)
350+
if deep_mode:
351+
file_components += collect_dex_files_metadata(
352+
app_file, parent_component, app_temp_dir
353+
)
269354
shutil.rmtree(app_temp_dir, ignore_errors=True)
270355
return file_components
271356

blint/binary.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import sys
22

33
import lief
4-
from lief import ELF, PE, MachO
4+
from lief import DEX, ELF, PE, MachO
55

66
from blint.logger import LOG
77
from blint.utils import calculate_entropy, check_secret, decode_base64
@@ -1107,3 +1107,22 @@ def parse(exe_file):
11071107
except Exception as e:
11081108
LOG.exception(e)
11091109
return metadata
1110+
1111+
1112+
def parse_dex(dex_file):
1113+
"""Parse dex files"""
1114+
metadata = {"file_path": dex_file}
1115+
try:
1116+
dexfile_obj = DEX.parse(dex_file)
1117+
metadata["version"] = dexfile_obj.version
1118+
metadata["header"] = dexfile_obj.header
1119+
metadata["classes"] = dexfile_obj.classes
1120+
metadata["fields"] = dexfile_obj.fields
1121+
metadata["methods"] = dexfile_obj.methods
1122+
metadata["strings"] = dexfile_obj.strings
1123+
metadata["types"] = dexfile_obj.types
1124+
metadata["prototypes"] = dexfile_obj.prototypes
1125+
metadata["map"] = dexfile_obj.map
1126+
except Exception as e:
1127+
LOG.exception(e)
1128+
return metadata

blint/cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def main():
132132
sbom_output = args.sbom_output
133133
else:
134134
sbom_output = os.path.join(os.getcwd(), "bom.json")
135-
generate(src_dirs, sbom_output)
135+
generate(src_dirs, sbom_output, args.deep_mode)
136136
# Default case
137137
else:
138138
# Create reports directory

blint/sbom.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def default_metadata(src_dirs):
5353
return metadata
5454

5555

56-
def generate(src_dirs, output_file):
56+
def generate(src_dirs, output_file, deep_mode):
5757
android_files = []
5858
components = []
5959
dependencies = []
@@ -84,7 +84,9 @@ def generate(src_dirs, output_file):
8484
for f in android_files:
8585
dependencies_dict = {}
8686
progress.update(task, description=f"Processing [bold]{f}[/bold]")
87-
parent_component, app_components = collect_app_metadata(f)
87+
parent_component, app_components = collect_app_metadata(
88+
f, deep_mode
89+
)
8890
if parent_component:
8991
if not sbom.metadata.component.components:
9092
sbom.metadata.component.components = []

0 commit comments

Comments
 (0)