Skip to content

Commit

Permalink
Merge pull request #1720 from mandiant/fix/issue-1705
Browse files Browse the repository at this point in the history
elf: detect Android OS via note and dependencies
  • Loading branch information
williballenthin authored Aug 14, 2023
2 parents 7c1522d + e6cb3d3 commit 8479bc2
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions capa/features/extractors/elf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -855,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

Expand Down
2 changes: 2 additions & 0 deletions tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}")

Expand Down
12 changes: 12 additions & 0 deletions tests/test_os_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 8479bc2

Please sign in to comment.