4
4
import sys
5
5
import tempfile
6
6
7
- from blint .binary import parse
7
+ from blint .binary import parse , parse_dex
8
8
from blint .cyclonedx .spec import (
9
9
Component ,
10
10
ComponentEvidence ,
@@ -64,7 +64,7 @@ def exec_tool(args, cwd=None, stdout=subprocess.PIPE):
64
64
return None
65
65
66
66
67
- def collect_app_metadata (app_file ):
67
+ def collect_app_metadata (app_file , deep_mode ):
68
68
"""
69
69
Collect various metadata about an android app
70
70
"""
@@ -81,7 +81,7 @@ def collect_app_metadata(app_file):
81
81
parent_component .properties .append (
82
82
Property (name = "internal.appPermissions" , value = permissions )
83
83
)
84
- components = collect_files_metadata (app_file )
84
+ components = collect_files_metadata (app_file , parent_component , deep_mode )
85
85
return parent_component , components
86
86
87
87
@@ -257,7 +257,88 @@ def collect_so_files_metadata(app_file, app_temp_dir):
257
257
return file_components
258
258
259
259
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 ):
261
342
"""
262
343
Unzip the app and collect metadata
263
344
"""
@@ -266,6 +347,10 @@ def collect_files_metadata(app_file):
266
347
unzip_unsafe (app_file , app_temp_dir )
267
348
file_components += collect_version_files_metadata (app_file , app_temp_dir )
268
349
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
+ )
269
354
shutil .rmtree (app_temp_dir , ignore_errors = True )
270
355
return file_components
271
356
0 commit comments