From 8003547414abc0a8b86fe5ad13de8abda6899b9e Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Mon, 14 Aug 2023 10:13:42 +0000 Subject: [PATCH 1/3] elf: detect Android OS via note closes #1705 --- capa/features/extractors/elf.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/capa/features/extractors/elf.py b/capa/features/extractors/elf.py index c3305444b..922ca5b86 100644 --- a/capa/features/extractors/elf.py +++ b/capa/features/extractors/elf.py @@ -54,6 +54,7 @@ class OS(str, Enum): CLOUD = "cloud" SYLLABLE = "syllable" NACL = "nacl" + ANDROID = "android" # via readelf: https://github.com/bminor/binutils-gdb/blob/c0e94211e1ac05049a4ce7c192c9d14d1764eb3e/binutils/readelf.c#L19635-L19658 @@ -764,6 +765,11 @@ def guess_os_from_ph_notes(elf: ELF) -> Optional[OS]: elif note.name == "FreeBSD": logger.debug("note owner: %s", "FREEBSD") return OS.FREEBSD + elif note.name == "Android": + logger.debug("note owner: %s", "Android") + # see the following for parsing the structure: + # https://android.googlesource.com/platform/ndk/+/master/parse_elfnote.py + return OS.ANDROID elif note.name == "GNU": abi_tag = note.abi_tag if abi_tag: From 18058beb0a7018eeecaf418f87f2161751db0965 Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Mon, 14 Aug 2023 10:20:30 +0000 Subject: [PATCH 2/3] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc710aa8a..e28a2efac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - Fix binja backend stack string detection. #1473 @xusheng6 - linter: skip native API check for NtProtectVirtualMemory #1675 @williballenthin +- OS: detect Android ELF files #1705 @williballenthin ### capa explorer IDA Pro plugin - fix unhandled exception when resolving rule path #1693 @mike-hunhoff From e6cb3d3b3bd5a009347c51fec52f351bd77103ec Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Mon, 14 Aug 2023 10:27:19 +0000 Subject: [PATCH 3/3] os: detect Android via dependencies, too --- capa/features/extractors/elf.py | 2 ++ tests/fixtures.py | 2 ++ tests/test_os_detection.py | 12 ++++++++++++ 3 files changed, 16 insertions(+) diff --git a/capa/features/extractors/elf.py b/capa/features/extractors/elf.py index 922ca5b86..01662a124 100644 --- a/capa/features/extractors/elf.py +++ b/capa/features/extractors/elf.py @@ -861,6 +861,8 @@ def guess_os_from_needed_dependencies(elf: ELF) -> Optional[OS]: return OS.HURD if needed.startswith("libhurduser.so"): return OS.HURD + if needed.startswith("libandroid.so"): + return OS.ANDROID return None diff --git a/tests/fixtures.py b/tests/fixtures.py index 291ba1a89..a85656a6e 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -308,6 +308,8 @@ def get_data_path_by_name(name) -> Path: return CD / "data" / "2bf18d0403677378adad9001b1243211.elf_" elif name.startswith("ea2876"): return CD / "data" / "ea2876e9175410b6f6719f80ee44b9553960758c7d0f7bed73c0fe9a78d8e669.dll_" + elif name.startswith("1038a2"): + return CD / "data" / "1038a23daad86042c66bfe6c9d052d27048de9653bde5750dc0f240c792d9ac8.elf_" else: raise ValueError(f"unexpected sample fixture: {name}") diff --git a/tests/test_os_detection.py b/tests/test_os_detection.py index d5806d45c..a650165dd 100644 --- a/tests/test_os_detection.py +++ b/tests/test_os_detection.py @@ -80,6 +80,18 @@ def test_elf_symbol_table(): assert capa.features.extractors.elf.detect_elf_os(f) == "linux" +def test_elf_android_notes(): + # DEBUG:capa.features.extractors.elf:guess: osabi: None + # DEBUG:capa.features.extractors.elf:guess: ph notes: OS.ANDROID + # DEBUG:capa.features.extractors.elf:guess: sh notes: None + # DEBUG:capa.features.extractors.elf:guess: linker: None + # DEBUG:capa.features.extractors.elf:guess: ABI versions needed: None + # DEBUG:capa.features.extractors.elf:guess: needed dependencies: OS.ANDROID + path = get_data_path_by_name("1038a2") + with Path(path).open("rb") as f: + assert capa.features.extractors.elf.detect_elf_os(f) == "android" + + def test_elf_parse_capa_pyinstaller_header(): # error after misidentified large pydata section with address 0; fixed in #1454 # compressed ELF header of capa-v5.1.0-linux